Полезно ли использовать DISTINCT в качестве подсказки в подзапросах?

18

Влияет ли добавление DISTINCTв следующем примере на время выполнения запроса?
Разумно ли использовать это как подсказку иногда?

SELECT *
FROM   A
WHERE  A.SomeColumn IN (SELECT DISTINCT B.SomeColumn FROM B) 
Йоси Дахари
источник

Ответы:

25

Задаваясь вопросом о таких вещах, вы должны сравнить планы выполнения ваших запросов.

Форма плана выполнения для вашего запроса, конечно, будет отличаться в зависимости от того, сколько строк в ваших таблицах и какие индексы определены.
Один сценарий, который показывает, что нет разницы в производительности, - это когда строк значительно больше, Aчем в B. Затем оптимизатор выберет Bв качестве таблицы управления объединение вложенных циклов A. Чтобы получить верный результат, он должен использовать агрегат потока в таблице Bв обоих запросах, чтобы получить только отдельные строки B. Таким образом, в этом случае отдельное ключевое слово не влияет на производительность.

введите описание изображения здесь

введите описание изображения здесь

План выполнения для двух других очевидных случаев тестирования: больше строк в B, чем A и равное количество строк в таблицах, также показывает точно такой же план выполнения для запросов.

Обновить

Перед оптимизацией запроса он проходит фазу упрощения. Вы можете увидеть, как выглядит логическое дерево, используя флаг трассировки 8606.

Дерево ввода для запросов явно отличается, но после упрощения они совпадают.

Ref: Дополнительные флаги Незарегистрированные Оптимизатор запросов трассировки и оптимизатор запросов Deep Dive - Часть 2

Дерево ввода и упрощенное дерево для запроса с использованием различных:

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

Дерево ввода и упрощенное дерево для запроса, не использующего различные:

*** 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
*******************
Микаэль Эрикссон
источник