Performance em SQL com UNION

Dúvidas, dicas e truques de SQL, Select, Update, Delete, cláusulas, operações com joins, Funções em SQLs, etc
Diego_Mello
Rank: DBA Júnior
Rank: DBA Júnior
Mensagens: 229
Registrado em: Sex, 05 Set 2008 2:59 pm
Localização: Igrejinha - RS
Diego Mello
Igrejinha - RS
www.twitter.com/diegolmello

Buenas!
Galera, estou com um problema de performance em uma view.
Ela é gigante, mas podemos simular o gargalo na query a seguir.

Selecionar tudo

SQL> SELECT *
  2    FROM ( --/ View
  3          SELECT ao.object_name
  4            FROM all_objects ao
  5          UNION
  6          SELECT NULL
  7            FROM dual
  8          --/
  9          )
 10   WHERE object_name = 'V$SESSION';
 
OBJECT_NAME
------------------------------
V$SESSION
 
SQL> 
Essa query roda instantaneamente, porém preciso filtrar pelos registros retornados por outra tabela.

Ao adicionar essa nova tabela na query, o plano de execução muda completamente.
A tabela pode ser simulada também como uma query simples.

Selecionar tudo

SELECT *
  FROM ( --/ View
        SELECT ao.object_name
          FROM all_objects ao
        UNION
        SELECT NULL
          FROM dual
        --/
        )
 WHERE object_name IN (SELECT 'V$SESSION'
                         FROM dual);
Essa query não roda.
Alguém tem alguma ideia?

Abraço! ;)
PericlesAlmeida
Rank: Programador Júnior
Rank: Programador Júnior
Mensagens: 15
Registrado em: Ter, 01 Nov 2011 2:57 pm
"A falta de tempo é desculpa daqueles que perdem tempo por falta de método"
Albert Einstein

Tenta utilizar o UNION ALL caso não necessite de um DISTINCT entre as consultas e um EXISTS que normalmente é de maior desempenho que o IN.
DanielNN
Moderador
Moderador
Mensagens: 641
Registrado em: Seg, 03 Set 2007 3:26 pm
Localização: Fortaleza - CE
att,

Daniel N.N.

Se a query é gigante, dependendo de suas cláusulas, ela pode não usar corretamente os indices.
Além do que Pericles falou, se não melhorar, reveja as condições/restrições, verifique se você utiliza views no lugar de tabela, etc...
Diego_Mello
Rank: DBA Júnior
Rank: DBA Júnior
Mensagens: 229
Registrado em: Sex, 05 Set 2008 2:59 pm
Localização: Igrejinha - RS
Diego Mello
Igrejinha - RS
www.twitter.com/diegolmello

Pois é, cara.
O que o Pericles falou eu não tinha tentado ainda.
Funcionou para a minha simulação com a ALL_OBJECTS, mas não com a minha query.

Vou desenvolver melhor o meu problema:
Essa view é muito utilizada aqui na empresa.
Foi implementada uma nova solução em que os usuários vão usá-la filtrando muitos elementos para a mesma coluna.
Como o Oracle tem o limite de 1000 elementos no IN, criei uma tabela temporária.
É aí que meus problemas começam.

Quando utilizada com IN, a performance é excelente.
Quando a tabela é adicionada, o EXPLAIN PLAN muda completamente.

Experimenta fazer isso com tabelas do teu banco.
Pega duas tabelas grandes. Pedidos e itens são um bom exemplo.
Executa assim:

Selecionar tudo

SELECT *
  FROM (SELECT t1.coluna
          FROM tabela1 t1
              ,tabela2 t2
         WHERE t1.coluna = t2.coluna
        UNION
        SELECT NULL
          FROM dual)
 WHERE coluna IN (999999)
E executa assim:

Selecionar tudo

