由于 where 子句中的 <>,查询耗时过长
Posted
技术标签:
【中文标题】由于 where 子句中的 <>,查询耗时过长【英文标题】:Query takes too long because of <> in where clause 【发布时间】:2021-11-13 20:42:03 【问题描述】:我正在构建一个通过电子邮件发送的脚本。我有一张交易表,我只想在状态为 "failed" 时通过电子邮件发送。该表现在有大约 5000 万行,并且会不断增加,我无法存档。
这是查询:
if exists (select top 1 1 from TicketTransactionDetails where ServiceStatus != 0)
begin
DECLARE @tablehtml NVARCHAR(MAX) ;
SET @tableHTML =
N'<H1>Transactions Status</H1>' +
N'<table border="1">' +
N'<tr><th>TransactionDate</th><th>NbOfRecords</th>' +
N'<th>ServiceStatus</th><th>StatusDescription</th><th>RunDate</th></tr>' +
CAST ( (select td = CAST(InsertDate as date), '',
td = COUNT(*),'',
td = ServiceStatus,'',
td = b.StatusDescription,'',
td = GETDATE()
from TicketTransactionDetails a
inner join ServiceStatuses b on a.ServiceStatus = b.StatusID
where ServiceStatus = 0
group by CAST(InsertDate as date),ServiceStatus,b.StatusDescription
order by CAST(InsertDate as date) desc
FOR XML PATH('tr'), TYPE
) AS NVARCHAR(MAX) ) +
N'</table>' ;
exec msdb.dbo.sp_send_dbmail
@profile_name = 'DB_Maintenance',
@recipients = 'a.a@a.a',
@subject = 'Tranzanctions with errors',
@body = @tableHTML,
@body_format = 'html';
end
执行(约 25 秒)需要很多时间的是:
select top 1 1 from TicketTransactionDetails where ServiceStatus != 0
有没有办法改进我的查询?
非常感谢。
【问题讨论】:
您需要提供表定义、索引定义和执行计划(使用“粘贴计划”)以获得性能建议。 如果您没有关于 ServiceStatus 的索引肯定从那里开始,您也可以尝试用大于比较替换您的 != 比较,假设这适用于 ServiceStatus 值。使用“不等于”的查询可能会很慢。 正确的索引可能就是您所需要的。事实上,SSMS 甚至可能会向您推荐它。 您的代码对我来说似乎有缺陷。您首先检查ServiceStatus != 0
,但您的查询过滤器为ServiceStatus = 0
。
"Tranzanctions" != 我使用的语言中的 "Transactions"。
【参考方案1】:
你可以做几件事 -
首先,检查ServiceStatus
列是否有索引。如果没有,则创建它。确实应该这样做。
虽然有风险,但另一个选择是在查询中添加 (nolock) 提示。这将绕过表上持有的任何锁
select top 1 1 from TicketTransactionDetails (nolock) where ServiceStatus != 0
【讨论】:
将nolock
用于消息队列听起来是个非常糟糕的主意。
感谢您的指点。列上没有索引。我会用索引看看它是如何工作的,我确实不希望使用 nolock
如果你也推荐NOLOCK
,你应该强调使用这种提示的所有后果,这样OP就不会变得讨厌当他们获得的数据不是他们期望的数据时,他们会感到惊讶。
不要不推荐nolock
我已经建立了一个索引,但它并不完美。谢谢大家【参考方案2】:
改用count,count的表现比top好很多
if exists (select count(1) from TicketTransactionDetails where ServiceStatus != 0)
【讨论】:
以上是关于由于 where 子句中的 <>,查询耗时过长的主要内容,如果未能解决你的问题,请参考以下文章
Linq to Entities 中的动态 where 子句 (OR)
SQL语句中,为啥where子句不能使用列别名,而order by却可以?