“ SELECT TOP”效果问题


18

我有一个查询,使用select可以运行得更快,top 100而没有则要慢得多top 100。返回的记录数为0。能否解释查询计划中的差异或在解释差异的地方共享链接?

没有top文本的查询:

SELECT --TOP 100
*
FROM InventTrans
     JOIN
     InventDim
     ON InventDim.DATAAREAID = 'dat' AND 
        InventDim.INVENTDIMID = InventTrans.INVENTDIMID
WHERE InventTrans.DATAAREAID = 'dat' AND 
      InventTrans.ITEMID = '027743' AND 
      InventDim.INVENTLOCATIONID = 'КзРЦ Алмат' AND 
      InventDim.ECC_BUSINESSUNITID = 'Казахстан';

以上查询计划(不含top):

https://pastebin.com/cbtJpxFf

在此处输入图片说明

IO和TIME统计信息(无top):

SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

(0 row(s) affected)
Table 'INVENTDIM'. Scan count 0, logical reads 988297, physical reads 0, read-ahead reads 1, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'INVENTTRANS'. Scan count 1, logical reads 1234560, physical reads 0, read-ahead reads 14299, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

(1 row(s) affected)

 SQL Server Execution Times:
   CPU time = 6256 ms,  elapsed time = 13348 ms.
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

使用的索引(无top):

1. INVENTTRANS.I_177TRANSIDIDX
   4 KEYS:
 - DATAAREAID
 - INVENTTRANSID
 - INVENTDIMID
 - RECID
2. INVENTTRANS.I_177ITEMIDX
   3 KEYS:
   - DATAAREAID
   - ITEMID
   - DATEPHYSICAL 
3. INVENTDIM.I_698DIMIDIDX
   2 KEYS:
   - DATAAREAID
   - INVENTDIMID

查询top

SELECT TOP 100
*
FROM InventTrans
     JOIN
     InventDim
     ON InventDim.DATAAREAID = 'dat' AND 
        InventDim.INVENTDIMID = InventTrans.INVENTDIMID
WHERE InventTrans.DATAAREAID = 'dat' AND 
      InventTrans.ITEMID = '027743' AND 
      InventDim.INVENTLOCATIONID = 'КзРЦ Алмат' AND 
      InventDim.ECC_BUSINESSUNITID = 'Казахстан';

查询计划(带有TOP):

https://pastebin.com/0dyu6QZd

在此处输入图片说明


查询IO和TIME统计信息(带有TOP):

SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

(0 row(s) affected)
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'INVENTTRANS'. Scan count 15385, logical reads 82542, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'INVENTDIM'. Scan count 1, logical reads 62704, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

(1 row(s) affected)

 SQL Server Execution Times:
   CPU time = 265 ms,  elapsed time = 257 ms.
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

使用的索引(带有TOP):

 1. INVENTTRANS.I_177TRANSIDIDX
     4 KEYS:
     - DATAAREAID
     - INVENTTRANSID
     - INVENTDIMID
     - RECID
 2. INVENTTRANS.I_177DIMIDIDX
    3 KEYS:
    - DATAAREAID
    - INVENTDIMID
    - ITEMID
 3. INVENTDIM.I_698DIMIDIDX
    2 KEYS:
    - DATAAREAID
    - INVENTDIMID
 4. INVENTDIM.I_698ECC_BUSUNITLOCIDX
    3 KEYS
    - DATAAREAID
    - ECC_BUSINESSUNITID
    - INVENTLOCATIONID

非常感谢您对此主题的任何帮助!


2
我认为没有“ ORDER BY”的情况下“ TOP”的速度并不重要。正确的结果比速度更重要。
丹·古兹曼

Answers:


15

SQL Server使用不同的排序算法为TOP 100构建不同的执行计划。有时速度更快,有时速度更慢。

有关更简单的示例,请阅读一行可以更改查询计划多少?第1 部分第2部分

有关深入的技术细节,以及有关TOP 100算法实际上速度较慢的示例,请阅读Paul White的Sorting,Row Goals和TOP 100 Problem

底线:在您的情况下,如果您知道将不返回任何行,那么...不要运行查询,是吗?最快的查询是您从未做出过的查询。但是,如果需要进行存在性检查,只需执行IF EXISTS(在此处进行查询),然后SQL Server会制定一个甚至不同的执行计划。


谢谢,我一定会读的。我还注意到在两种情况下行估计都不正确。它可能与什么有关?统计信息是否良好-我已经在两个聚簇索引上使用fullscan选项对其进行了更新。
乔治·K

另外-因为我没有任何订单,是否适合我的情况,所以我认为我的计划中不会有SORT?
乔治·K

看看TOP 100和TOP 101的执行计划是否相同将是非常有趣的。如果可能,请分享。谢谢。
Artashes Khachatryan

@GeorgeK我可以看到您正在使用Dynamics AX。注意跟踪标志[ blogs.msdn.microsoft.com/axinthefield/…,这可能会导致很多估计问题。如果禁用了跟踪标志4136,请检查“分区”列是否在索引中是第一列。分区通常只有很少的不同值。
汉斯·维达

9

查看这两个计划,您将对这两个计划有一个关键的查找,它们的%成本相差很大。如果将鼠标悬停在对象上,将看到执行次数。

关键查找是对聚簇索引的查找,因为在索引查找(右上角)中使用的索引没有覆盖所有列(选择*因此必须使用聚簇索引)。

前100名能够从较少的索引中获取所需的100行,然后执行查找100次而不是对表中的每一行进行查找。还说明了不执行“顶部”操作时读取的页面数增加。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.