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

Oracle utilizza o ignora la colonna indicizzata a seconda del formato di to_date(letterale)

Ok, ci proverò, questa è principalmente una deduzione dalle informazioni disponibili:

Perché Oracle sceglie un piano di esecuzione diverso?

Sembra che nella tua seconda query con l'insolito Date-Format, l'ottimizzatore non abbia idea di quale sia il valore della data risultante. Viene visualizzato il predicato del filtro:

1 - filter(TO_DATE('20140610 ','yyyymmdd ')<=TO_DATE(' 2014-06-10 23:59:59', 'syyyy-mm-dd hh24:mi:ss'))

Ciò significa che l'ottimizzatore non è nemmeno sicuro che la prima data sia inferiore alla seconda! Ciò significa che l'ottimizzatore non ha idea del numero di righe restituite e utilizzerà semplicemente un piano generico senza tenere conto di statistiche specifiche. Sarebbe lo stesso se avessi una funzione definita dall'utente xyt() che restituirebbe una data per l'intervallo. L'ottimizzatore non ha modo di sapere quale valore di data risulterà:ciò significa che ottieni un piano generale per tutti gli usi, che dovrebbe essere abbastanza decente per qualsiasi intervallo di date specificato.

Nel primo e nel terzo caso, l'ottimizzatore sembra comprendere direttamente la data e può indovinare il numero di righe che si trovano nell'intervallo di date utilizzando le statistiche. Quindi, mentre la seconda query era per l'ottimizzatore come BETWEEN X AND 3 questa query è come BETWEEN 1 AND 3 Quindi ottimizza il piano di query per il numero previsto di righe restituite!

La cosa strana sembra essere che Query Optimizer abbia tali problemi con uno strano formato della data, potrebbe essere archiviato come un bug/richiesta di miglioramento...

Ma un Punto importante:

  1. Una scansione completa della tabella non deve essere un piano MALE... Oltre a utilizzare un indice non è sempre più veloce!
  2. Il costo nel piano di query non è in alcun modo direttamente correlato al tempo di esecuzione o alle prestazioni effettivi:è una misurazione interna per confrontare piani diversi per la STESSA QUERY (quindi non puoi confrontare il costo di query diverse come le tue query 1 ,2 e 3)

Fondamentalmente se restituisci un numero elevato di righe da una tabella, una scansione completa della tabella senza accesso all'indice sarà in molti casi molto più veloce, specialmente quando si opera su determinate partizioni! - La scansione della tabella accederà solo alla pertizione per l'intervallo di date corrispondente, quindi solo per la data in questione e restituirà tutte le righe da questa partizione. Questo è molto più veloce che eseguire query sull'indice per ogni singola riga e quindi estrarre la riga tramite l'accesso all'indice... Prova a profilare le query:la scansione completa della tabella sulla partizione dovrebbe essere 3 volte più veloce con molto meno IO