none
Duvida o que é melhor distinct ou group by RRS feed

  • Pergunta

  • Gostaria de saber qual é mais eficiente, se é que existe alguma diferença:

    select distinct tbA.Percentual from tbA

    ou

    select tbA.Percentual from tbA group by
    tbA.Percentual
    terça-feira, 6 de janeiro de 2009 18:11

Respostas

  • Boa Tarde,

     

    Até onde sei (pelo menos seguindo os fundamentos de banco de dados e não as implementações de cada fabricante), os algoritmos de DISTINCT e GROUP BY são idênticos em suas fases iniciais seguindo primeiro uma ordenação e posterior eliminação de repetições. A diferença entre os algoritmos é que o GROUP BY permite funções de agregação como um passo adicional enquanto que o DISTINCT não permite. Quando se utiliza o GROUP BY sem essas funções, estaremos "repetindo" exatamente as fases iniciais que o DISTINCT utiliza. Vou exemplificar, suponha os seguintes registros:

     

    1 - DF

    2 - DF

    3 - RJ

    4 - SP

    5 - AM

    6 - SP

    7 - RJ

    8 - DF

     

    Para que as repetições possam ser eliminadas, o primeiro passo é fazer uma ordenação, pois, saberemos que o próximo valor será sempre maior que o primeiro, e que quando o valor for repetido, um novo grupo será formado:

     

    1 - AM

    2 - DF

    3 - DF

    4 - DF

    5 - RJ

    6 - RJ

    7 - SP

    8 - SP

     

    Agora basta aplicar um algoritmo bem simples:

     

    Para cada valor

    {

    Se o valor não apareceu

    {

    Cadastre-o

    }

    }

     

    Dessa forma, ao passar pelo registro 1, AM será cadastrada no Buffer de saída. Ao passar pelo registro 2, DF será cadastrado no Buffer de saída. Ao passar pelo registro 3, veremos que o último registro DF já existe e nada será feito. O mesmo irá se repetir no registro 4. Quando o registro 5 for lido, basta ler apenas o último registro no Buffer (DF) e tem-se a certeza de que ainda não existe registros RJ, pois, uma ordenação foi feita anteriormente. RJ será incluída no Buffer e o registro 6 será excluído. O mesmo comportamento será avaliado para os registros 7 e 8 (SP).

     

    Quando utilizamos o GROUP BY, o algoritmo é exatamente o mesmo. A única diferença é que juntamente com a avaliação é feita a agregação. Ex:

     

    Para cada valor

    {

    Se o valor não apareceu

    {

    Cadastre-o

    }

    Se o valor apareceu

    {

    Contabilize o grupo com uma função de agregação (SUM, COUNT, MAX, etc)

    }

    }

     

    Se fizermos o GROUP BY sem funções de agregação, estaremos desprezando a segundo condição do algoritmo e um resultado idêntico ao algoritmo do DISTINCT será produzido. Isso evidencia que "teoricamente" os dois algoritmos produzem exatamente o mesmo resultado com o mesmo custo (e é por isso que usar DISTINCT e GROUP BY é um senhor desperdício).

     

    Você poderá evidenciar isso através do plano de execução. Se você executar as consultas abaixo, verá que seus pares tem exatamente o mesmo plano de execução (rodei no AdventureWorks)

     

    Code Snippet

    SELECT DISTINCT Schema_ID FROM sys.all_objects

    SELECT Schema_ID FROM sys.all_objects GROUP BY Schema_ID

     

    SELECT DISTINCT CustomerID FROM sales.salesorderheader

    SELECT CustomerID FROM sales.salesorderheader GROUP BY CustomerID

     

     

    O primeiro exemplo não possui um índice sobre Schema_ID e o trabalho de ordenação é um pouco mais complicado. O segundo já possui um índice sobre CustomerID e nesse caso o índice é utilizado. Independente disso, você pode notar que os planos de execução são idênticos.

     

    Por uma questão de clareza, eu recomendo utilizar o DISTINCT, pois, esse operador normalmente é utilizado para eliminar repetições. Essa informação pode ser confirmada em:

     

    "Sistemas de Banco. de Dados", 4ª ed., Pearson Addison Wesley, São Paulo-. SP, 2005. Hector Garcia-Molina, Jeffrey D. Ullman, Jennifer D. Widom.

     

    Como disse, eu tive como base os fundamentos e não as implementações. Não sei há alguma razão para que o SQL Server faça distinção entre o DISTINCT e o GROUP BY. O Fabiano é um entusiasta da área de tuning e planos de execução. Talvez ele tenha alguma consideração.

     

    [ ]s,

     

    Gustavo

    terça-feira, 6 de janeiro de 2009 21:07
    Moderador
  • Oi Gustavo, creio que não tenha mais nenhuma consideração a fazer, ao meu ver Distinct e Group By são iguais, apenas com a diferença que o Group By pode calcular um valor agregado(MAX, MIN, etc...) ou não.

    Inclusive este assunto já foi abordado aqui no forum.

    http://forums.microsoft.com/MSDN-BR/ShowPost.aspx?PostID=4127666&SiteID=21

    quarta-feira, 7 de janeiro de 2009 10:28