SELECT *
  FROM (SELECT t1.coluna
          FROM tabela1 t1
              ,tabela2 t2
         WHERE t1.coluna = t2.coluna
        UNION
        SELECT NULL
          FROM dual)
 WHERE coluna IN (SELECT 999999 -- Aqui vai minha tabela temp
                    FROM dual)
Na primeira query, o plano de execução vai estar perfeito.
Na segunda, o plano fará FULL.

Alguma sugestão?
DanielNN
Moderador
Moderador
Mensagens: 641
Registrado em: Seg, 03 Set 2007 3:26 pm
Localização: Fortaleza - CE
att,

Daniel N.N.

Entendi.
Acho que é semelhante ao que foi desenvolvido aqui com com um relatório gerencial.
Faziam filtros dos segmentos contábeis gravavam numa tabela um id único e cada valor de segmento para (empresa, filial, ccusto, conta...) e um relatório faz join com essas tabelas por esse id.
Esse relatório realmente não é bom de performace.

Porém noutro relatório com filtros semelhantes implementei de outra forma.
Existe um select padrão do relatório e um parametro onde insiro a coluna junto com o IN.

Selecionar tudo

Select ... from ...
where a = b
AND a.campox IN (MEU_PARAM1)
AND (MEU_PARAM2)
Neste meu MEU_PARAM1 incluo os valores separados por virgula , para os parametros que não possuem mais de mil filtros.
Já no MEU_PARAM2 insiro o campo + IN + filtros e uma verificação para não estourar os mil.
Ficando +/- asssim:

Selecionar tudo

Select ... from ...
where a = b
AND a.campox IN (.... , .... , ...)
"AND (a.campochato IN (........) OR a.campochato IN (........)  OR a.campochato IN (........) ".
Talvez seja necessario sql dinamico.
Trevisolli
Moderador
Moderador
Mensagens: 2016
Registrado em: Qua, 12 Jan 2005 3:25 pm
Localização: Araraquara - SP
Abraço,

Trevisolli
OCA Oracle PL/SQL Developer Certified Associate
OCP Oracle Forms Developer Certified Professional
Araraquara-SP

Brother,

Uma dica: Caso criou essa tabela que vai processar no "IN", tente colocá-la como JOIN da tua tabela principal, ao invés de tratá-la no IN.
qualquer coisa, manda pra gente.
Diego_Mello
Rank: DBA Júnior
Rank: DBA Júnior
Mensagens: 229
Registrado em: Sex, 05 Set 2008 2:59 pm
Localização: Igrejinha - RS
Diego Mello
Igrejinha - RS
www.twitter.com/diegolmello

Acontece a mesma coisa.
Tentei com JOIN, com EXISTS, com IN, com vários hints e nada funfou.
O que eu não queria era fazer a solução do Noctifero, mas não teve outro jeito.
Fiz daquela forma e bombou.
Valeu a dica.

Se alguém tiver mais alguma ideia, posta aí e eu digo se funciona ou não.

Abraço :-o
DanielNN
Moderador
Moderador
Mensagens: 641
Registrado em: Seg, 03 Set 2007 3:26 pm
Localização: Fortaleza - CE
att,

Daniel N.N.

Opa Diego,

Não é a forma mais prática mas tem suas vantagens. Só não sei se entendi bem seu:
Fiz daquela forma e bombou.
você implementou do jeito que falei e deu certo? (bombou to na duvida se foi bem ou explodiu o banco, hehehehe).
Diego_Mello
Rank: DBA Júnior
Rank: DBA Júnior
Mensagens: 229
Registrado em: Sex, 05 Set 2008 2:59 pm
Localização: Igrejinha - RS
Diego Mello
Igrejinha - RS
www.twitter.com/diegolmello

aeuahuehauehaue
Vou correr o risco de parecer que não entendi a ironia, mas responderei igual...
Deu certo ;-)
Responder
  • Informação
  • Quem está online

    Usuários navegando neste fórum: Nenhum usuário registrado e 13 visitantes