Mysql
 sql >> Database >  >> RDS >> Mysql

Indice FULLTEXT composto in MySQL

La risposta di @Alden Quimby è corretta per quanto possibile, ma c'è dell'altro nella storia, perché MySQL proverà solo per scegliere l'indice ottimale e la sua capacità di effettuare tale determinazione è limitata a causa del modo in cui gli indici fulltext interagiscono con l'ottimizzatore.

Quello che succede in realtà è questo:

Se l'id_utente specificato esiste in 0 o 1 righe corrispondenti nella tabella, l'ottimizzatore se ne accorgerà e sceglierà user_id come indice per quella query. Esecuzione veloce.

In caso contrario, l'ottimizzatore sceglierà l'indice fulltext, filtrando ogni riga corrispondente all'indice fulltext per eliminare le righe che non contengono un user_id che corrisponde alla clausola WHERE. Non altrettanto veloce.

Quindi non è veramente il percorso "ottimale". È più simile al testo completo, con una bella ottimizzazione per evitare la ricerca del testo intero nell'unica condizione che sappiamo di non avere quasi nulla di interessante nella tabella.

Il motivo per cui questo si interrompe è che un indice fulltext non restituisce alcuna statistica significativa all'ottimizzatore. Dice solo "sì, penso che quella query dovrebbe probabilmente richiedermi solo di controllare 1 riga" ... il che, ovviamente, fa molto piacere all'ottimizzatore, quindi l'indice fulltext vince l'offerta per il costo più basso, a meno che l'indice con il numero intero anche il valore è relativamente basso o inferiore.

Tuttavia, ciò non significa che non lo proverei prima in questo modo.

C'è un'altra opzione, che funzionerebbe meglio con le query fulltext IN BOOLEAN MODE e cioè creare un'altra colonna che popoleresti con qualcosa come CONCAT('user_id_',user_id) o qualcosa di simile, quindi dichiarare un indice fulltext a 2 colonne.

filter_string VARCHAR(48) # populated with CONCAT('user_id_',user_id);
....
FULLTEXT KEY (message,filter_string)

Quindi specifica tutto nella query.

SELECT ...
 WHERE user_id = 500 AND
 MATCH (message,filter_string) AGAINST ('+kittens +puppies +user_id_500' IN BOOLEAN MODE);

Ora, l'indice fulltext sarà responsabile della corrispondenza solo di quelle righe in cui gattini, cuccioli e "user_id_500" appaiono nell'indice fulltext combinato delle due colonne, ma vorresti comunque avere il filtro intero anche lì per assicurarti che il i risultati finali sono vincolati nonostante qualsiasi apparizione casuale di "user_id_500" nel messaggio.