É útil usar o DISTINCT como dica nas subconsultas?

18

A adição DISTINCTno exemplo a seguir tem algum impacto no tempo de execução da consulta?
É aconselhável usá-lo como uma dica às vezes?

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

Respostas:

25

Ao se perguntar sobre coisas como essa, você deve comparar os planos de execução para suas consultas.

É claro que a forma do plano de execução da sua consulta varia dependendo de quantas linhas você tem em suas tabelas e de quais índices são definidos.
Um cenário que mostra que não há diferença no desempenho é quando há substancialmente mais linhas do Aque em B. O otimizador escolherá Bcomo a tabela de controle em uma junção aninhada contra A. Para obter um resultado correto, ele precisa usar um Stream Aggregate na tabela Bem ambas as consultas para obter apenas as linhas distintas B. Portanto, nesse caso, a palavra-chave distinta não afeta o desempenho.

insira a descrição da imagem aqui

insira a descrição da imagem aqui

O plano de execução para dois outros casos óbvios para testar, mais linhas em B que A e número igual de linhas nas tabelas, também mostra exatamente o mesmo plano de execução para as consultas.

Atualizar

Antes da otimização da consulta, a consulta passa por uma fase de simplificação. Você pode ver como é a árvore lógica usando o sinalizador de rastreamento 8606.

A Árvore de Entrada para as consultas é claramente diferente, mas após a simplificação elas são as mesmas.

Ref: Mais sinalizadores de rastreamento do Query Optimizer não documentados e Deep Dive do Query Optimizer - Parte 2

Árvore de entrada e árvore simplificada para consulta usando distintas:

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

Árvore de entrada e árvore simplificada para consulta que não usa distintas:

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