Todas as Respostas

  • Fomachi,

     

    A claúsulua distinct é utilizar para impedir a exibição de registros similares.

     

    Já a cláusula Group By é utilizado para criar um agrupamento de valores, permitindo utilizar funções para sumarização de dados.

     

    Agrupa um conjunto de linhas selecionadas em um conjunto de linhas de resumo pelos valores de uma ou mais colunas ou expressões. Uma linha é retornada para cada grupo. Funções de agregação na lista de <seleção> da cláusula SELECT fornecem informações sobre cada grupo em vez de linhas individuais.

    A cláusula GROUP BY tem uma sintaxe de conformidade ISO e uma sintaxe de não conformidade ISO. Só um estilo de sintaxe pode ser usado em uma instrução SELECT única. Use a sintaxe de conformidade ISO para todo o novo trabalho. A sintaxe de não conformidade ISO é fornecida para compatibilidade com versões anteriores.

    Neste tópico, uma cláusula GROUP BY pode ser descrita como geral ou simples:

    • Uma cláusula GROUP BY geral inclui GROUPING SETS, CUBE, ROLLUP, WITH CUBE ou WITH ROLLUP.

    • Uma cláusula GROUP BY simples não inclui GROUPING SETS, CUBE, ROLLUP, WITH CUBE nem WITH ROLLUP. GROUP BY (), total geral, é considerado um GROUP BY simples.

    Em relação a performance isso deve depender a maneira que você esta trabalhando, mas basicamente, se você imaginar que quando utilizamos o Group By, o SQL Server deverá fazer análise e agrupar os valores desejar, acredito que esta procedimento possa consumir mais tempo de processamento, não possa afirmar temos que testar.

    terça-feira, 6 de janeiro de 2009 18:19
  • Boa Tarde,

     

    Até onde sei (pelo menos seguindo os fundamentos de banco de dados e não as implementações de cada fabricante), os algoritmos de DISTINCT e GROUP BY são idênticos em suas fases iniciais seguindo primeiro uma ordenação e posterior eliminação de repetições. A diferença entre os algoritmos é que o GROUP BY permite funções de agregação como um passo adicional enquanto que o DISTINCT não permite. Quando se utiliza o GROUP BY sem essas funções, estaremos "repetindo" exatamente as fases iniciais que o DISTINCT utiliza. Vou exemplificar, suponha os seguintes registros:

     

    1 - DF

    2 - DF

    3 - RJ

    4 - SP

    5 - AM

    6 - SP

    7 - RJ

    8 - DF

     

    Para que as repetições possam ser eliminadas, o primeiro passo é fazer uma ordenação, pois, saberemos que o próximo valor será sempre maior que o primeiro, e que quando o valor for repetido, um novo grupo será formado:

     

    1 - AM

    2 - DF

    3 - DF

    4 - DF

    5 - RJ

    6 - RJ

    7 - SP

    8 - SP

     

    Agora basta aplicar um algoritmo bem simples:

     

    Para cada valor

    {

    Se o valor não apareceu

    {

    Cadastre-o

    }

    }

     

    Dessa forma, ao passar pelo registro 1, AM será cadastrada no Buffer de saída. Ao passar pelo registro 2, DF será cadastrado no Buffer de saída. Ao passar pelo registro 3, veremos que o último registro DF já existe e nada será feito. O mesmo irá se repetir no registro 4. Quando o registro 5 for lido, basta ler apenas o último registro no Buffer (DF) e tem-se a certeza de que ainda não existe registros RJ, pois, uma ordenação foi feita anteriormente. RJ será incluída no Buffer e o registro 6 será excluído. O mesmo comportamento será avaliado para os registros 7 e 8 (SP).

     

    Quando utilizamos o GROUP BY, o algoritmo é exatamente o mesmo. A única diferença é que juntamente com a avaliação é feita a agregação. Ex:

     

    Para cada valor

    {

    Se o valor não apareceu

    {

    Cadastre-o

    }

    Se o valor apareceu

    {

    Contabilize o grupo com uma função de agregação (SUM, COUNT, MAX, etc)

    }

    }

     

    Se fizermos o GROUP BY sem funções de agregação, estaremos desprezando a segundo condição do algoritmo e um resultado idêntico ao algoritmo do DISTINCT será produzido. Isso evidencia que "teoricamente" os dois algoritmos produzem exatamente o mesmo resultado com o mesmo custo (e é por isso que usar DISTINCT e GROUP BY é um senhor desperdício).

     

    Você poderá evidenciar isso através do plano de execução. Se você executar as consultas abaixo, verá que seus pares tem exatamente o mesmo plano de execução (rodei no AdventureWorks)

     

    Code Snippet

    SELECT DISTINCT Schema_ID FROM sys.all_objects

    SELECT Schema_ID FROM sys.all_objects GROUP BY Schema_ID

     

    SELECT DISTINCT CustomerID FROM sales.salesorderheader

    SELECT CustomerID FROM sales.salesorderheader GROUP BY CustomerID

     

     

    O primeiro exemplo não possui um índice sobre Schema_ID e o trabalho de ordenação é um pouco mais complicado. O segundo já possui um índice sobre CustomerID e nesse caso o índice é utilizado. Independente disso, você pode notar que os planos de execução são idênticos.

     

    Por uma questão de clareza, eu recomendo utilizar o DISTINCT, pois, esse operador normalmente é utilizado para eliminar repetições. Essa informação pode ser confirmada em:

     

    "Sistemas de Banco. de Dados", 4ª ed., Pearson Addison Wesley, São Paulo-. SP, 2005. Hector Garcia-Molina, Jeffrey D. Ullman, Jennifer D. Widom.

     

    Como disse, eu tive como base os fundamentos e não as implementações. Não sei há alguma razão para que o SQL Server faça distinção entre o DISTINCT e o GROUP BY. O Fabiano é um entusiasta da área de tuning e planos de execução. Talvez ele tenha alguma consideração.

     

    [ ]s,

     

    Gustavo

    terça-feira, 6 de janeiro de 2009 21:07
    Moderador
  • Oi Gustavo, creio que não tenha mais nenhuma consideração a fazer, ao meu ver Distinct e Group By são iguais, apenas com a diferença que o Group By pode calcular um valor agregado(MAX, MIN, etc...) ou não.

    Inclusive este assunto já foi abordado aqui no forum.

    http://forums.microsoft.com/MSDN-BR/ShowPost.aspx?PostID=4127666&SiteID=21

    quarta-feira, 7 de janeiro de 2009 10:28
  • Obrigado a todos, desculpe ter postado uma duvida que já havia sido discutida.

    Eu havia procurado antes no forum mas não tinha encontrado sobre o assunto.
    quarta-feira, 7 de janeiro de 2009 11:30