none
Performance Consulta RRS feed

  • Pergunta

  • Pessoal tenho que melhora a seguinte consulta:

    SELECT p.idproduct,
           p.name,
           p.iddepto,
           p.idcategory,
           p.idsubcategoria,
           p.idsite,
           p.domain,
           p.quantity - p.reserved AS RealQuantity,
           p.price,
           p.idmanufactor,
           p.datacadastro,
           p.preco_promocional,
           pb.busdescricao,
           pb.idicone,
           pb.maisvendidos
    FROM   dbo.productsbusca AS pb
           INNER JOIN dbo.products AS p
                   ON pb.idproduct = p.idproduct
    WHERE  ( p.del <> 1 )
           AND ( p.domain <> 10 )
    UNION
    SELECT pc.idproduct,
           p.name,
           pc.iddepto,
           pc.idcategory,
           pc.idsubcategoria,
           pc.idsite,
           p.domain,
           p.quantity - p.reserved AS RealQuantity,
           p.price,
           p.idmanufactor,
           p.datacadastro,
           p.preco_promocional,
           pb.busdescricao,
           pb.idicone,
           pb.maisvendidos
    FROM   dbo.productsbusca AS pb
           INNER JOIN dbo.products AS p
                   ON pb.idproduct = p.idproduct
           INNER JOIN dbo.vprcprodutoscategorizacao AS pc
                   ON pc.idproduct = p.idproduct
    WHERE  ( p.del <> 1 )
           AND ( p.domain <> 10 )
    UNION
    SELECT p.idproduct,
           p.name,
           p.iddepto,
           p.idcategory,
           p.idsubcategoria,
           p.idsite,
           p.domain,
           p.quantity - p.reserved            AS RealQuantity,
           p.price,
           p.idmanufactor,
           p.datacadastro,
           p.preco_promocional,
           dbo.apelidoproduto.apelido         AS busDescricao,
           dbo.viconeproduto.id               AS IDIcone,
           dbo.vmaisvendidos.somadequantidade AS MaisVendidos
    FROM   dbo.products AS p
           INNER JOIN dbo.apelidoproduto
                   ON p.idproduct = dbo.apelidoproduto.idproduct
           LEFT OUTER JOIN dbo.vmaisvendidos
                        ON p.idproduct = dbo.vmaisvendidos.idproduct
           LEFT OUTER JOIN dbo.viconeproduto
                        ON p.idproduct = dbo.viconeproduto.idproduct
    WHERE  ( p.del <> 1 )
           AND ( p.domain <> 10 ) 

    Pelo plano de execução, o maior recurso esta em um sort ( Distinct Sort), não entendi da onde esta saindo este sort !!!

    OBS : Quando eu executo apenas a primeira parte do select ( ate o ponto do union) o recurso consumido é 68% index scan e 26% em um merge join, alguem tem alguma sugestão ???

    sexta-feira, 15 de junho de 2012 15:38

Respostas

  • DBA BH, Boa tarde!

    O Distinct Sort está sendo provocado pelo uso do UNION.

    A utilização do UNION o SQL Server automáticamente desconsidera os registros duplicados no resultset como no DISTINCT. Por isso, que o SORT é executado. Caso você queira evitar o uso do SORT, tente substituir o UNION por UNION ALL, porém atente-se que neste caso, não será mais efetuado o distinct dos dados e você pode passar a ter dados repetidos no retorno da query.

    Segue exemplo e referências:

    http://blog.sqlauthority.com/2009/03/11/sql-server-difference-between-union-vs-union-all-optimal-performance-comparison/

    USE tempdb
    GO
    If Exists(	SELECT * FROM sys.tables
    			WHERE NAME LIKE 'TesteUNION')
    Begin
    	DROP TABLE TesteUNION 
    End
    GO
    CREATE TABLE TesteUNION (Descricao varchar(50))
    INSERT INTO TesteUNION VALUES ('Descricao A')
    INSERT INTO TesteUNION VALUES ('Descricao B')
    INSERT INTO TesteUNION VALUES ('Descricao C')
    -- UNION utiliza o SORT e desconsidera os registros duplcados
    SELECT * FROM TesteUNION
    UNION 
    SELECT * FROM TesteUNION
    -- UNION não utiliza o SORT e retorna também os registros duplcados
    SELECT * FROM TesteUNION
    UNION ALL
    SELECT * FROM TesteUNION


    Espero que ajude! Luiz Phellipe

    domingo, 17 de junho de 2012 15:57

Todas as Respostas

  • DBA BH, Boa tarde!

    O Distinct Sort está sendo provocado pelo uso do UNION.

    A utilização do UNION o SQL Server automáticamente desconsidera os registros duplicados no resultset como no DISTINCT. Por isso, que o SORT é executado. Caso você queira evitar o uso do SORT, tente substituir o UNION por UNION ALL, porém atente-se que neste caso, não será mais efetuado o distinct dos dados e você pode passar a ter dados repetidos no retorno da query.

    Segue exemplo e referências:

    http://blog.sqlauthority.com/2009/03/11/sql-server-difference-between-union-vs-union-all-optimal-performance-comparison/

    USE tempdb
    GO
    If Exists(	SELECT * FROM sys.tables
    			WHERE NAME LIKE 'TesteUNION')
    Begin
    	DROP TABLE TesteUNION 
    End
    GO
    CREATE TABLE TesteUNION (Descricao varchar(50))
    INSERT INTO TesteUNION VALUES ('Descricao A')
    INSERT INTO TesteUNION VALUES ('Descricao B')
    INSERT INTO TesteUNION VALUES ('Descricao C')
    -- UNION utiliza o SORT e desconsidera os registros duplcados
    SELECT * FROM TesteUNION
    UNION 
    SELECT * FROM TesteUNION
    -- UNION não utiliza o SORT e retorna também os registros duplcados
    SELECT * FROM TesteUNION
    UNION ALL
    SELECT * FROM TesteUNION


    Espero que ajude! Luiz Phellipe

    domingo, 17 de junho de 2012 15:57
  • Luiz,

    Valeu pela ajuda, realmente eu percebi esta diferença, porem eu preciso da retirada de registros duplicados.

    Teria alguma sugestão de melhoria de performance mantendo o union ??

    segunda-feira, 18 de junho de 2012 11:07