Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Por que a verificação de null diminui a velocidade dessa consulta?


A única maneira que consigo pensar para obter esse tipo de diferença na velocidade de execução seria (a) ter um índice em field4 , e (b) tem um lote de blocos de dados vazios; possivelmente de uma marca d'água alta definida muito alta por cargas repetidas de caminho direto.

A primeira consulta ainda usaria o índice e funcionaria conforme o esperado. Mas como os valores nulos não são indexados, o índice não pode ser usado para verificar se or field4 is null condição, então ele voltaria para uma varredura de tabela completa.

Isso por si só não deve ser um problema aqui, pois uma varredura completa de 7.000 linhas na tabela não deve demorar muito. Mas como é demorando tanto, outra coisa está acontecendo. Uma verificação completa da tabela precisa examinar todos os blocos de dados alocados à tabela para ver se eles contêm alguma linha, e o tempo que leva sugere que há muito mais blocos do que você precisa para manter 7.000 linhas, mesmo com armazenamento CLOB embutido.

A maneira mais simples de obter muitos blocos de dados vazios é ter muitos dados e excluir a maioria deles. Mas acredito que você disse em um comentário agora excluído em uma pergunta anterior que o desempenho costumava ser bom e piorou. Isso pode acontecer se você fizer inserções de caminho direto , especialmente se você 'atualizar' dados excluindo-os e inserindo novos dados no modo de caminho direto. Você pode estar fazendo isso com inserções que têm o /*+ append */ dica; ou em paralelo; ou através do SQL*Loader. Cada vez que você fazia isso, a marca d'água alta se movia, pois os velhos blocos vazios não seriam reutilizados; e cada vez que o desempenho da consulta que verifica se há nulos diminuiria um pouco. Depois de muitas iterações, isso realmente começaria a somar.

Você pode verificar o dicionário de dados para ver quanto espaço está alocado para sua tabela (user_segments etc.) e compare isso com o tamanho dos dados que você acha que realmente tem. Você pode redefinir o HWM reconstruindo a tabela, por exemplo, fazendo:
alter table mytable move;

(de preferência em uma janela de manutenção!)

Como demonstração, executei um ciclo para inserir e excluir 7.000 linhas de caminho direto mais de cem vezes e, em seguida, executei as duas consultas. O primeiro levou 0,06 segundos (muito do qual é sobrecarga do SQL Devleoper); o segundo levou 1.260. (Também corri Gordon's, que teve um tempo semelhante, pois ainda tem que fazer um FTS). Com mais iterações a diferença se tornaria ainda mais marcada, mas fiquei sem espaço... Então fiz um alter table move e reexecutou sua segunda consulta, que levou 0,05 segundos.