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

Comment fonctionnent les index MySQL ?

La première chose que vous devez savoir est que les index sont un moyen d'éviter de balayer toute la table pour obtenir le résultat que vous recherchez.

Il existe différents types d'index et ils sont implémentés dans la couche de stockage, il n'y a donc pas de norme entre eux et ils dépendent également du moteur de stockage que vous utilisez.

InnoDB et l'index B+Tree

Pour InnoDB, le type d'index le plus courant est l'index basé sur B+Tree, qui stocke les éléments dans un ordre trié. De plus, vous n'avez pas besoin d'accéder à la table réelle pour obtenir les valeurs indexées, ce qui accélère le retour de votre requête.

Le "problème" de ce type d'index est que vous devez interroger la valeur la plus à gauche pour utiliser l'index. Ainsi, si votre index comporte deux colonnes, disons last_name et first_name, l'ordre dans lequel vous interrogez ces champs est très important .

Donc, étant donné le tableau suivant :

CREATE TABLE person (
    last_name VARCHAR(50) NOT NULL,
    first_name VARCHAR(50) NOT NULL,
    INDEX (last_name, first_name)
);

Cette requête tirerait parti de l'index :

SELECT last_name, first_name FROM person
WHERE last_name = "John" AND first_name LIKE "J%"

Mais le suivant ne le serait pas

SELECT last_name, first_name FROM person WHERE first_name = "Constantine"

Parce que vous interrogez le first_name colonne en premier et ce n'est pas la colonne la plus à gauche dans l'index.

Ce dernier exemple est encore pire :

SELECT last_name, first_name FROM person WHERE first_name LIKE "%Constantine"

Parce que maintenant, vous comparez la partie la plus à droite du champ le plus à droite dans l'index.

L'index de hachage

Il s'agit d'un type d'index différent que, malheureusement, seul le backend de la mémoire prend en charge. C'est rapide comme l'éclair mais seulement utile pour les recherches complètes, ce qui signifie que vous ne pouvez pas l'utiliser pour des opérations comme > , < ou LIKE .

Comme cela ne fonctionne que pour le backend de la mémoire, vous ne l'utiliserez probablement pas très souvent. Le cas principal auquel je peux penser en ce moment est celui où vous créez une table temporaire dans la mémoire avec un ensemble de résultats d'une autre sélection et effectuez de nombreuses autres sélections dans cette table temporaire à l'aide d'index de hachage.

Si vous avez un gros VARCHAR champ, vous pouvez "émuler" l'utilisation d'un index de hachage lors de l'utilisation d'un B-Tree, en créant une autre colonne et en y enregistrant un hachage de la grande valeur. Disons que vous stockez une URL dans un champ et que les valeurs sont assez grandes. Vous pouvez également créer un champ entier appelé url_hash et utilisez une fonction de hachage comme CRC32 ou toute autre fonction de hachage pour hacher l'url lors de son insertion. Et ensuite, lorsque vous avez besoin d'interroger cette valeur, vous pouvez faire quelque chose comme ceci :

SELECT url FROM url_table WHERE url_hash=CRC32("http://gnu.org");

Le problème avec l'exemple ci-dessus est que depuis le CRC32 génère un hachage assez petit, vous vous retrouverez avec beaucoup de collisions dans les valeurs hachées. Si vous avez besoin de valeurs exactes, vous pouvez résoudre ce problème en procédant comme suit :

SELECT url FROM url_table 
WHERE url_hash=CRC32("http://gnu.org") AND url="http://gnu.org";

Cela vaut toujours la peine de hacher les choses même si le nombre de collisions est élevé car vous n'effectuerez que la deuxième comparaison (celle de la chaîne) avec les hachages répétés.

Malheureusement, en utilisant cette technique, vous devez toujours frapper la table pour comparer l'url champ.

Récapitulez

Quelques faits dont vous pourriez tenir compte chaque fois que vous voulez parler d'optimisation :

  1. La comparaison d'entiers est beaucoup plus rapide que la comparaison de chaînes. Cela peut être illustré par l'exemple sur l'émulation de l'index de hachage dans InnoDB .

  2. Peut-être que l'ajout d'étapes supplémentaires dans un processus le rend plus rapide, pas plus lent. Cela peut être illustré par le fait que vous pouvez optimiser un SELECT en le divisant en deux étapes, en faisant en sorte que la première stocke les valeurs dans une table en mémoire nouvellement créée, puis exécute les requêtes les plus lourdes sur cette seconde table.

MySQL a aussi d'autres index, mais je pense que celui de B+Tree est le plus utilisé et celui de hachage est une bonne chose à savoir, mais vous pouvez trouver les autres dans le Documentation MySQL .

Je vous recommande fortement de lire le livre "High Performance MySQL", la réponse ci-dessus était définitivement basée sur son chapitre sur les index.