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

Les index de texte intégral et composites et leur impact sur la requête

Si je comprends votre question, vous savez que MATCH AGAINST utilise votre index FULLTEXT et vous vous demandez comment MySQL s'y prend pour appliquer le reste de la clause WHERE (c'est-à-dire effectue-t-il un balayage de table ou une recherche indexée).

Voici ce que je suppose à propos de votre table :elle a une CLÉ PRIMAIRE sur une colonne d'identifiant et l'index FULLTEXT.

Alors tout d'abord, MySQL ne sera jamais utilisez l'index FULLTEXT pour la clause WHERE ville/état. Pourquoi? Parce que les index FULLTEXT ne s'appliquent qu'avec MATCH AGAINST. Voir ici dans le paragraphe après la première série de puces (pas les puces de la table des matières).

MODIF : Dans votre cas, en supposant que votre table n'a pas seulement 10 lignes, MySQL appliquera l'index FULLTEXT pour votre MATCH AGAINST, puis effectuera une analyse de table sur ces résultats pour appliquer la ville/l'état WHERE.

Et si vous ajoutiez un index BTREE à la ville et à l'état ?

CREATE INDEX city__state ON table (city(10),state(2)) USING BTREE;

Eh bien, MySQL ne peut en utiliser qu'un un index pour cette requête puisqu'il s'agit d'une simple sélection. Ce sera soit utilisez le FULLTEXT ou le BTREE. Notez que lorsque je dis un index, je veux dire une définition d'index, pas une colonne dans un index en plusieurs parties. De toute façon, cela soulève alors la question de savoir lequel fait il utilise ?

Cela dépend de l'analyse du tableau. MySQL tentera d'estimer (basé sur les statistiques de table de la dernière OPTIMIZE TABLE) quel index élaguera le plus d'enregistrements. Si la ville/état WHERE vous ramène à 10 enregistrements alors que MATCH AGAINST ne vous ramène qu'à 100, alors MySQL utilisera l'index city__state en premier pour la ville/l'état WHERE, puis effectuez une analyse de table pour le MATCH CONTRE.

D'autre part, si le MATCH_AGAINST vous ramène à 10 enregistrements alors que la ville/l'état WHERE vous ramène à seulement 1000, alors MySQL appliquera d'abord l'index FULLTEXT et le balayage de table pour la ville et l'état.

L'essentiel est la cardinalité de votre indice. Essentiellement, à quel point les valeurs qui entreront dans votre index sont-elles uniques ? Si chaque enregistrement de votre table a une ville définie sur Oakland, alors ce n'est pas une clé très unique et donc avoir city ='Oakland' ne réduit pas vraiment le nombre d'enregistrements pour vous. Dans ce cas, nous disons que votre index city__state a une faible cardinalité .

Par conséquent, si 90 % des mots de votre index FULLTEXT sont "John", cela ne vous aide pas vraiment non plus pour les mêmes raisons.

Si vous pouvez vous permettre l'espace et la surcharge UPDATE/DELETE/INSERT, je recommanderais d'ajouter l'index BTREE et de laisser MySQL décider quel index il veut utiliser. D'après mon expérience, il fait généralement un très bon travail pour choisir le bon.

J'espère que cela répond à votre question.

MODIF : En passant, assurez-vous de choisir la bonne taille pour votre index BTREE (dans mon exemple, j'ai choisi les 10 premiers caractères de la ville). Cela a évidemment un impact énorme sur la cardinalité. Si vous avez choisi city(1), vous obtiendrez évidemment une cardinalité inférieure à celle de city(10).

EDIT2 : Le plan de requête de MySQL (estimation) pour lequel l'index supprime le plus d'enregistrements est ce que vous voyez dans EXPLAIN.