Pourquoi est-il nécessaire?
Lorsque les données sont stockées sur des périphériques de stockage sur disque, elles sont stockées sous forme de blocs de données. Ces blocs sont accessibles dans leur intégralité, ce qui en fait l'opération d'accès au disque atomique. Les blocs de disques sont structurés de la même manière que les listes liées; les deux contiennent une section pour les données, un pointeur vers l'emplacement du nœud (ou bloc) suivant, et les deux n'ont pas besoin d'être stockés de manière contiguë.
Étant donné qu'un certain nombre d'enregistrements ne peuvent être triés que sur un champ, nous pouvons affirmer que la recherche sur un champ qui n'est pas trié nécessite une recherche linéaire qui nécessite N/2
des accès aux blocs (en moyenne), où N
est le nombre de blocs qui la table s'étend. Si ce champ est un champ non clé (c'est-à-dire qu'il ne contient pas d'entrées uniques), l'espace de table entier doit être recherché aux N
accès par bloc.
Alors qu'avec un champ trié, une recherche binaire peut être utilisée, qui a log2 N
des accès par blocs. De plus, étant donné que les données sont triées en fonction d'un champ non clé, le reste du tableau n'a pas besoin d'être recherché pour les valeurs en double, une fois qu'une valeur plus élevée est trouvée. Ainsi, l'augmentation des performances est substantielle.
Qu'est-ce que l'indexation?
L'indexation est un moyen de trier un certain nombre d'enregistrements sur plusieurs champs. La création d'un index sur un champ dans une table crée une autre structure de données qui contient la valeur du champ et un pointeur sur l'enregistrement auquel elle se rapporte. Cette structure d'index est ensuite triée, ce qui permet d'effectuer des recherches binaires dessus.
L'inconvénient de l'indexation est que ces index nécessitent de l'espace supplémentaire sur le disque car les index sont stockés ensemble dans une table à l'aide du moteur MyISAM, ce fichier peut rapidement atteindre les limites de taille du système de fichiers sous-jacent si de nombreux champs de la même table sont indexés .
Comment ça marche?
Tout d'abord, décrivons un exemple de schéma de table de base de données;
Nom du champ Type de données Taille sur le disque
id (clé primaire) INT non signé 4 octets
firstName Char (50) 50 octets
lastName Char (50) 50 octets
emailAddress Char (100) 100 octets
Remarque : char a été utilisé à la place de varchar pour permettre une taille précise sur la valeur du disque. Cet exemple de base de données contient cinq millions de lignes et n'est pas indexé. Les performances de plusieurs requêtes vont maintenant être analysées. Il s'agit d'une requête utilisant l' id (un champ clé trié) et une utilisant le prénom (un champ non trié non clé).
Exemple 1 - champs triés et champs non triés
Compte tenu de notre exemple de base de données d' r = 5,000,000
enregistrements d'une taille fixe donnant une longueur d'enregistrement d' R = 204
octets et ils sont stockés dans une table en utilisant le moteur MyISAM qui utilise les B = 1,024
octets de taille de bloc par défaut . Le facteur de blocage de la table serait des bfr = (B/R) = 1024/204 = 5
enregistrements par bloc de disque. Le nombre total de blocs requis pour contenir la table est de N = (r/bfr) = 5000000/5 = 1,000,000
blocs.
Une recherche linéaire sur le champ id nécessiterait une moyenne d' N/2 = 500,000
accès aux blocs pour trouver une valeur, étant donné que le champ id est un champ clé. Mais comme le champ id est également trié, une recherche binaire peut être effectuée nécessitant une moyenne d' log2 1000000 = 19.93 = 20
accès aux blocs. Instantanément, nous pouvons voir que c'est une amélioration drastique.
Maintenant, le champ firstName n'est ni trié ni un champ clé, donc une recherche binaire est impossible, et les valeurs ne sont pas uniques, et donc la table nécessitera une recherche jusqu'au bout pour un N = 1,000,000
bloc exact accède. C'est cette situation que l'indexation vise à corriger.
Étant donné qu'un enregistrement d'index ne contient que le champ indexé et un pointeur sur l'enregistrement d'origine, il va de soi qu'il sera plus petit que l'enregistrement multi-champ vers lequel il pointe. Ainsi, l'index lui-même nécessite moins de blocs de disques que la table d'origine, ce qui nécessite donc moins d'accès aux blocs pour parcourir. Le schéma d'un index sur le champ firstName est décrit ci-dessous;
Nom du champ Type de données Taille sur le disque
firstName Char (50) 50 octets
(pointeur d'enregistrement) 4 octets spéciaux
Remarque : Les pointeurs dans MySQL ont une longueur de 2, 3, 4 ou 5 octets selon la taille de la table.
Exemple 2 - indexation
Compte tenu de notre exemple de base de données d' r = 5,000,000
enregistrements avec une longueur d'enregistrement d'index d' R = 54
octets et en utilisant les B = 1,024
octets de taille de bloc par défaut . Le facteur de blocage de l'index serait des bfr = (B/R) = 1024/54 = 18
enregistrements par bloc de disque. Le nombre total de blocs requis pour contenir l'index est de N = (r/bfr) = 5000000/18 = 277,778
blocs.
Désormais, une recherche utilisant le champ firstName peut utiliser l'index pour augmenter les performances. Cela permet une recherche binaire de l'index avec une moyenne d' log2 277778 = 18.08 = 19
accès aux blocs. Pour trouver l'adresse de l'enregistrement réel, ce qui nécessite un accès de bloc supplémentaire pour lire, ce qui porte le total 19 + 1 = 20
des accès de bloc, loin des 1 000 000 d'accès de bloc requis pour trouver une correspondance firstName dans la table non indexée.
Quand faut-il l'utiliser?
Étant donné que la création d'un index nécessite un espace disque supplémentaire (277 778 blocs supplémentaires par rapport à l'exemple ci-dessus, une augmentation de ~ 28%), et qu'un trop grand nombre d'index peut entraîner des problèmes liés aux limites de taille des systèmes de fichiers, une réflexion approfondie doit être menée pour sélectionner le bon champs à indexer.
Étant donné que les index ne sont utilisés que pour accélérer la recherche d'un champ correspondant dans les enregistrements, il va de soi que l'indexation des champs utilisés uniquement pour la sortie serait simplement une perte d'espace disque et de temps de traitement lors d'une opération d'insertion ou de suppression, et donc devrait être évité. Compte tenu également de la nature d'une recherche binaire, la cardinalité ou l'unicité des données est importante. L'indexation sur un champ avec une cardinalité de 2 diviserait les données en deux, tandis qu'une cardinalité de 1 000 retournerait environ 1 000 enregistrements. Avec une cardinalité aussi faible, l'efficacité est réduite à un tri linéaire et l'optimiseur de requête évitera d'utiliser l'index si la cardinalité est inférieure à 30% du nombre d'enregistrements, ce qui fait de l'index une perte d'espace.