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

Un guide des index MySQL

Lorsque l'optimisation des requêtes MySQL est mentionnée, les index sont l'une des premières choses à être couvertes. Aujourd'hui, nous allons essayer de voir pourquoi ils sont si importants.

Que sont les index ?

En général, un index est une liste alphabétique d'enregistrements avec des références aux pages sur lesquelles ils sont mentionnés. Dans MySQL, un index est une structure de données utilisée pour trouver rapidement des lignes. Les index sont également appelés clés et ces clés sont essentielles pour de bonnes performances - à mesure que les données grossissent, la nécessité d'utiliser correctement les index peut devenir de plus en plus importante. L'utilisation d'index est l'un des moyens les plus puissants d'améliorer les performances des requêtes. Si les index sont utilisés correctement, les performances des requêtes peuvent augmenter de dizaines, voire de centaines de fois.

Aujourd'hui, nous allons essayer d'expliquer les avantages et les inconvénients de base de l'utilisation des index dans MySQL. Gardez à l'esprit que les index MySQL méritent à eux seuls un livre entier, donc cet article ne couvrira pas absolument tout, mais ce sera un bon point de départ. Pour ceux qui s'intéressent au fonctionnement des index à un niveau plus approfondi, la lecture du livre Relational Database Index Design and the Optimizers de Tapio Lahdenmäki et Michael Leach devrait fournir plus d'informations.

Les avantages de l'utilisation des index

L'utilisation des index dans MySQL présente quelques avantages principaux :

  • Les index permettent de trouver rapidement les lignes correspondant à une clause WHERE ;
  • Les index peuvent aider les requêtes à éviter de chercher dans certaines lignes, réduisant ainsi la quantité de données que le serveur doit examiner - s'il y a un choix entre plusieurs index, MySQL utilise généralement l'index le plus sélectif, c'est-à-dire un index qui trouve le plus petit nombre de lignes ;
  • Les index peuvent être utilisés pour récupérer des lignes d'autres tables dans les opérations JOIN ;
  • Les index peuvent être utilisés pour trouver la valeur minimale ou maximale d'une colonne spécifique qui utilise un index ;
  • Les index peuvent être utilisés pour trier ou regrouper une table si les opérations sont effectuées sur un préfixe le plus à gauche d'un index - de même, un préfixe le plus à gauche d'un index à plusieurs colonnes peut également être utilisé par l'optimiseur de requête pour rechercher des lignes ;
  • Les index peuvent également être utilisés pour enregistrer les E/S disque :lorsqu'un index de couverture est utilisé, une requête peut renvoyer des valeurs directement à partir de la structure de l'index en enregistrant les E/S disque.

De même, il existe plusieurs types d'index :

  • INDEX est un type d'index où les valeurs n'ont pas besoin d'être uniques. Ce type d'index accepte les valeurs NULL ;
  • UNIQUE INDEX est fréquemment utilisé pour supprimer les lignes en double d'une table - ce type d'index permet aux développeurs d'imposer l'unicité des valeurs de ligne ;
  • FULLTEXT INDEX est un index qui s'applique aux champs qui utilisent les capacités de recherche en texte intégral. Ce type d'index trouve des mots-clés dans le texte au lieu de comparer directement les valeurs aux valeurs de l'index ;
  • DESCENDING INDEX est un index qui stocke les lignes dans un ordre décroissant - l'optimiseur de requête choisira ce type d'index lorsqu'un ordre décroissant est demandé par la requête. Ce type d'index a été introduit dans MySQL 8.0 ;
  • PRIMARY KEY est aussi un index. En un mot, la PRIMARY KEY est une colonne ou un ensemble de colonnes qui identifie chaque ligne d'une table - fréquemment utilisée avec des champs ayant un attribut AUTO_INCREMENT. Ce type d'index n'accepte pas les valeurs NULL et une fois définies, les valeurs de la PRIMARY KEY ne peuvent pas être modifiées.

