2009-04-16 10 views
8

J'ai ajouté un index FULLTEXT à l'une de mes tables de base de données MySQL comme suit:Pourquoi la cardinalité d'un index dans MySQL reste-t-elle inchangée quand j'ajoute un nouvel index?

ALTER TABLE members ADD FULLTEXT(about,fname,lname,job_title); 

Le problème est que l'utilisation phpmyadmin Je peux voir la cardinalité de mon nouvel indice est seulement . Est-ce que cela signifie que l'index ne sera jamais utilisé?

J'ai exécuté une commande d'analyse de table mais elle n'a pas semblé faire n'importe quoi.

analyze table members 

Les types respectifs des champs d'index sont varchar (100), varchar (100), le texte, varchar (200) et le moteur utilisé est MyISAM et la table a environ 30 000 lignes, tous uniques. Ma version de MySQL est 5.0.45.

Est-ce que je fais quelque chose de mal?

Répondre

13

Si vous ne disposez que d'une ligne dans le tableau, la cardinalité de l'index doit être de 1, bien sûr. C'est juste en comptant le nombre de valeurs uniques.

Si vous considérez un index comme une table de recherche basée sur des compartiments (comme un hachage), alors la cardinalité est le nombre de compartiments.

Voici comment cela fonctionne: Lorsque vous créez un index sur un ensemble de colonnes (a,b,c,d), la base de données parcourt toutes les lignes de la table, en regardant les quadruplés ordonnés de ces 4 colonnes, pour chaque ligne. Disons que votre table ressemble à ceci:

a b c d e 
-- -- -- -- -- 
1 1 1 1 200 
1 1 1 1 300 
1 2 1 1 200 
1 3 1 1 200 

Alors, que la base de données regarde est seulement les 4 colonnes (a, b, c, d):

a b c d 
-- -- -- -- 
1 1 1 1 
1 2 1 1 
1 3 1 1 

Voir qu'il ya seulement trois uniques rangées à gauche? Ceux-ci deviendront nos seaux, mais nous y reviendrons. En réalité, il existe également un identifiant d'enregistrement ou un identifiant de ligne pour chaque ligne de la table. Donc, notre table originale ressemble à ceci:

(row id) a b c d e 
-------- -- -- -- -- -- 
00000001 1 1 1 1 200 
00000002 1 1 1 1 300 
00000003 1 2 1 1 200 
00000004 1 3 1 1 200 

Alors quand on regarde seulement les 4 colonnes (a, b, c, d), nous sommes vraiment aussi à l'ID de ligne:

(row id) a b c d 
-------- -- -- -- -- 
00000001 1 1 1 1 
00000002 1 1 1 1 
00000003 1 2 1 1 
00000004 1 3 1 1 

Mais nous voulons faire lookup (a, b, c, d) et non par identifiant de ligne, donc nous produisons quelque chose comme ceci:

(a,b,c,d) (row id) 
--------- -------- 
1,1,1,1 00000001 
1,1,1,1 00000002 
1,2,1,1 00000003 
1,3,1,1 00000004 

et enfin, nous regroupons toutes les lignes ids de lignes qui ont des valeurs d'identité (a, b, c, d) ensemble:

(a,b,c,d) (row id) 
--------- --------------------- 
1,1,1,1 00000001 and 00000002 
1,2,1,1 00000003 
1,3,1,1 00000004 

Voir cela? Les valeurs de (a, b, c, d), qui sont (1,1,1,1) (1,2,1,1) et (1,3,1,1) sont devenues des clés pour notre table de recherche dans les rangées de la table d'origine. En réalité, rien de tout cela ne se passe réellement, mais cela devrait vous donner une bonne idée de la façon dont une implémentation "naïve" (c'est-à-dire directe) d'un index pourrait être effectuée. Mais la ligne de fond est la suivante: la cardinalité mesure juste combien de lignes uniques il y a dans un index. Et dans notre exemple c'était le nombre de clés dans notre table de recherche, qui était 3.

Espérons que ça aide!

+0

Merci pour les informations d'index. Très bien expliqué. La cardinalité de mon index devrait être plus de 1 étant donné qu'il y a 30000 lignes et presque tous les membres ont un nom différent? – Tom

+0

Merci pour l'explication sur les index, c'était très bien, mais votre explication n'a pas répondu à la question ci-dessus. –

+0

Vous avez raison, je n'ai pas dit explicitement la conclusion finale: je viens de montrer que 4 rangs tombent dans 3 seaux. Je suis sûr que vous pourriez inventer une autre ligne qui pourrait être ajoutée à l'une des trois catégories existantes de l'indice. Cela laisserait le nombre de compartiments inchangé, ce qui signifierait également que la cardinalité de l'indice était inchangée. Désolé pour ça. – scraimer

8

Je ne peux pas répondre définitivement pourquoi MySQL ne calcule pas la cardinalité, mais je peux le deviner. Les états MySQL manual indiquent:

Cardinalité: estimation du nombre de valeurs uniques dans l'index. Ceci est mis à jour en exécutant ANALYZE TABLE ou myisamchk -a. La cardinalité est calculée en fonction des statistiques stockées en tant qu'entier, de sorte que la valeur n'est pas nécessairement exacte même pour les petites tables. Plus la cardinalité est élevée, plus la probabilité que MySQL utilise l'index lors des jointures est grande.

Les index FULLTEXT ne sont utilisés que dans les requêtes MATCH ... AGAINST (...), ce qui force l'index à être utilisé. La syntaxe MATCH ... AGAINST ne fonctionne pas s'il n'existe pas d'index FULLTEXT sur ces champs.

Je suppose que la cardinalité n'est pas calculée car n'est vraiment pas nécessaire.

Notez que les recherches sur l'index fonctionnent même si la cardinalité n'est pas définie. Pour l'anecdote, une instruction foobar ANALYZE TABLE semble définir correctement la cardinalité.