Páginas

▼

13 de jun. de 2022

Otimizando SQLs com comparações de negação



Olá pessoal,


     No post de hoje quero apenas compartilhar um dica simples, mas muito útil, que mostro nos meus treinamentos de SQL Tuning: Evite comparações de negação NOT EQUAL (!= ou <>) ou NOT IN para viabilizar o uso de índices b-tree. Se não for possível evitá-los avalie o uso de índices BITMAP. 

     De um modo geral devemos evitar comparações de negação sempre que possível, e por que devemos evitá-las? Porque se você tiver um índice do tipo b-tree na coluna em que a comparação de negação for utilizada, normalmente ele será ignorado, e por que isso ocorre? Porque segundo a Oracle (consultar última versão do Oracle SQL Tuning Guide) índices do tipo B-tree são ótimos para serem criados em colunas com alta cardinalidade visando otimizar consultas que retornam poucos dados, em média quando a seletividade é de até 4% do total de linhas das tabelas envolvidas. Mais que isso normalmente o índice b-tree deixará de ser eficiente, então o otimizador irá preferir realizar uma operação de FULL TABLE SCAN (ao invés de INDEX SCAN). Quando há uma comparação de negação, normalmente a seletividade será maior que 4%, por esse motivo, "quase sempre" o otimizador irá ignorar índices do tipo B-tree. É importante ressaltar, porém, que existem (pouquíssimos) casos em que o btree pode ser usado até mesmo numa comparação de negação, mas como isso raramente irá acontecer, é necessário pensar em outra solução para otimizar SQLs desse tipo. Uma alternativa é criar um índice do tipo BITMAP, ao invés de B-tree. O Bitmap pode atender perfeitamente essa necessidade, porém ele possui outras desvantagens, como por exemplo, ter um tempo de atualização extremamente alto, o que normalmente inviabiliza o seu uso em ambientes OLTP. Ele é ótimo para ambientes OLAP!

     Veja na "Imagem 01" que criei um índice B-tree na coluna ID_STATUS da tabela ECOMMERCE.PEDIDO, e em seguida verifiquei o plano de execução de um SELECT que filtra dados na coluna ID_STATUS através de uma comparação de negação. Neste caso podemos verificar na "Imagem 02" que o índice foi ignorado.

   

Imagem 01 - Criação de um índice b-tree na coluna ID_STATUS

Imagem 02 - Plano de execução de um SELECT filtrando por comparação de negação na coluna ID_STATUS 


     Agora veja na "Imagem 03" que em seguida eu apaguei o índice B-tree criado anteriormente e recriei-o como BITMAP. A partir de então o otimizador deixou de fazer "FULL TABLE SCAN" e realizou uma operação do tipo "BITMAP INDEX FULL SCAN". Podemos deduzir analisando o custo do SQL em um plano de execução estimado, antes e depois da criação do índice bitmap, que mesmo utilizando índice o SQL não foi otimizado, pois o custo que era 258 (ver Imagem 02) aumentou para 1.439 (ver Imagem 04).


Imagem 03 - Recriando o índice como bitmap

Imagem 04 - Plano de execução do SELECT utilizando o índice bitmap



CONCLUSÃO
O índice Bitmap pode ser utilizado em SQLs que utilizam comparação de negação, mas isso não significa que o SQL será "sempre" otimizado com o uso desse índice. Muitas vezes a otimização irá ocorrer, mas no caso apresentado nesse post ela não ocorreu. Outra solução que poderia ser utilizada nesse caso seria reescrever o SQL utilizando a cláusula IN (ao invés de NOT IN), pois a coluna ID_STATUS possui apenas 5 valores, então poderíamos mudar a cláusula WHERE para ficar igual a:   WHERE  ID_STATUS IN (3,4).
 
  
 
Por hoje é só!
Se você tiver dúvidas deixe um comentário que responderei o mais breve possível. Caso você queira aprender mais sobre este assunto, sugiro participar de uma turma dos meus treinamentos de SQL Tuning.

[]s











Nenhum comentário:

Postar um comentário