Maintenant, nous allons essayer de passer en revue les avantages et les inconvénients de l'utilisation des index dans MySQL. Nous commencerons par l'avantage probablement le plus fréquemment évoqué - accélérer les requêtes qui correspondent à une clause WHERE.

Accélération des requêtes correspondant à une clause WHERE

Les index sont fréquemment utilisés pour accélérer les requêtes de recherche qui correspondent à une clause WHERE. La raison pour laquelle un index accélère ces opérations de recherche est assez simple :les requêtes qui utilisent un index évitent une analyse complète de la table.

Afin d'accélérer les requêtes qui correspondent à une clause WHERE, vous pouvez utiliser l'instruction EXPLAIN dans MySQL. L'instruction EXPLAIN SELECT devrait vous donner un aperçu de la façon dont l'optimiseur de requête MySQL exécute la requête - elle peut également vous montrer si la requête en question utilise un index ou non et quel index utilise-t-elle. Examinez l'explication de requête suivante :

mysql> EXPLAIN SELECT * FROM demo_table WHERE field_1 = “Demo” \G;

*************************** 1. row ***************************

<...>

possible_keys: NULL

key: NULL

key_len: NULL

<...>

La requête ci-dessus n'utilise pas d'index. Cependant, si nous ajoutons un index sur "field_1", l'index sera utilisé avec succès :

mysql> EXPLAIN SELECT * FROM demo_table WHERE field_1 = “Demo” \G;

*************************** 1. row ***************************

<...>

possible_keys: field_1

key: field_1

key_len: 43

<...>

La colonne possible_keys décrit les index possibles que MySQL peut choisir, la colonne key décrit l'index réellement choisi et la colonne key_len décrit la longueur de la clé choisie.

Dans ce cas, MySQL effectuerait une recherche des valeurs dans l'index et renverrait toutes les lignes contenant la valeur spécifiée - par conséquent, la requête serait plus rapide. Bien que les index aident certaines requêtes à être plus rapides, il y a quelques points que vous devez garder à l'esprit si vous voulez que vos index facilitent vos requêtes :

  • Isolez vos colonnes - MySQL ne peut pas utiliser d'index si les colonnes sur lesquelles les index sont utilisés ne sont pas isolées. Par exemple, une requête comme celle-ci n'utiliserait pas d'index :
    SELECT field_1 FROM demo_table WHERE field_1 + 5 = 10;

Pour résoudre ce problème, laissez la colonne qui suit la clause WHERE seule - simplifiez votre requête autant que possible et isolez les colonnes ;

  • Évitez d'utiliser des requêtes LIKE avec un caractère générique précédent - dans ce cas, MySQL n'utilisera pas d'index car le caractère générique précédent signifie qu'il peut y avoir n'importe quoi avant le texte. Si vous devez utiliser des requêtes LIKE avec des caractères génériques et que vous souhaitez que les requêtes utilisent des index, assurez-vous que le caractère générique se trouve à la fin de l'instruction de recherche.

Bien sûr, l'accélération des requêtes qui correspondent à une clause WHERE peut également être effectuée d'autres manières (par exemple, le partitionnement), mais par souci de simplicité, nous n'approfondirons pas cela dans cet article.

Cependant, ce qui pourrait nous intéresser, ce sont différents types de types d'index, nous allons donc examiner cela maintenant.

Se débarrasser des valeurs en double dans une colonne - Index UNIQUES

Le but d'un index UNIQUE dans MySQL est de renforcer l'unicité des valeurs dans une colonne. Pour utiliser un index UNIQUE, lancez une requête CREATE UNIQUE INDEX :

CREATE UNIQUE INDEX demo_index ON demo_table(demo_column);

You can also create a unique index when you create a table:

CREATE TABLE demo_table (
`demo_column` VARCHAR(100) NOT NULL,
UNIQUE KEY(demo_column)
);

C'est tout ce qu'il faut pour ajouter un index unique à une table. Maintenant, lorsque vous essayez d'ajouter une valeur en double à la table, MySQL renverra l'erreur suivante :

