Mysql
 sql >> Base de données >  >> RDS >> Mysql

Index composé FULLTEXT dans MySQL

La réponse de @Alden Quimby est correcte dans la mesure où elle va, mais il y a plus dans l'histoire, car MySQL ne fera que essayer pour choisir l'index optimal, et sa capacité à effectuer cette détermination est limitée en raison de la façon dont les index de texte intégral interagissent avec l'optimiseur.

Voici ce qui se passe :

Si l'user_id spécifié existe dans 0 ou 1 lignes correspondantes dans la table, l'optimiseur s'en rendra compte et choisira user_id comme index pour cette requête. Exécution rapide.

Sinon, l'optimiseur choisira l'index de texte intégral, en filtrant chaque ligne correspondant à l'index de texte intégral pour éliminer les lignes ne contenant pas un user_id qui correspond à la clause WHERE. Pas aussi vite.

Ce n'est donc pas vraiment le chemin "optimal". Cela ressemble plus à du texte intégral, avec une belle optimisation pour éviter la recherche en texte intégral à la seule condition que nous sachions que nous n'avons presque rien d'intéressant dans la table.

La raison pour laquelle cela échoue est qu'un index de texte intégral ne renvoie aucune statistique significative à l'optimiseur. Il dit simplement "ouais, je pense que cette requête ne devrait probablement m'obliger qu'à vérifier 1 ligne" ... ce qui, bien sûr, plaît beaucoup à l'optimiseur, donc l'index de texte intégral remporte l'enchère pour le coût le plus bas, à moins que l'index avec l'entier la valeur est également relativement faible ou inférieure.

Néanmoins, cela ne signifie pas que je ne l'essayerais pas de cette façon en premier.

Il existe une autre option, qui fonctionnerait mieux avec les requêtes en texte intégral IN BOOLEAN MODE et c'est pour créer une autre colonne que vous rempliriez avec quelque chose comme CONCAT('user_id_',user_id) ou quelque chose de similaire, puis déclarer un index de texte intégral à 2 colonnes.

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

Ensuite, spécifiez tout dans la requête.

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

Désormais, l'index de texte intégral sera chargé de faire correspondre uniquement les lignes où chatons, chiots et "user_id_500" apparaissent dans l'index de texte intégral combiné des deux colonnes, mais vous voudrez toujours avoir le filtre entier là aussi pour vous assurer que le les résultats finaux sont limités malgré toute apparition aléatoire de "user_id_500" dans le message.