Oracle
 sql >> Database >  >> RDS >> Oracle

Perché il controllo di null rallenta questa query?

L'unico modo in cui posso pensare di ottenere quel tipo di differenza nella velocità di esecuzione sarebbe (a) avere un indice su field4 e (b) hanno un lotto di blocchi dati vuoti; possibilmente da una boa alta posta molto in alto da ripetuti carichi di percorso diretto.

La prima query utilizzerà comunque l'indice e funzionerà come previsto. Ma poiché i valori nulli non sono indicizzati, l'indice non può essere utilizzato per verificare il or field4 is null condizione, quindi ricadrebbe su una scansione completa della tabella.

Questo di per sé non dovrebbe essere un problema qui, poiché una scansione completa della tabella di 7000 righe non dovrebbe richiedere molto tempo. Ma poiché è impiegando così tanto tempo, sta succedendo qualcos'altro. Una scansione completa della tabella deve esaminare ogni blocco di dati allocato alla tabella per vedere se contengono righe e il tempo necessario suggerisce che ci sono molti più blocchi di quelli necessari per contenere 7000 righe, anche con l'archiviazione CLOB inline.

Il modo più semplice per ottenere molti blocchi di dati vuoti è avere molti dati e quindi eliminarne la maggior parte. Ma credo che tu abbia detto in un commento ora cancellato su una domanda precedente che le prestazioni erano OK e sono peggiorate. Ciò può accadere se esegui inserimenti di percorsi diretti , in particolare se si "aggiornano" i dati eliminandoli e quindi inserendo nuovi dati in modalità percorso diretto. Potresti farlo con inserti che hanno il /*+ append */ suggerimento; o in parallelo; o tramite SQL*Loader. Ogni volta che lo facevi, il segno dell'acqua alta si spostava, poiché i vecchi blocchi vuoti non sarebbero stati riutilizzati; e ogni volta le prestazioni della query che controlla i valori null si degraderebbero leggermente. Dopo molte iterazioni, inizierebbero davvero a sommarsi.

Puoi controllare il dizionario dei dati per vedere quanto spazio è allocato alla tua tabella (user_segments ecc.) e confrontalo con la dimensione dei dati che pensi di avere effettivamente. È possibile ripristinare l'HWM ricostruendo la tabella, ad esempio facendo:

alter table mytable move;

(preferibilmente in una finestra di manutenzione!)

Come demo, ho eseguito un ciclo per inserire ed eliminare 7000 righe del percorso diretto più di cento volte, quindi ho eseguito entrambe le query. Il primo ha richiesto 0,06 secondi (molto dei quali è un sovraccarico di SQL Devleoper); il secondo ha preso 1.260. (Ho anche gestito Gordon's, che ha avuto un tempo simile, poiché deve ancora fare un FTS). Con più iterazioni la differenza diventerebbe ancora più marcata, ma ho esaurito lo spazio... Ho quindi eseguito un alter table move ed esegui nuovamente la tua seconda query, che ha richiesto 0,05 secondi.