Czy używanie DISTINCT jako wskazówki w podkwerendach jest przydatne?

18

Czy dodanie DISTINCTw poniższym przykładzie ma wpływ na czas wykonywania zapytania?
Czy czasem warto używać go jako podpowiedzi?

SELECT *
FROM   A
WHERE  A.SomeColumn IN (SELECT DISTINCT B.SomeColumn FROM B) 
Yosi Dahari
źródło

Odpowiedzi:

25

Zastanawiając się nad takimi rzeczami, powinieneś porównać plany wykonania swoich zapytań.

Kształt planu wykonania zapytania będzie się oczywiście różnić w zależności od liczby wierszy w tabelach i zdefiniowanych indeksów.
Jednym ze scenariuszy, który pokazuje, że nie ma różnicy w wydajności jest sytuacja, gdy jest znacznie więcej wierszy Aniż jest w B. Optymalizator następnie wybierze Bstół sterujący w zagnieżdżonej pętli sprzężenia z A. Aby odzyskać poprawny wynik, musi użyć tabeli agregacji strumienia Bw obu zapytaniach, aby uzyskać tylko odrębne wiersze B. W tym przypadku odrębne słowo kluczowe nie ma wpływu na wydajność.

wprowadź opis zdjęcia tutaj

wprowadź opis zdjęcia tutaj

Plan wykonania dla dwóch innych oczywistych przypadków do przetestowania, więcej wierszy w B niż A i równa liczba wierszy w tabelach, pokazuje również dokładnie ten sam plan wykonania dla zapytań.

Aktualizacja

Przed optymalizacją zapytania zapytanie przechodzi przez fazę uproszczenia. Możesz zobaczyć, jak wygląda drzewo logiczne, używając flagi śledzenia 8606.

Drzewo wprowadzania zapytań jest wyraźnie różne, ale po uproszczeniu są takie same.

Zobacz: Więcej nieudokumentowanych flag śledzenia i flagi śledzenia głębokiego nurkowania - część 2

Drzewo wejściowe i drzewo uproszczone dla zapytania przy użyciu odrębnych:

*** 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
*******************

Drzewo wejściowe i drzewo uproszczone dla zapytania nie używającego odrębnego:

*** 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
źródło