2010-03-16 5 views
30

Se il tuo obiettivo è verificare se una stringa esiste in una colonna MySQL (di tipo 'varchar', 'text', 'blob', ecc.) Quale delle seguenti è più veloce/più efficiente/migliore da usare, e perché?Quale è più veloce - INSTR o LIKE?

Oppure, c'è qualche altro metodo che supera uno di questi?

INSTR(columnname, 'mystring') > 0 

vs

columnname LIKE '%mystring%' 
+2

L'attivazione di un indice di ricerca full-text potrebbe essere più veloce se le stringhe di testo sono lunghe – kibibu

+0

'myspace regexp ' "Di solito è più veloce di quello – Seth

+0

La tua domanda ha almeno 5 voti per il tag [tag: like-operator]. Potrei cortesemente chiedere di suggerire [tag: sql-like] come [sinonimo] (http://stackoverflow.com/tags/like-operator/synonyms)? – Kermit

risposta

45

ricerche FULLTEXT sono assolutamente intenzione di essere più veloce, come kibibu notato nei commenti sopra.

Tuttavia:

mysql> select COUNT(ID) FROM table WHERE INSTR(Name,'search') > 0; 
+-----------+ 
| COUNT(ID) | 
+-----------+ 
|  40735 | 
+-----------+ 
1 row in set (5.54 sec) 

mysql> select COUNT(ID) FROM table WHERE Name LIKE '%search%'; 
+-----------+ 
| COUNT(ID) | 
+-----------+ 
|  40735 | 
+-----------+ 
1 row in set (5.54 sec) 

Nel mio test, essi svolgono esattamente lo stesso. Sono entrambi insensibili alle maiuscole e minuscole, e generalmente eseguono scansioni a tutta pagina, un no-no generale quando si tratta di MySQL ad alte prestazioni.

A meno che non si sta facendo una ricerca di prefisso su una colonna indicizzata:

mysql> select COUNT(ID) FROM table WHERE Name LIKE 'search%'; 
+-----------+ 
| COUNT(ID) | 
+-----------+ 
|   7 | 
+-----------+ 
1 row in set (3.88 sec) 

In questo caso, l'LIKE con un carattere jolly solo suffisso è molto più veloce.

+10

+1 per fare effettivamente l'esperimento!Troppe prestazioni "saggezza" si basa sull'istinto – kibibu

10

Nel caso di un predicato "front wilcard" (cioè un "LIKE '% ...'"), come sembra essere il caso qui, INSTR e LIKE dovrebbero eseguire all'incirca lo stesso.

Quando il carattere jolly è non un "carattere jolly anteriore", l'approccio LIKE deve essere più veloce, a meno che il carattere jolly non sia molto selettivo.

Il motivo per cui il tipo di wildcard e la sua selettività materia è che un predicato con INSTR() sarà sistematicamente risultato in una scansione di tabella (SQL può non fare alcuna ipotesi circa la semantica di INSTR), per cui SQL può sfruttare la sua comprensione della semantica del predicato LIKE per magari usare un indice per aiutarlo a testare solo una serie ridotta di possibili corrispondenze.

Come suggerito nel commento alla domanda stessa, un indice di testo completo sarà molto più veloce. La differenza dipende dalla distribuzione specifica delle parole all'interno del testo, e anche dalla dimensione generale della tabella, ecc., Ma si aspetta qualcosa dal due volte più veloce a forse 10 volte più veloce.

Un possibile svantaggio dell'utilizzo dell'indice di testo completo, oltre al sovraccarico generale per la creazione di tale indice, è che a meno che si sia molto attenti nella configurazione di questo indice (ad es. Definizione dell'elenco di parole di arresto, utilizzando sintassi di ricerca specifica per evitare forme flessive e simili ...), ci possono essere casi in cui i risultati forniti da FullText non saranno come previsto. Ad esempio, cercando un "SAW" (uno strumento per tagliare il legno), si possono ottenere molti successi per i record tra cui il verbo "vedere", nelle sue varie forme coniugate.
Ovviamente, queste funzionalità linguistiche degli indici fulltext possono essere sovrascritte e si può anche considerare che tali funzionalità siano effettivamente un vantaggio, non un inconveniente. Ne parlo solo qui dato che stiamo confrontando questo con una semplice ricerca con caratteri jolly.

+0

Grazie, molto istruttivo. – Grekker

3

C'è poco da aggiungere al test di Razzed.Ma a quanto pare usando regexp si incorre in un carico di elaborazione molto più pesante, a differenza di quello che Seth indica nel suo commento.

I seguenti test per scontato che si imposta query_caching-On in my.ini

query_cache_type = 1 
query_cache_size = 64M 

Test

  • I tempi mostrano la performance media, di tre misure (con la cache cancellato a intermittenza):

  • PIACE

    SELECT * FROM `domain_model_offers` WHERE `description` LIKE '%inform%' LIMIT 0 , 30 
    

    iniziale: 0.0035s
    Cached: 0.0005s

  • REGEXP

    SELECT * FROM `domain_model_offers` WHERE `description` REGEXP 'inform' LIMIT 0 , 30 
    

    iniziale: 0.01s
    Cached: 0.0004s

Risultato

LIKE o INSTR è sicuramente più veloce di REGEXP.

Anche se minimo, la differenza di temporizzazione della cache è probabilmente sufficiente per giustificare ulteriori indagini.

Su un sistema MySQL configurato probabilmente, l'indicizzazione di testo completo dovrebbe essere sempre più veloce o almeno alla pari con una ricerca non indeterminata. Quindi usa l'indicizzazione, specialmente su lunghi testi in linguaggio umano, indipendentemente dal codice di markup intermittente.

9

MySQL - INSTR vs LOCATE vs COME vs REGEXP

Per me la INSTR e LOCATE eseguito il più veloce:

# 5.074 sec 
SELECT BENCHMARK(100000000,INSTR('foobar','foo')); 

# 5.086 sec 
SELECT BENCHMARK(100000000,LOCATE('foo','foobar')); 

# 8.990 sec 
SELECT BENCHMARK(100000000,'foobar' LIKE '%foo%'); 

# 14.433 sec 
SELECT BENCHMARK(100000000,'foobar' REGEXP 'foo'); 

# 5.5.35-0ubuntu0.12.10.2 
SELECT @@version; 
+2

Ripeto questo test e vedo risultati simili! –