2009-07-28 12 views
22

SarebbeIl substr o LIKE è più veloce in Oracle?

WHERE substr(my_field,1,6) = 'search' 

o

WHERE my_field LIKE 'search%' 

essere più veloce in Oracle, o ci sarebbe alcuna differenza?

+0

Vedi anche http://stackoverflow.com/questions/8646623/what-is-the-difference-between-instr-and-like-in-oracle – Vadzim

risposta

19

Supponendo che le prestazioni massime siano l'obiettivo, sceglierei idealmente SUBSTR(my_field,1,6) e creare un indice basato su funzioni per supportare la query.

CREATE INDEX my_substr_idx 
    ON my_table(substr(my_field,1,6)); 

Come altri sottolineano, SUBSTR(my_field,1,6) non sarebbe in grado di utilizzare un indice regolare MY_FIELD. La versione LIKE potrebbe usare l'indice, ma le stime di cardinalità dell'ottimizzatore in quel caso sono generalmente piuttosto scadenti, quindi è probabile che non utilizzi un indice quando sarebbe utile o se usasse un indice quando sarebbe preferibile effettuare una scansione della tabella. L'indicizzazione dell'espressione effettiva fornirà all'ottimizzatore molte più informazioni su cui lavorare, quindi è molto più probabile che scelga l'indice correttamente. Qualcuno più intelligente di me potrebbe essere in grado di suggerire un modo per utilizzare le statistiche su colonne virtuali in 11g per fornire all'ottimizzatore informazioni migliori per la query LIKE.

Se 6 è una variabile (ad esempio a volte si desidera cercare i primi 6 caratteri e talvolta si desidera cercare un numero diverso), probabilmente non si sarà in grado di elaborare un indice basato su funzioni per supportare tale query . In questo caso, probabilmente stai meglio con i capricci delle decisioni dell'ottimizzatore con la formulazione LIKE.

9

Delle due opzioni fornite, sicuramente come. Il metodo della sottostringa dovrà essere eseguito su tutte le righe della tabella. L'utilizzo di LIKE consentirà l'uso di indici.

Per verificare la risposta, è sufficiente visualizzare i risultati. Dovrebbe essere chiaro come il giorno.

+0

COME è forse più veloce, non definitivamente. Anche se esiste un indice, può o non può essere utilizzato a seconda della selettività. –

+0

@Alex - Vero. Ma in tutti i casi è meglio cercare il meglio e consentire al server l'opzione di utilizzare gli indici, se disponibili. L'utilizzo del metodo della sottostringa garantisce che non verranno utilizzati indici. – beach

+5

concordato. Ma è possibile eseguire il slap di un indice basato su funzioni su SUBSTR (my_field, 1,6) che è più probabile che venga utilizzato rispetto a un indice normale su my_field per LIKE. –

2

Se si dispone di un indice su my_field, LIKE potrebbe essere più veloce. Fai i tuoi punti di riferimento.

0

Vorrei profilare entrambi. Ma direi che il 'LIKE' sarebbe molto più veloce, perché usa la ricerca binaria sull'indice (se il campo è indicizzato). Se si utilizza il metodo SUBSTR, si avrà una scansione completa della tabella, poiché Oracle deve elaborare riga per riga la funzione.

1

Non c'è davvero due questioni qui:

  1. Per quale sarà Oracle produrre il più accurato cardinalità e preventivo di spesa?
  2. Quale metodo è più flessibile in termini di potenziali metodi di accesso?

Questo può variare in base alla versione, ma entrambi sono abbastanza facili da testare e in questo modo si è certi di disporre delle migliori informazioni per la propria versione e i propri dati.

piani di esecuzione Run per entrambe le query utilizzando ...

explain plan for 
select ... from ... where my_field LIKE 'search%'; 

select * from table(dbms_xplan.display); 

e

explain plan for 
select ... from ... where substr(my_field,1,6) = 'search'; 

select * from table(dbms_xplan.display); 

Si può vedere una differenza nel piano di esecuzione, a seconda della presenza di indici, ecc, Ma anche confrontare le stime di cardinalità con il risultato effettivo che si ottiene da:

select count(*) from ... where my_field LIKE 'search%'; 

Uno dei due metodi può essere significativamente più accurato rispetto agli altri.

Se nessuno di loro è molto accurata e questa query è previsto per l'esecuzione per un importo non banale di tempo, allora considerare l'utilizzo di campionamento dinamico per migliorare la stima, perché con la stima di cardinalità sbagliato l'ottimizzatore può scegliere una non ottimale metodo di accesso comunque.

explain plan for 
select /*+ dynamic_sampling(4) */ ... from ... where substr(my_field,1,6) = 'search'; 

select * from table(dbms_xplan.display); 

Per quanto riguarda l'utilizzo dell'indice, entrambi i metodi potrebbero utilizzare un metodo di accesso basato su indice. Il predicato LIKE è probabilmente più indicizzato e potrebbe utilizzare una scansione di intervallo o una scansione dell'indice completa rapida. Il metodo SUBSTR può certamente utilizzare la scansione rapida dell'indice completo, ma se l'ottimizzatore considererà che la scansione di un intervallo sia meglio testata sulla propria versione - ricordo che non lo farà ma chi dirà che substr (my_column, , n) non sarà riconosciuto come caso speciale, se non ora in futuro?

2

Se si dispone di nessun indice di quanto non ci sia differenza. Perché oracle sta eseguendo una scansione completa della tabella e valuta l'espressione per ogni riga. È possibile inserire un indice sulla colonna per accelerare entrambe le query.

CREATE INDEX my_like_idx 
ON my_table(my_field); 

Questo indice è più flessibile e accelera la query utilizzando come. Funzionerà per qualsiasi confronto a partire dai personaggi e con il segnaposto (%) alla fine. Oracle sta eseguendo una scansione dell'indice per trovare tutte le righe corrispondenti.

CREATE INDEX my_substr_idx 
ON my_table(substr(my_field,1,6)); 

Questo indice accelera la query con substr. Ma l'indice è molto speciale per confrontare solo i primi 6 caratteri.

Se si interroga per un pezzo di partenza nel mezzo. La creazione di un indice basato su funzioni aiuterà.

WHERE substr(my_field,2,5) = 'earch' 
WHERE my_field like '%earch%' 
+0

http://stackoverflow.com/a/30781872/603516 – Vadzim

Problemi correlati