Deparei-me com um problema em que precisei usar o operador OR. Ela está demorando mais de 1min para ser executada.
Ex com OR (01min:26s):
SELECT * FROM TABELA1 T1
INNER JOIN TABELA2 T2...
WHERE T1.FOO = 'A' OR T2.BAR = 'A'
Ex com UNION (6s):
SELECT * FROM TABELA1 T1
INNER JOIN TABELA2 T2...
WHERE T1.FOO = 'A'
UNION
SELECT * FROM TABELA1 T1
INNER JOIN TABELA2 T2...
WHERE T2.BAR = 'A'
Lendo o artigo no site da ORACLE https://blogs.oracle.com/optimizer/entry/or_expansion_transformation ele indicou realmente o uso do UNION ou a criação de índices para os campos em questão.
Meu problema: a query em questão é bem grande e é criada dinamicamente por causa de filtros inseridos pelo usuário.
Qual seriam minhas possibilidades? Realmente ter que usar o UNION e ter 2 queries enormes duplicadas, ou tentar agilizar os índices?
Alguém já deve ter passado por isso também…
[quote=tiagofaustino]Deparei-me com um problema em que precisei usar o operador OR. Ela está demorando mais de 1min para ser executada.
Ex com OR (01min:26s):
SELECT * FROM TABELA1 T1
INNER JOIN TABELA2 T2...
WHERE T1.FOO = 'A' OR T2.BAR = 'A'
Ex com UNION (6s):
SELECT * FROM TABELA1 T1
INNER JOIN TABELA2 T2...
WHERE T1.FOO = 'A'
UNION
SELECT * FROM TABELA1 T1
INNER JOIN TABELA2 T2...
WHERE T2.BAR = 'A'
Lendo o artigo no site da ORACLE https://blogs.oracle.com/optimizer/entry/or_expansion_transformation ele indicou realmente o uso do UNION ou a criação de índices para os campos em questão.
Meu problema: a query em questão é bem grande e é criada dinamicamente por causa de filtros inseridos pelo usuário.
Qual seriam minhas possibilidades? Realmente ter que usar o UNION e ter 2 queries enormes duplicadas, ou tentar agilizar os índices?
Alguém já deve ter passado por isso também…
[/quote]
se forem feitas muitas inserções nessa tabela eu diria “boa sorte” para você montar essa query dinâmica na unha… caso contrário acho que a criação de índices seja mais vantajosa…
vivendo e aprendendo, eu nunca tinha parado para pensar que fazer um union com praticamente a mesma query mudando só o filtro do or desse jeito seria mais performático, até que tem sentido quando o resto da query seja rápido e o filtro que é usado no or demore…
O Oracle não tem problemas com queries enormes. Faça a query enorme, se você souber que é mais rápida. Nem sempre é possível “agilizar os índices”.
A minha preocupação nem era com o Oracle, e sim eu ter que ter que concatenar os filtros dinamicamente, e com mais uma query grandona, piora as coisas. Ai fico pensando: no meu caso só tenho uma aparição de OR, imagina se tivessem outras? Seriam várias queries com UNION! Tenso isso, aí só com índices mesmo.
Mas enfim, eu temia que teria que fazer isso, só vim aqui para me certificar se havia uma possibilidade menos traumática. Não tendo, mãos à obra, fazer o que. Rs.
[quote=tiagofaustino][quote=entanglement]
O Oracle não tem problemas com queries enormes. Faça a query enorme, se você souber que é mais rápida. Nem sempre é possível “agilizar os índices”.
[/quote]
A minha preocupação nem era com o Oracle, e sim eu ter que ter que concatenar os filtros dinamicamente, e com mais uma query grandona, piora as coisas. Ai fico pensando: no meu caso só tenho uma aparição de OR, imagina se tivessem outras? Seriam várias queries com UNION! Tenso isso, aí só com índices mesmo.
Mas enfim, eu temia que teria que fazer isso, só vim aqui para me certificar se havia uma possibilidade menos traumática. Não tendo, mãos à obra, fazer o que. Rs.[/quote]
olha, sendo bem franco, a parte do que falei quanto a usar algum índice para resolver isso, assumindo que vai resolver mesmo, é pro que sei que nestes casos de queries dinâmicas montadas no código, é comum se ter uns códigos macarronicos e soluções do tipo funcionou não mecha… se der pra fazer o union e não ficar muito ruim de fazer é a indicação…
O UNION demora mais pois ele elimina implicitamente as linhas duplicadas. É como se usasse o DISTINCT, que deixa query um pouco mais lenta, dependendo da massa de dados trabalhada.
Caso não seja necessário a eliminação das linhas duplicadas, você pode usar o UNION ALL.
[quote=FabricioPJ]O UNION demora mais pois ele elimina implicitamente as linhas duplicadas. É como se usasse o DISTINCT, que deixa query um pouco mais lenta, dependendo da massa de dados trabalhada.
Caso não seja necessário a eliminação das linhas duplicadas, você pode usar o UNION ALL.[/quote]
O artigo que citei acima fala do uso do UNION ALL junto do LNNVL(). Eu nem sabia da existência desse segundo. Vou estudar melhor esta forma de fazer depois…
Ex. citado no artigo:
Select *
From products
Where prod_subcategory ='Camera Media'
UNION ALL
Select *
From products
Where prod_category ='Photo'
And LNNVL(prod_subcategory ='Camera Media');
[quote=FabricioPJ]O UNION demora mais pois ele elimina implicitamente as linhas duplicadas. É como se usasse o DISTINCT, que deixa query um pouco mais lenta, dependendo da massa de dados trabalhada.
Caso não seja necessário a eliminação das linhas duplicadas, você pode usar o UNION ALL.[/quote]
O artigo que citei acima fala do uso do UNION ALL junto do LNNVL(). Eu nem sabia da existência desse segundo. Vou estudar melhor esta forma de fazer depois…
Ex. citado no artigo:
Select *
From products
Where prod_subcategory ='Camera Media'
UNION ALL
Select *
From products
Where prod_category ='Photo'
And LNNVL(prod_subcategory ='Camera Media');