#1062 - Duplicate entry ‘Demo’ for key ‘demo_column’

Index FULLTEXT

Un index FULLTEXT est un tel index qui est appliqué aux colonnes qui utilisent les capacités de recherche en texte intégral. Ce type d'index possède de nombreuses fonctionnalités uniques, notamment les mots vides et les modes de recherche.

La liste de mots vides InnoDB a 36 mots tandis que la liste de mots vides MyISAM en a 143. Dans InnoDB, les mots vides sont dérivés de la table définie dans la variable innodb_ft_user_stopword_table, sinon, si cette variable n'est pas définie, ils sont dérivés de la variable innodb_ft_server_stopword_table. Si aucune de ces deux variables n'est définie, InnoDB utilise la liste intégrée. Pour voir la liste de mots vides InnoDB par défaut, interrogez la table INNODB_FT_DEFAULT_STOPWORD.

Dans MyISAM, les mots vides sont dérivés du fichier storage/myisam/ft_static.c. La variable ft_stopword_file permet de modifier la liste de mots vides par défaut. Les mots vides seront désactivés si cette variable est définie sur une chaîne vide, mais gardez à l'esprit que si cette variable définit un fichier, le fichier défini n'est pas analysé pour les commentaires - MyISAM traitera tous les mots trouvés dans le fichier comme des mots vides.

Les index FULLTEXT sont également réputés pour leurs modes de recherche uniques :

  • Si une requête de recherche FULLTEXT sans modificateurs est lancée, un mode langage naturel sera activé. Le mode langage naturel peut également être activé en utilisant le modificateur IN NATURAL LANGUAGE MODE ;
  • Le modificateur WITH QUERY EXPANSION active un mode de recherche avec extension de requête. Un tel mode de recherche fonctionne en effectuant la recherche deux fois et lorsque la recherche est exécutée pour la deuxième fois, le jeu de résultats comprendra quelques-uns des documents les plus pertinents de la première recherche. En général, ce modificateur est utile lorsque l'utilisateur a des connaissances implicites (par exemple, l'utilisateur peut rechercher "base de données" et espérer voir "InnoDB" et "MyISAM" dans le jeu de résultats );
  • Le modificateur IN BOOLEAN MODE permet la recherche avec des opérateurs booléens. Par exemple, les opérateurs +, - ou * accompliraient chacun des tâches différentes - l'opérateur + définirait que la valeur doit être présente dans une ligne, l'opérateur - définirait que la valeur ne doit pas exister et l'opérateur * agirait comme un caractère générique.

Une requête qui utilise un index FULLTEXT ressemble à ceci :

SELECT * FROM demo_table WHERE MATCH(demo_field) AGAINST(‘value’ IN NATURAL LANGUAGE MODE);

Gardez à l'esprit que les index FULLTEXT sont généralement utiles pour les opérations MATCH() AGAINST() - pas pour les opérations WHERE, ce qui signifie que si une clause WHERE est utilisée, l'utilité d'utiliser différents types d'index ne serait pas éliminée.

Il convient également de mentionner que les index FULLTEXT ont une longueur minimale de caractères. Dans InnoDB, une recherche FULLTEXT ne peut être effectuée que lorsque la requête de recherche se compose d'un minimum de trois caractères - cette limite est portée à quatre caractères dans le moteur de stockage MyISAM.

Index DESCENDANT

Un index DESCENDING est un tel index où InnoDB stocke les entrées dans un ordre décroissant - l'optimiseur de requête utilisera un tel index lorsqu'un ordre décroissant est demandé par la requête. Un tel index peut être ajouté à une colonne en exécutant une requête comme ci-dessous :

CREATE INDEX descending_index ON demo_table(column_name DESC);

Un index ascendant peut également être ajouté à une colonne - il suffit de remplacer DESC par ASC.

CLÉS PRIMAIRES

