none
Melhorar performance RRS feed

  • Pergunta

  • Ajuda para melhorar consulta... a tabela com os dados originais é igual essa ai abaixo

    Esses são os dados originais

    quarta-feira, 30 de janeiro de 2019 19:56

Respostas

  • Boa noite,

    Douglas, não sei se vai melhorar mas segue uma sugestão para testes:

    SELECT
        CA.PONTO_SERVICO_AGUA,
        CA.TOTAL_SITUACAO_PSA
    FROM MXL01..WFM_CLIENTE w
    cross apply
    (
        select 
            w.PONTO_SERVICO_AGUA_1 AS PONTO_SERVICO_AGUA, 
            w.TOTAL_SITUACAO_PSA_1 AS TOTAL_SITUACAO_PSA
        WHERE 
            w.PONTO_SERVICO_AGUA_1 IS NOT NULL
    
        UNION
    
        select 
            w.PONTO_SERVICO_AGUA_2, 
            w.TOTAL_SITUACAO_PSA_2
        WHERE 
            w.PONTO_SERVICO_AGUA_2 IS NOT NULL
    
        UNION
    
        select 
            w.PONTO_SERVICO_AGUA_3, 
            w.TOTAL_SITUACAO_PSA_3
        WHERE 
            w.PONTO_SERVICO_AGUA_3 IS NOT NULL
    
        UNION
    
        select 
            w.PONTO_SERVICO_AGUA_4, 
            w.TOTAL_SITUACAO_PSA_4 
        WHERE 
            w.PONTO_SERVICO_AGUA_4 IS NOT NULL
    ) ca
    WHERE
        w.ID_CLIENTE = 221311

    Espero que ajude


    Assinatura: http://www.imoveisemexposicao.com.br

    • Marcado como Resposta Ddev13 quinta-feira, 31 de janeiro de 2019 10:30
    quinta-feira, 31 de janeiro de 2019 01:40
  • Observe que na última linha do seu segundo código a cláusula WHERE deve ser revista com relação ao filtro.

    No segundo código que você postou, me parece que a performance será boa caso exista índice de cobertura pela coluna ID_CLIENTE.

    O código deve retornar somente um cliente de cada vez?

    Das 4 colunas de PONTO_SERVICO_AGUA, ao menos uma está com informação em cada linha?

    Eis sugestão para avaliar localmente se é melhor ou pior do que a solução que você utiliza atualmente:

    -- código #1
    with 
    -- gera 4 linhas para cada linha original
    CLIENTE_4 as (
    SELECT W.ID_CLIENTE, N.I,
           W.PONTO_SERVICO_AGUA_1, W.PONTO_SERVICO_AGUA_2,
           W.PONTO_SERVICO_AGUA_3, W.PONTO_SERVICO_AGUA_4,
           W.TOTAL_SITUACAO_PSA_1, W.TOTAL_SITUACAO_PSA_2,
           W.TOTAL_SITUACAO_PSA_3, W.TOTAL_SITUACAO_PSA_4
      from MXL01..WFM_CLIENTE as W
           cross join (values (1), (2), (3), (4)) as N (I)
      where W.ID_CLIENTE = ____
    ),
    -- simula unpivot
    CLIENTE_4_U as (
    SELECT ID_CLIENTE, I,
           case I when 1 then coalesce (PONTO_SERVICO_AGUA_1, '') 
                  when 2 then PONTO_SERVICO_AGUA_2 
                  when 3 then PONTO_SERVICO_AGUA_3 
                  when 4 then PONTO_SERVICO_AGUA_4 
           end as PONTO_SERVICO_AGUA,
           case I when 1 then TOTAL_SITUACAO_PSA_1 
                  when 2 then TOTAL_SITUACAO_PSA_2
                  when 3 then TOTAL_SITUACAO_PSA_3
                  when 4 then TOTAL_SITUACAO_PSA_4
           end as TOTAL_SITUACAO_PSA
      from CLIENTE_4
    )
    --
    SELECT ID_CLIENTE, PONTO_SERVICO_AGUA, TOTAL_SITUACAO_PSA
      from CLIENTE_4_U
      where PONTO_SERVICO_AGUA <> ''; 

    Não testei; espero que não tenha erro(s).

    Sugiro que analise os planos de execução para comparar a performance das soluções. Detalhes no artigo “O Plano Perfeito”.


    José Diz     Belo Horizonte, MG - Brasil     [Linked In]   [e-mail]   [Porto SQL]


    Este conteúdo é fornecido sem garantias de qualquer tipo, seja expressa ou implícita.

    • Editado José Diz quinta-feira, 31 de janeiro de 2019 00:00
    • Marcado como Resposta Ddev13 quinta-feira, 31 de janeiro de 2019 10:30
    quarta-feira, 30 de janeiro de 2019 23:50

