L'utilisation de DISTINCT comme indice dans les sous-requêtes est-elle utile?

18

L'ajout DISTINCTdans l'exemple suivant a-t-il un impact sur le temps d'exécution de la requête?
Est-il sage de l'utiliser parfois comme indice?

SELECT *
FROM   A
WHERE  A.SomeColumn IN (SELECT DISTINCT B.SomeColumn FROM B) 
Yosi Dahari
la source

Réponses:

25

Lorsque vous vous posez des questions sur ce sujet, vous devez comparer les plans d'exécution de vos requêtes.

La forme du plan d'exécution de votre requête variera bien sûr en fonction du nombre de lignes que vous avez dans vos tables et des index définis.
Un scénario qui montre qu'il n'y a pas de différence de performances est lorsqu'il y a beaucoup plus de lignes Aqu'il n'y en a B. L'optimiseur choisira alors Bcomme table de pilotage dans une jointure en boucle imbriquée A. Pour obtenir un résultat correct, il doit utiliser un agrégat de flux sur la table Bdans les deux requêtes pour obtenir uniquement les lignes distinctes B. Dans ce cas, le mot clé distinct n'a donc aucun impact sur les performances.

entrez la description de l'image ici

entrez la description de l'image ici

Le plan d'exécution pour deux autres cas évidents à tester, plus de lignes dans B que A et un nombre égal de lignes dans les tables, montre également exactement le même plan d'exécution pour les requêtes.

Mise à jour

Avant que l'optimisation de la requête n'ait lieu, la requête passe par une phase de simplification. Vous pouvez voir à quoi ressemble l'arborescence logique en utilisant l'indicateur de trace 8606.

L'arbre d'entrée pour les requêtes est clairement différent mais après simplification, il est le même.

Ref: Plus Undocumented Optimiseur de requête Flags Trace et Optimiseur de requête Deep Dive - Partie 2

Arborescence d'entrée et arborescence simplifiée pour la requête utilisant distinct:

*** Input Tree: ***
        LogOp_Project QCOL: [xx].[dbo].[A].SomeColumn
            LogOp_Select
                LogOp_Get TBL: A A TableID=213679909 TableReferenceID=0 IsRow: COL: IsBaseRow1002 
                ScaOp_SomeComp 2
                    ScaOp_Identifier QCOL: [xx].[dbo].[A].SomeColumn
                    LogOp_GbAgg OUT(QCOL: [xx].[dbo].[B].SomeColumn,) BY(QCOL: [xx].[dbo].[B].SomeColumn,)
                        LogOp_Project
                            LogOp_Project
                                LogOp_Get TBL: B B TableID=229679966 TableReferenceID=0 IsRow: COL: IsBaseRow1006 
                                AncOp_PrjList 
                            AncOp_PrjList 
                        AncOp_PrjList 
            AncOp_PrjList 
*******************
*** Simplified Tree: ***
        LogOp_LeftSemiJoin
            LogOp_Get TBL: A A TableID=213679909 TableReferenceID=0 IsRow: COL: IsBaseRow1002 
            LogOp_Get TBL: B B TableID=229679966 TableReferenceID=0 IsRow: COL: IsBaseRow1006 
            ScaOp_Comp x_cmpEq
                ScaOp_Identifier QCOL: [xx].[dbo].[A].SomeColumn
                ScaOp_Identifier QCOL: [xx].[dbo].[B].SomeColumn
*******************

Arborescence d'entrée et arborescence simplifiée pour la requête n'utilisant pas distinct:

*** Input Tree: ***
        LogOp_Project QCOL: [xx].[dbo].[A].SomeColumn
            LogOp_Select
                LogOp_Get TBL: A A TableID=213679909 TableReferenceID=0 IsRow: COL: IsBaseRow1002 
                ScaOp_SomeComp 2
                    ScaOp_Identifier QCOL: [xx].[dbo].[A].SomeColumn
                    LogOp_Project
                        LogOp_Get TBL: B B TableID=229679966 TableReferenceID=0 IsRow: COL: IsBaseRow1006 
                        AncOp_PrjList 
            AncOp_PrjList 
*******************
*** Simplified Tree: ***
        LogOp_LeftSemiJoin
            LogOp_Get TBL: A A TableID=213679909 TableReferenceID=0 IsRow: COL: IsBaseRow1002 
            LogOp_Get TBL: B B TableID=229679966 TableReferenceID=0 IsRow: COL: IsBaseRow1006 
            ScaOp_Comp x_cmpEq
                ScaOp_Identifier QCOL: [xx].[dbo].[A].SomeColumn
                ScaOp_Identifier QCOL: [xx].[dbo].[B].SomeColumn
*******************
Mikael Eriksson
la source