Une CLÉ PRIMAIRE sert d'identifiant unique pour chaque ligne d'une table. Une colonne avec une PRIMARY KEY doit contenir des valeurs uniques - aucune valeur NULL n'est autorisée à être utilisée non plus. Si une valeur en double est ajoutée à une colonne qui a une PRIMARY KEY, MySQL répondra avec une erreur #1062 :

#1062 - Duplicate entry ‘Demo’ for key ‘PRIMARY’

Si une valeur NULL est ajoutée à la colonne, MySQL répondra avec une erreur #1048 :

#1048 - Column ‘id’ cannot be null

Les index primaires sont aussi parfois appelés index clusterisés (nous en discuterons plus tard).

Vous pouvez également créer des index sur plusieurs colonnes à la fois - ces index sont appelés index multicolonnes.

Index multicolonnes

Les index sur plusieurs colonnes sont souvent mal compris - parfois les développeurs et les DBA indexent toutes les colonnes séparément ou les indexent dans le mauvais ordre. Afin de rendre les requêtes utilisant des index multicolonnes aussi efficaces que possible, rappelez-vous que l'ordre des colonnes dans les index qui utilisent plus d'une colonne est l'une des causes les plus courantes de confusion dans cet espace - car il n'y a pas de "par ici ou sur l'autoroute". ” solutions d'ordre d'index, vous devez vous rappeler que l'ordre correct des index multicolonnes dépend des requêtes qui utilisent l'index. Bien que cela puisse sembler assez évident, rappelez-vous que l'ordre des colonnes est essentiel lorsqu'il s'agit d'index multicolonnes - choisissez l'ordre des colonnes de manière à ce qu'il soit aussi sélectif que possible pour les requêtes qui s'exécuteront le plus fréquemment.

Afin de mesurer la sélectivité pour des colonnes spécifiques, obtenez le rapport entre le nombre de valeurs indexées distinctes et le nombre total de lignes dans le tableau - la colonne qui a la sélectivité la plus élevée doit être la première .

Parfois, vous devez également indexer de très longues colonnes de caractères, et dans ce cas, vous pouvez souvent économiser du temps et des ressources en indexant les premiers caractères - un préfixe - au lieu de la valeur entière.

Index des préfixes

Les index de préfixe peuvent être utiles lorsque les colonnes contiennent des valeurs de chaîne très longues, ce qui signifierait que l'ajout d'un index sur toute la colonne consommerait beaucoup d'espace disque. MySQL aide à résoudre ce problème en vous permettant d'indexer uniquement un préfixe de la valeur, ce qui réduit la taille de l'index. Jetez un œil :

CREATE TABLE `demo_table` (
`demo_column` VARCHAR(100) NOT NULL,
INDEX(demo_column(10))
);

La requête ci-dessus créerait un index de préfixe sur la colonne de démonstration indexant uniquement les 10 premiers caractères de la valeur. Vous pouvez également ajouter un index de préfixe à une table existante :

CREATE INDEX index_name ON table_name(column_name(length));

Ainsi, par exemple, si vous souhaitez indexer les 5 premiers caractères d'une demo_column sur une demo_table, vous pouvez exécuter la requête suivante :

CREATE INDEX demo_index ON demo_table(demo_column(5));

Vous devez choisir un préfixe suffisamment long pour donner de la sélectivité, mais aussi suffisamment court pour donner de l'espace. Cela pourrait être plus facile à dire qu'à faire cependant - vous devez expérimenter et trouver la solution qui vous convient.

Index de couverture

Un index couvrant "couvre" tous les champs requis pour exécuter une requête. En d'autres termes, lorsque tous les champs d'une requête sont couverts par un index, un index de couverture est utilisé. Par exemple pour une requête comme celle-ci :

SELECT id, title FROM demo_table WHERE id = 1;

Un index de couverture pourrait ressembler à ceci :

INDEX index_name(id, title);