Todas as Respostas

  • e hoje eu retorno os dados dessa forma

    Gostaria de saber se tem outra forma melhor de fazer isso

    quarta-feira, 30 de janeiro de 2019 19:57
  • Observe que na última linha do seu segundo código a cláusula WHERE deve ser revista com relação ao filtro.

    No segundo código que você postou, me parece que a performance será boa caso exista índice de cobertura pela coluna ID_CLIENTE.

    O código deve retornar somente um cliente de cada vez?

    Das 4 colunas de PONTO_SERVICO_AGUA, ao menos uma está com informação em cada linha?

    Eis sugestão para avaliar localmente se é melhor ou pior do que a solução que você utiliza atualmente:

    -- código #1
    with 
    -- gera 4 linhas para cada linha original
    CLIENTE_4 as (
    SELECT W.ID_CLIENTE, N.I,
           W.PONTO_SERVICO_AGUA_1, W.PONTO_SERVICO_AGUA_2,
           W.PONTO_SERVICO_AGUA_3, W.PONTO_SERVICO_AGUA_4,
           W.TOTAL_SITUACAO_PSA_1, W.TOTAL_SITUACAO_PSA_2,
           W.TOTAL_SITUACAO_PSA_3, W.TOTAL_SITUACAO_PSA_4
      from MXL01..WFM_CLIENTE as W
           cross join (values (1), (2), (3), (4)) as N (I)
      where W.ID_CLIENTE = ____
    ),
    -- simula unpivot
    CLIENTE_4_U as (
    SELECT ID_CLIENTE, I,
           case I when 1 then coalesce (PONTO_SERVICO_AGUA_1, '') 
                  when 2 then PONTO_SERVICO_AGUA_2 
                  when 3 then PONTO_SERVICO_AGUA_3 
                  when 4 then PONTO_SERVICO_AGUA_4 
           end as PONTO_SERVICO_AGUA,
           case I when 1 then TOTAL_SITUACAO_PSA_1 
                  when 2 then TOTAL_SITUACAO_PSA_2
                  when 3 then TOTAL_SITUACAO_PSA_3
                  when 4 then TOTAL_SITUACAO_PSA_4
           end as TOTAL_SITUACAO_PSA
      from CLIENTE_4
    )
    --
    SELECT ID_CLIENTE, PONTO_SERVICO_AGUA, TOTAL_SITUACAO_PSA
      from CLIENTE_4_U
      where PONTO_SERVICO_AGUA <> ''; 

    Não testei; espero que não tenha erro(s).

    Sugiro que analise os planos de execução para comparar a performance das soluções. Detalhes no artigo “O Plano Perfeito”.


    José Diz     Belo Horizonte, MG - Brasil     [Linked In]   [e-mail]   [Porto SQL]


    Este conteúdo é fornecido sem garantias de qualquer tipo, seja expressa ou implícita.

    • Editado José Diz quinta-feira, 31 de janeiro de 2019 00:00
    • Marcado como Resposta Ddev13 quinta-feira, 31 de janeiro de 2019 10:30
    quarta-feira, 30 de janeiro de 2019 23:50
  • Boa noite,

    Douglas, não sei se vai melhorar mas segue uma sugestão para testes:

    SELECT
        CA.PONTO_SERVICO_AGUA,
        CA.TOTAL_SITUACAO_PSA
    FROM MXL01..WFM_CLIENTE w
    cross apply
    (
        select 
            w.PONTO_SERVICO_AGUA_1 AS PONTO_SERVICO_AGUA, 
            w.TOTAL_SITUACAO_PSA_1 AS TOTAL_SITUACAO_PSA
        WHERE 
            w.PONTO_SERVICO_AGUA_1 IS NOT NULL
    
        UNION
    
        select 
            w.PONTO_SERVICO_AGUA_2, 
            w.TOTAL_SITUACAO_PSA_2
        WHERE 
            w.PONTO_SERVICO_AGUA_2 IS NOT NULL
    
        UNION
    
        select 
            w.PONTO_SERVICO_AGUA_3, 
            w.TOTAL_SITUACAO_PSA_3
        WHERE 
            w.PONTO_SERVICO_AGUA_3 IS NOT NULL
    
        UNION
    
        select 
            w.PONTO_SERVICO_AGUA_4, 
            w.TOTAL_SITUACAO_PSA_4 
        WHERE 
            w.PONTO_SERVICO_AGUA_4 IS NOT NULL
    ) ca
    WHERE
        w.ID_CLIENTE = 221311

    Espero que ajude


    Assinatura: http://www.imoveisemexposicao.com.br

    • Marcado como Resposta Ddev13 quinta-feira, 31 de janeiro de 2019 10:30
    quinta-feira, 31 de janeiro de 2019 01:40
  • José, valeu vou usar a sua solução, o pessoal aqui não gosta muito de usar union o DBA  fala que union perde performance
    quinta-feira, 31 de janeiro de 2019 10:32
  • Gapimex, obrigado, a sua solução usa union igual a minha e o pessoal aqui não curti muito isso não, embora pra mim não muda muita coisa
    quinta-feira, 31 de janeiro de 2019 10:33
  • José, valeu vou usar a sua solução, o pessoal aqui não gosta muito de usar union o DBA  fala que union perde performance

    Douglas, o código #1 é somente uma proposta. O ideal é analisar localmente os planos de execução das opções, para decidir qual é mais eficiente.

    No segundo código que você postou sugiro que substitua UNION por UNION ALL; isso melhorará a execução, ao eliminar operador intermediário SORT (Distinct sort), desnecessário nesse caso.

    A sugestão do "gapimex" também é interessante, ao utilizar o CROSS APPLY, desde que substitua UNION por UNION ALL. Observe que dentro da subconsulta CROSS APPLY não há cláusula FROM.  Mágica!  rs


    José Diz     Belo Horizonte, MG - Brasil     [Linked In]   [e-mail]   [Porto SQL]


    Este conteúdo é fornecido sem garantias de qualquer tipo, seja expressa ou implícita.
    • Editado José Diz sexta-feira, 1 de fevereiro de 2019 00:03
    quinta-feira, 31 de janeiro de 2019 10:50