我有这个查询,实际上它与此类似,这是出于测试目的:
SELECT
[Distinct1].[ProspectID] AS [ProspectID]
FROM ( SELECT DISTINCT
[Limit1].[ProspectID] AS [ProspectID]
FROM ( SELECT TOP 10
[Extent1].[ProspectID] AS [ProspectID]
FROM [sqlsolvent].[crm_SearchTable] AS [Extent1]
WHERE ([Extent1].[CP_Name] LIKE '%dsd%' ESCAPE N'~')
) AS [Limit1]
) AS [Distinct1]
这是它的执行计划:
当我从查询中删除TOP 10
时,我得到了这个执行计划:
没有TOP 10
的第二个执行计划快2倍,有人可以解释为什么TOP会更改执行计划以及为什么这么慢?即使查询没有返回任何结果也是一样的,不应该仅仅应用于结果集,为什么当查询什么都没有返回时它会对性能产生如此大的影响?
答案 0 :(得分:2)
请注意,查询中存在错误 - top
必须与一些显式排序一起使用,否则结果的排序是未定义的,因此top
本身的结果是未定义。
我不能肯定地告诉你发生了什么,但强加显式排序可能会更好地理解你的结果 - 要么它允许更合理的执行计划,要么它会使你的“无首”查询变慢。
在任何情况下,您在执行distinct之前都会强制执行排序和限制。虽然您的无顶查询可以使用索引来执行distinct
(在整个表中),但是当您使用top
时,这些查询将不再可用,尤其是因为您的过滤器不允许使用任何index(like '%whatever%'
是一种杀死性能的好方法:))。由于您distinct
所在的列是聚簇索引,因此distinct
实际上非常便宜 - 只要您可以使用该索引。
总而言之,我将了解两个查询如何使用更多数据执行。减速可能会变成一个带有大量实际数据的加速 - 很难猜测这些事情:)
答案 1 :(得分:2)
第二个查询被拆分为并行流,这取决于计算机配置,将提高性能。 TOP运算符不会这样做,因为它试图获得所需的行数,直到满足TOP条件,而不是所有行。
如果您的where子句是严格的,则表扫描需要扫描更多的表,直到满足TOP条件。如果你的where子句不严格(例如它匹配总行数的很大一部分),那么使用TOP的查询可能比没有TOP的查询更快。
答案 2 :(得分:1)
您可以参考提供解决方法的support article from Microsoft
解决方法强>
要解决此问题,请制作一个收集TOP N的查询 每个分区的元素。然后,从中找到TOP N元素 元素集合。
您可以参考此article获取详细信息:
当由SELECT运算符调用时,Top运算符调用Nested 循环操作员获取一行;将它返回给SELECT运算符;和 然后等待直到再次调用 - 这通常会 发生得相当快,除非SELECT运算符必须等待 应用程序或网络发送出来的行。同样的事情发生了两件事 更多次,但当SELECT运算符调用Top运算符时 第四次,Top运营商将立即返回“结束 数据“条件没有经常打扰它的后代嵌套 循环节点。无论SalesOrderHeader表有多少行, TOP条款保证永远不会超过三个 查找。我们在第一个计划中的Sort运算符比它便宜 31,465次查找,但远比三次查找要贵得多。