Si vous voulez vous assurer qu'une requête utilise un index de couverture, émettez une instruction EXPLAIN dessus, puis jetez un œil à la colonne Extra. Par exemple, si votre table a un index multicolonne sur id et title et qu'une requête qui accède uniquement à ces deux colonnes est exécutée, MySQL utilisera l'index :

mysql> EXPLAIN SELECT id, title FROM demo_table \G;

*************************** 1. row ***************************

<...>

type: index

key: index_name

key_len: 5

rows: 1000

Extra: Using index

<...>

Gardez à l'esprit qu'un index de couverture doit stocker les valeurs des colonnes qu'il couvre. Cela signifie que MySQL ne peut utiliser que des index B-Tree pour couvrir les requêtes, car les autres types d'index ne stockent pas ces valeurs.

Indices groupés, secondaires et cardinalité d'index

Lorsqu'il est question d'index, vous pouvez également entendre les termes clustered, index secondaires et cardinalité d'index. En termes simples, les index clusterisés sont une approche du stockage de données et tous les index autres que les index clusterisés sont des index secondaires. La cardinalité de l'index, quant à elle, est le nombre de valeurs uniques dans un index.

Un index clusterisé accélère les requêtes car les valeurs proches sont également stockées à proximité les unes des autres sur le disque, mais c'est aussi la raison pour laquelle vous ne pouvez avoir qu'un seul index clusterisé dans une table.

Un index secondaire est tout index qui n'est pas l'index primaire. Un tel index peut avoir des doublons.

Les inconvénients de l'utilisation des index

L'utilisation des index a certainement des avantages, mais nous ne devons pas oublier que les index peuvent également être l'une des principales causes de problèmes dans MySQL. Certains des inconvénients de l'utilisation des index sont les suivants :

  • Les index peuvent dégrader les performances de certaines requêtes :même si les index ont tendance à accélérer les performances des requêtes SELECT, ils ralentissent les performances des requêtes INSERT, UPDATE et DELETE car, lorsque les données sont mises à jour, index doit également être mis à jour avec lui :toute opération impliquant la manipulation des index sera plus lente que d'habitude ;
  • Les index consomment de l'espace disque - un index occupe son propre espace, donc les données indexées consommeront également plus d'espace disque ;
  • Les index redondants et en double peuvent être un problème - MySQL vous permet de créer des index en double sur une colonne et il ne vous « protège » pas contre une telle erreur. Jetez un œil à cet exemple : 
    CREATE TABLE `demo_table` (
    
    `id` INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,
    
    `column_2` VARCHAR(10) NOT NULL,
    
    `column_3` VARCHAR(10) NOT NULL,
    
    INDEX(id),
    
    UNIQUE(id)
    
    );

Un utilisateur inexpérimenté pourrait penser que cette requête incrémente automatiquement la colonne id, puis ajoute un index sur la colonne et fait en sorte que la colonne n'accepte pas les valeurs en double. Cependant, ce n'est pas ce qui se passe ici. Dans ce cas, la même colonne contient trois index :un INDEX ordinaire, et puisque MySQL implémente à la fois les contraintes PRIMARY KEY et UNIQUE avec les index, cela ajoute deux index supplémentaires sur la même colonne !

Conclusion

Pour conclure, les index dans MySQL ont leur propre place - les index peuvent être utilisés dans une multitude de scénarios, mais chacun de ces scénarios d'utilisation a ses propres inconvénients qui doivent être pris en compte afin de tirer le meilleur parti de index en cours d'utilisation.

Pour bien utiliser les index, profilez vos requêtes, examinez les options dont vous disposez en matière d'index, connaissez leurs avantages et leurs inconvénients, décidez des index dont vous avez besoin en fonction de vos besoins et après avoir indexé les colonnes, assurez-vous que vos index sont réellement utilisé par MySQL. Si vous avez correctement indexé votre schéma, les performances de vos requêtes devraient s'améliorer, mais si le temps de réponse ne vous satisfait pas, voyez si un meilleur index peut être créé afin de l'améliorer.