web-dev-qa-db-fra.com

Question de performance «SELECT TOP»

J'ai une requête qui s'exécute beaucoup plus rapidement avec select top 100 et beaucoup plus lent sans top 100. Le nombre d'enregistrements renvoyés est de 0. Pourriez-vous expliquer la différence dans les plans de requête ou partager des liens où cette différence est expliquée?

La requête sans top texte:

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 = 'Казахстан';

Le plan de requête pour ce qui précède (sans top):

https://Pastebin.com/cbtJpxFf

enter image description here

Les statistiques IO et TIME (sans 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.

Les index utilisés (sans 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

La requête avec 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 = 'Казахстан';

Le plan de requête (avec TOP):

https://Pastebin.com/0dyu6QZd

enter image description here


La requête IO et les statistiques TIME (avec 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.

Les index utilisés (avec 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

Appréciera profondément toute aide sur le sujet!

18
George K

SQL Server crée différents plans d'exécution pour TOP 100, à l'aide d'un algorithme de tri différent. Parfois, c'est plus rapide, parfois plus lent.

Pour des exemples plus simples, lisez Combien une ligne peut-elle changer un plan de requête? Partie 1 et Partie 2 .

Pour des détails techniques approfondis, ainsi qu'un exemple où l'algorithme TOP 100 est en fait plus lent, lisez Tri de Paul White, objectifs de ligne et problème TOP 1 .

L'essentiel: dans votre cas, si vous savez qu'aucune ligne ne sera retournée, eh bien ... ne lancez pas la requête, hein? La requête la plus rapide est celle que vous ne faites jamais. Cependant, si vous devez vérifier l'existence, faites simplement IF EXISTS (coller la requête ici), puis SQL Server fera un plan d'exécution encore différent.

15
Brent Ozar

En regardant les deux plans, vous avez une recherche clé sur les deux avec des% de coûts radicalement différents. Si vous passez la souris sur les objets, vous verrez le nombre d'exécutions.

La recherche de clé est une recherche de retour à l'index cluster car l'index utilisé dans la recherche d'index (en haut à droite) ne couvre pas toutes les colonnes (sélectionnez * pour que l'index cluster soit utilisé).

Le Top 100 est capable d'obtenir les 100 lignes nécessaires en moins de lectures à partir de l'index, puis d'effectuer la recherche 100 fois plutôt que pour chaque ligne du tableau. Explique également l'augmentation du nombre de pages lues lorsque vous ne faites pas le "top".

9
Simon Hellings