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/2des accès aux blocs (en moyenne), où Nest 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 Naccès par bloc.
Alors qu'avec un champ trié, une recherche binaire peut être utilisée, qui a log2 Ndes 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,000enregistrements d'une taille fixe donnant une longueur d'enregistrement d' R = 204octets et ils sont stockés dans une table en utilisant le moteur MyISAM qui utilise les B = 1,024octets de taille de bloc par défaut . Le facteur de blocage de la table serait des bfr = (B/R) = 1024/204 = 5enregistrements par bloc de disque. Le nombre total de blocs requis pour contenir la table est de N = (r/bfr) = 5000000/5 = 1,000,000blocs.
Une recherche linéaire sur le champ id nécessiterait une moyenne d' N/2 = 500,000accè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 = 20accè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,000bloc 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,000enregistrements avec une longueur d'enregistrement d'index d' R = 54octets et en utilisant les B = 1,024octets de taille de bloc par défaut . Le facteur de blocage de l'index serait des bfr = (B/R) = 1024/54 = 18enregistrements par bloc de disque. Le nombre total de blocs requis pour contenir l'index est de N = (r/bfr) = 5000000/18 = 277,778blocs.
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 = 19accè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 = 20des 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.