我正在努力调整我们生产 SQL Server 2016 SP2 上的一个查询。由于安全策略,我需要匿名化查询。查询是这样的:
SELECT TOP 1000 Object1.Column1,Object1.Column2,Object1.Column3,Object1.Column4,Object1.Column5,Object1.Column6,Object1.Column7,Object1.Column8,Object1.Column9,Object1.Column10,Object1.Column11,Object1.Column12,Object1.Column13,Object1.Column14,Object1.Column15,Object1.Column16,Object1.Column17,Object1.Column18,Object1.Column19,Object1.Column20,Object1.Column21,Object1.Column22,Object1.Column23,Object1.Column24,Object1.Column25,Object1.Column26,Object1.Column27,Object1.Column28,Object1.Column29,Object1.Column30,Object1.Column31,Object1.Column32,Object1.Column33,Object1.Column34,Object1.Column35,Object1.Column36,Object1.Column37,Object1.Column38,Object1.Column39,Object1.Column40,Object1.Column41,Object1.Column42,Object1.Column43,Object1.Column44,Object1.Column45,Object1.Column46,Object1.Column47,Object1.Column48,Object1.Column49,Object1.Column50,Object1.Column51,Object1.Column52
FROM Schema1.Object2 Object1
LEFT OUTER JOIN Schema1.Object3 Object4 ON Object4.Column3 = Object1.Column3
WHERE ((Object1.Column43 IS NULL OR Object1.Column43='') AND (Object4.Column54 = 0 OR Object4.Column54 IS NULL) AND Object1.Column3 = N'SomeValue')
ORDER BY Object1.Column3 ASC,Object1.Column8 ASC,Object1.Column7 ASC,Object1.Column12 ASC,Object1.Column13 ASC,Object1.Column1 ASC
可以在此处
找到实际的查询计划
正如您所见,在 Object2.Index1.Object1 上完成了索引搜索,但估计很糟糕。SQL Server 估计将返回 194907 行,但仅返回 710 行。
当我删除该ORDER BY
子句时,估计要好得多,SQL Server 预计只有 1181 行返回。该计划可以在这里找到。
我不明白为什么 anORDER BY
会影响索引搜索的估计。两个查询都使用相同的 column3 值运行。
有人可以向我解释一下吗?
这是一个最高值查询。ORDER BY 指定查询将返回哪1000 行。如果没有 ORDER BY,SQL Server 可以自由返回任何 1000。因此,一旦 SQL Server 从 Schema1.Object2 中有 1000 行符合 WHERE 子句的条件,它就可以停止。LEFT JOIN 不能减少行数。
具体来说,no-ORDER BY 计划在读取 Object2 时有一个行目标:
ORDER BY 计划没有。在确定要返回的 1000之前,它需要对所有过滤的行进行排序。