TOP性能问题

时间:2016-03-08 08:48:45

标签: sql sql-server

我有这个查询,实际上它与此类似,这是出于测试目的:

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]

这是它的执行计划:

enter image description here

当我从查询中删除TOP 10时,我得到了这个执行计划:

enter image description here

没有TOP 10的第二个执行计划快2倍,有人可以解释为什么TOP会更改执行计划以及为什么这么慢?即使查询没有返回任何结果也是一样的,不应该仅仅应用于结果集,为什么当查询什么都没有返回时它会对性能产生如此大的影响?

3 个答案:

答案 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次查找,但远比三次查找要贵得多。