单一条件大幅减慢 SQL 查询速度

Posted

技术标签:

【中文标题】单一条件大幅减慢 SQL 查询速度【英文标题】:Single condition slows down SQL query drastically 【发布时间】:2013-03-15 04:22:23 【问题描述】:

我有一个如下所示的 SQL 查询:

WITH RES_CTE AS
  (SELECT
  COLUMN1,
  COLUMN2,
  [MORE COLUMNS...]
  ROW_NUMBER() OVER (ORDER BY R.RANKING DESC) AS RowNum 
  FROM TABLE1 As R, TABLE2 As A, TABLE3 As U, TABLE4 As S, TABLE5 As T 
  WHERE R.RID = A.LID 
  AND S.QRYID = R.QRYID
  AND A.AID = U.AID
  AND CONDITION1 = 'VALUE'
  AND CONDITION2 = 'VALUE'
  AND [MORE CONDITIONS...]
),
Results_Cnt AS 
  (SELECT COUNT(*) CNT FROM Results_CTE)
SELECT * FROM Results_CTE, Results_Cnt WHERE RowNum >= 1 AND RowNum <= 25

现在,此查询通常在 1 秒内运行,并返回基于 CONDITION1 的 5000 条记录中的 25 条记录。

不过,最近,我向TABLE1 添加了一个新列,然后在上面的查询中将其值用作CONDITION2。该列将继续填充,但过去的所有值都是NULL

我在加入表上方阅读了一些内容,其中 NULL 是执行缓慢的原因。该表有大约 1,300,000 条记录。其中 90% 是有问题的列中的NULL。但是该列没有被加入。 (正在加入的那个有一个INDEX

但是,无论如何,我还是想尝试通过创建一个新列并像这样简单地复制数据:

ALTER TABLE TABLE1 ADD COL_NEW
UPDATE TABLE1 SET COL_NEW = COL_OLD

我的下一步是用实际值替换 NULL,但首先,只是为了好玩,我将查询更改为使用新字段 COL_NEW 作为条件,然后问题就消失了。

虽然我很高兴问题消失了,但我无法向自己解释。如果它与 NULL 无关,为什么首先执行缓慢?

更新:问题似乎是由缓存的查询计划引起的。所以问题本质上变成了,如何强制刷新查询计划?

UPDATE:虽然做ALTER TABLE可能刷新了执行计划,但问题又回来了。我怎样才能知道发生了什么?

【问题讨论】:

能否请您发布查询执行计划?例如。 SET SHOWPLAN_ALL ON go --My SQL Query go SET SHOWPLAN_ALL OFF gO 【参考方案1】:

听起来您的查询计划已被缓存,而新列的统计信息显示它完全充满了空值,从而强制进行表扫描。在 ALTER TABLE 之后,查询计划被刷新,再次用索引 lookujp 替换表扫描,性能恢复正常。

确定是否发生了这种情况的唯一方法是检查两个查询的查询计划,但现在这些计划早已不复存在。

【讨论】:

你说早已不复存在,我说备份 :) 但是我不明白下次我想向表中添加一列时我应该做些什么不同的事情,并且有很多 NULL 进入那里? 表扫描是指查询从集群索引的第 1 条记录开始,并扫描所有记录到集群索引的末尾。索引查找是当查询进入索引以获取所需的第一个记录时,并且仅在需要读取查询所需的所有记录时才通过索引。如果 SQL Server 估计必须读取 > 10% 的表记录,则通常会执行表 san。查询计划被缓存而不记录,因此备份不会检索旧的。 我所说的备份是指性能不佳的 AWS AMI。 你可以强制刷新一个查询计划,虽然我刚才忘记了这个命令。重建表统计信息将具有相同的效果,但可能需要等待维护窗口。 问题又来了。它是间歇性发生的。我怎样才能知道发生了什么?

以上是关于单一条件大幅减慢 SQL 查询速度的主要内容,如果未能解决你的问题,请参考以下文章

SORT 的成本正在减慢我的查询速度

在某些情况下,为什么CTE(公用表表达式)与SQL Server中的临时表相比会减慢查询速度

为啥没有聚合的结束 Group By 会减慢我的查询速度?

当计划中未使用该索引时,为什么在SQL Server中添加索引会减慢查询速度?

条件语句会减慢着色器的速度吗?

为啥有些列会减慢查询速度