Question de performance «SELECT TOP»


18

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

La requête sans toptexte:

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

entrez la description de l'image ici

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

entrez la description de l'image ici


Les statistiques de requête IO et 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!


2
Je ne pense pas que la vitesse de «TOP» sans «ORDER BY» soit importante. Des résultats corrects sont plus importants que la vitesse.
Dan Guzman

Réponses:


15

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 de lignes peuvent être modifiées dans 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 réellement plus lent, lisez le tri, les objectifs de ligne et le problème TOP 100 de Paul White .

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.


Merci, je vais certainement le lire. J'ai également remarqué que les estimations des lignes sont incorrectes dans les deux scénarios. À quoi pourrait-il être lié? Les statistiques sont bonnes - je l'ai mis à jour avec l'option fullscan sur les deux index clusterisés.
George K

Aussi - est-ce approprié dans mon cas car je n'ai pas de COMMANDE, donc je crois qu'il n'y aura pas de TRI dans mon plan?
George K

Il sera très intéressant de voir si le plan d'exécution est le même pour le TOP 100 et le TOP 101. Si c'est possible, merci de partager. Merci.
Artashes Khachatryan

@GeorgeK Je peux voir que vous utilisez Dynamics AX. Méfiez-vous des indicateurs de trace [ blogs.msdn.microsoft.com/axinthefield/… qui peuvent entraîner de nombreux problèmes d'estimation. Si l'indicateur de trace 4136 est désactivé, vérifiez si la colonne "Partition" est la première de vos index. La partition a généralement très peu de valeurs distinctes.
Hans Vader

9

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 vers l'index clusterisé car l'index utilisé dans la recherche d'index (en haut à droite) ne couvre pas toutes les colonnes (sélectionnez * pour que l'index clusterisé soit utilisé).

Le Top 100 est capable d'obtenir les 100 lignes nécessaires en moins de lectures 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».

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.