web-dev-qa-db-fra.com

Comment fonctionnent les index MySQL?

Je suis vraiment intéressé par le fonctionnement des index MySQL. En particulier, comment peuvent-ils renvoyer les données demandées sans analyser l'intégralité de la table?

Je sais que c'est hors sujet, mais s'il y avait quelqu'un qui pourrait m'expliquer cela en détail, je serais très, très reconnaissant.

378
good_evening

Fondamentalement, un index sur une table fonctionne comme un index dans un livre (c'est de là que vient le nom):

Supposons que vous avez un livre sur les bases de données et que vous souhaitez trouver des informations sur le stockage, par exemple. Sans index (sans autre aide, telle qu'une table des matières), il vous faudrait parcourir les pages une par une jusqu'à ce que vous trouviez le sujet (c'est un full table scan). D'autre part, un index contient une liste de mots-clés. Vous pouvez donc consulter l'index et voir que storage est mentionné aux pages 113-120, 231 et 354. Vous pouvez ensuite accéder directement à ces pages sans effectuer de recherche ( c'est une recherche avec un index, un peu plus rapide).

Bien entendu, l’utilité de l’index dépend de nombreux facteurs - quelques exemples, à l’aide de la comparaison ci-dessus:

  • si vous aviez un livre sur les bases de données et indexé le mot "base de données", vous verriez qu'il est mentionné aux pages 1-59,61-290 et 292 à 400. Dans ce cas, l'index n'aide pas beaucoup et peut être plus rapide pour parcourir les pages une par une (dans une base de données, il s'agit d'une "mauvaise sélectivité").
  • Pour un livre de 10 pages, cela n'a aucun sens de faire un index, car vous pouvez vous retrouver avec un livre de 10 pages préfixé par un index de 5 pages, ce qui est juste idiot - il suffit de numériser les 10 pages pour en finir. .
  • L’index doit également être utile - il n’ya généralement aucun intérêt à indexer, par exemple. la fréquence de la lettre "L" par page.
490
Piskvor

La première chose que vous devez savoir, c'est que les index sont un moyen d'éviter d'analyser le tableau complet pour obtenir le résultat recherché.

Il existe différents types d'index et ils sont implémentés dans la couche de stockage. Il n'y a donc aucune 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 l'arborescence B +, qui stocke les éléments dans un ordre trié. En outre, 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" concernant ce type d'index est que vous devez rechercher la valeur la plus à gauche pour utiliser l'index. Ainsi, si votre index comporte deux colonnes, dites 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 serait pas

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

Parce que vous interrogez d'abord la colonne first_name et que ce n'est pas la colonne la plus à gauche de 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 de l'index.

L'index de hachage

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

Comme il 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 maintenant est celui où vous créez une table temporaire dans la mémoire avec un ensemble de résultats provenant 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 grand champ VARCHAR, vous pouvez "émuler" l'utilisation d'un index de hachage lorsque vous utilisez un arbre B, en créant une autre colonne et en enregistrant un hachage de 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 utiliser une fonction de hachage telle que CRC32 ou toute autre fonction de hachage pour hacher l'URL lors de son insertion. Et puis, lorsque vous devez 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, puisque la fonction CRC32 génère un hachage assez petit, vous allez vous retrouver 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";

Même si le nombre de collisions est élevé, cela vaut toujours la peine de hacher, car vous ne ferez que la deuxième comparaison (la chaîne 1) avec les hachages répétés.

Malheureusement, en utilisant cette technique, vous devez toujours accéder à la table pour comparer le champ url.

Emballer

Quelques faits que vous pouvez considérer 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é avec 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 accélère le processus, pas le ralentit. Cela peut être illustré par le fait que vous pouvez optimiser une SELECT en la scindant en deux étapes, en faisant en sorte que la première stocke les valeurs dans une table en mémoire nouvellement créée, puis en exécutant les requêtes plus lourdes sur cette seconde table.

MySQL a aussi d’autres index, mais je pense que celui de B + Tree est le plus utilisé de tous les temps et que celui du hash est une bonne chose à savoir, mais vous pouvez trouver les autres dans la documentation MySQL .

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

249
clarete

Fondamentalement, un index est une carte de toutes vos clés qui est triée dans l'ordre. Avec une liste dans l’ordre, au lieu de vérifier chaque clé, il peut faire quelque chose comme ceci:

1: Aller au milieu de la liste - est-il plus haut ou plus bas que ce que je cherche?

2: Si plus haut, aller à mi-chemin entre le milieu et le bas, si plus bas, le milieu et le haut

3: est plus haut ou plus bas? Sauter à nouveau au milieu, etc.

En utilisant cette logique, vous pouvez rechercher un élément dans une liste triée en 7 étapes environ, au lieu de vérifier chaque élément.

Évidemment, il y a des complexités, mais cela vous donne une idée de base.

36
Joshua

Jetez un oeil à ce lien: http://dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html

Leur mode de travail est trop vaste pour couvrir un seul SO poste.

Ici est l'une des meilleures explications des index que j'ai vues. Malheureusement, c'est pour SQL Server et non pour MySQL. Je ne sais pas à quel point les deux sont similaires ...

4
Abe Miessler

Prenez à this vidéos pour plus de détails sur l'indexation

Indexation simple Vous pouvez créer un index unique sur une table. Un index unique signifie que deux lignes ne peuvent pas avoir la même valeur d'index. Voici la syntaxe pour créer un index sur une table

CREATE UNIQUE INDEX index_name
ON table_name ( column1, column2,...);

Vous pouvez utiliser une ou plusieurs colonnes pour créer un index. Par exemple, nous pouvons créer un index sur tutorials_tbl à l'aide de tutorial_author.

CREATE UNIQUE INDEX AUTHOR_INDEX
ON tutorials_tbl (tutorial_author)

Vous pouvez créer un index simple sur une table. Il suffit d'omettre le mot clé UNIQUE de la requête pour créer un index simple. Un index simple permet de dupliquer des valeurs dans une table.

Si vous souhaitez indexer les valeurs d'une colonne dans l'ordre décroissant, vous pouvez ajouter le descriptif Word DESC réservé après le nom de la colonne.

mysql> CREATE UNIQUE INDEX AUTHOR_INDEX
ON tutorials_tbl (tutorial_author DESC)
3
shahirnana

Je veux ajouter mes 2 cents. Je suis loin d'être un expert en bases de données, mais j'ai récemment lu un peu sur ce sujet; assez pour moi d'essayer de donner un ELI5. Alors, voici l'explication d'un profane.


Je le comprends en tant que tel, un index est comme un mini-miroir de votre table, plutôt comme un tableau associatif. Si vous l'alimentez avec une clé correspondante, vous pouvez simplement passer à cette ligne dans une "commande".

Mais si vous n'avez pas cet index/tableau, l'interpréteur de requête doit utiliser une boucle for pour parcourir toutes les lignes et rechercher une correspondance (l'analyse de la table complète).

Avoir un index présente "l'inconvénient" d'un stockage supplémentaire (pour ce mini-miroir), en contrepartie de "l'avantage" de rechercher plus rapidement du contenu.

Notez que (en fonction de votre moteur de base de données), la création de clés principales, étrangères ou uniques définit automatiquement un index respectif. Ce même principe est fondamentalement pourquoi et comment ces touches fonctionnent.

0
WoodrowShigeru

Dans MySQL InnoDB, il existe deux types d'index.

  1. Clé primaire appelée index clusterisé. Les mots clés d'index sont stockés avec les données d'enregistrement réelles dans le nœud feuille B + Tree.

  2. Clé secondaire qui est un index non clusterisé. Ces index ne stockent que les mots-clés de la clé primaire ainsi que leurs propres mots-clés d'index dans le nœud feuille B + Tree. Ainsi, lors de la recherche à partir de l'index secondaire, il trouvera d'abord ses mots clés d'index de clé primaire, puis analysera l'arborescence B + de la clé primaire pour rechercher les enregistrements de données réels. Cela ralentira l'index secondaire par rapport à la recherche par index primaire. Cependant, si les colonnes select sont toutes dans l'index secondaire, inutile de rechercher à nouveau l'index primaire B + Tree. Ceci est appelé indice de couverture.

0
sendon1982

Ajout d'une représentation visuelle à la liste des réponses. enter image description here

MySQL utilise une couche supplémentaire d'indirection: les enregistrements d'index secondaire pointent vers les enregistrements d'index primaires et l'index primaire lui-même contient les emplacements des lignes sur le disque. Si un décalage de ligne change, seul l'index principal doit être mis à jour.

Mise en garde: la structure des données du disque est plate dans le diagramme, mais il s'agit en fait d'une arborescence B +.

Source: lien

0
Anurag Sharma