2012-04-27 12 views
11

Avere questa tabella:Ottimizzazione delle query MySQL LIKE '% stringa%' in InnoDB

CREATE TABLE `example` (
`id` int(11) unsigned NOT NULL auto_increment, 
`keywords` varchar(200) NOT NULL, 
PRIMARY KEY (`id`) 
) ENGINE=InnoDB; 

Vorremmo ottimizzare la seguente query:

SELECT id FROM example WHERE keywords LIKE '%whatever%' 

Il tavolo è InnoDB, (quindi non FULLTEXT per ora) quale sarebbe l'indice migliore da utilizzare per ottimizzare tale query?

Abbiamo provato un semplice:

ALTER TABLE `example` ADD INDEX `idxSearch` (`keywords`); 

Ma un spiegare query mostra che necessità di eseguire la scansione di tutto il tavolo se le nostre domande in cui LIKE 'qualunque%' invece, questo indice si comporta bene, ma altrimenti non ha valore.

Esiste comunque l'ottimizzazione per innoDB?

Grazie!

+0

Mi raccomando qualche ottimizzazione delle prestazioni di MySQL, [mysqltuner.pl] (http://mysqltuner.com/) o [tuning-primer.sh] (http://www.day32.com/MySQL/) – jaggedsoft

risposta

38

Gli indici vengono creati dall'inizio della stringa verso la fine. Quando si utilizza la clausola di tipo LIKE 'whatever%', MySQL può utilizzare gli indici basati su start per cercare whatever molto rapidamente.

Ma passare a LIKE '%whatever%' rimuove quell'ancora all'inizio della stringa. Ora gli indici basati su start non possono essere usati, perché il tuo termine di ricerca non è più ancorato all'inizio della stringa - è "mobile" da qualche parte nel mezzo e l'intero campo deve essere ricercato. Qualsiasi query LIKE '%... non può mai utilizzare gli indici.

Ecco perché si utilizzano gli indici di testo completo se tutto ciò che si sta facendo sono ricerche "mobili", perché sono progettate per quel tipo di utilizzo.

Nota importante: InnoDB ora supports fulltext indici dalla versione 5.6.4. Quindi, a meno che non sia possibile eseguire l'aggiornamento ad almeno 5.6.4, non c'è nulla che ti trattiene dall'usare le ricerche a testo intero di InnoDB * E.

+0

+1 per grande spiegazione –

+0

Grazie, sto usando MySQL 5.0.77-log in un ambiente cloud quindi nessun modo per aggiornare :( Prenderò in considerazione la possibilità di spostare la tabella su MyIsam quindi – jmserra

+0

Se passiamo a InnoDB dovremmo cambiare le query per utilizzare MATCH/AGAINST? o l'uso corrente del vantaggio 'LIKE' dell'indice di FullText? Grazie ancora – jmserra

0

Desidero commentare che, sorprendentemente, la creazione di un indice ha anche contribuito a velocizzare le query per le query like '%abc%' nel mio caso.

In esecuzione MySQL 5.5.50 su Ubuntu (lasciando tutto su impostazione predefinita), ho creato una tabella con un sacco di colonne e ha inserito voci fittizie 100,000. In una colonna, ho inserito stringhe completamente casuali con 32 caratteri (vale a dire che sono tutte uniche).

Ho eseguito alcune query e aggiunto un indice su questa colonna. Un semplice

select id, searchcolumn from table_x where searchcolumn like '%ABC%' 

restituisce un risultato in ~2 secondssenza l'indice e in 0.05 secondscon l'indice.

Questo non si adatta alle spiegazioni sopra (e in molti altri post). Quale potrebbe essere la ragione per questo?

EDIT Ho controllato l'uscita EXPLAIN.L'output dice che le righe sono 100,000, ma le informazioni aggiuntive sono "Using where; Using index". Quindi, in qualche modo, il DBMS deve cercare tutte le righe, ma è ancora in grado di utilizzare l'indice?

+0

La tua query non contiene una condizione LIKE. Ecco perché viene utilizzato l'indice. – ditscheri

+0

@ditscheri Ci dispiace, questo era un errore di battitura, in realtà è una condizione LIKE (ho corretto la mia posizione t) – abulhol