web-dev-qa-db-fra.com

Index MySQL - Quelles sont les meilleures pratiques?

Cela fait quelque temps que j'utilise les index sur mes bases de données MySQL, mais je n'ai jamais appris correctement à leur sujet. Généralement, je mets un index sur les champs que je vais rechercher ou sélectionner en utilisant une clause WHERE, mais parfois, cela ne semble pas si noir et blanc.

Quelles sont les meilleures pratiques pour les index MySQL?

Exemples de situations/dilemmes:

Si un tableau comporte six colonnes et que toutes sont consultables, devrais-je les indexer toutes ou aucune?

.

Quels sont les impacts négatifs de l'indexation sur les performances?

.

Si j'ai une colonne VARCHAR 2500 consultable à partir de certaines parties de mon site, dois-je l'indexer?

192
Haroldo

Vous devriez certainement passer un peu de temps à lire sur l'indexation, il y a beaucoup d'écrits à ce sujet et il est important de comprendre ce qui se passe.

De manière générale, un index impose un ordre sur les lignes d'un tableau.

Pour simplifier, imaginez qu’une table ne soit qu’un gros fichier CSV. Chaque fois qu'une ligne est insérée, elle est insérée à la fin . Ainsi, l'ordre "naturel" de la table est simplement l'ordre dans lequel les lignes ont été insérées.

Imaginez que ce fichier CSV soit chargé dans un tableur très rudimentaire. Cette feuille de calcul n'a pour effet que d'afficher les données et de numéroter les lignes dans un ordre séquentiel.

Maintenant, imaginez que vous deviez trouver toutes les lignes ayant une valeur "M" dans la troisième colonne. Compte tenu de ce que vous avez disponible, vous n'avez qu'une seule option. Vous analysez la table en vérifiant la valeur de la troisième colonne pour chaque ligne. Si vous avez beaucoup de lignes, cette méthode (un "balayage de table") peut prendre beaucoup de temps!

Maintenant, imaginez qu’en plus de cette table, vous avez un index. Cet index particulier est l'index des valeurs de la troisième colonne. L'index répertorie toutes les valeurs de la troisième colonne, dans un ordre significatif (par exemple, par ordre alphabétique) et, pour chacune d'entre elles, fournit une liste des numéros de ligne où cette valeur apparaît.

Maintenant, vous avez une bonne stratégie pour trouver toutes les lignes où la valeur de la troisième colonne est "M". Par exemple, vous pouvez effectuer un recherche binaire ! Alors que l'analyse de la table nécessite que vous examiniez N lignes (où N est le nombre de lignes), la recherche binaire nécessite uniquement que vous examiniez les entrées d'index log-n, dans le pire des cas. Wow, c'est beaucoup plus facile!

Bien sûr, si vous avez cet index et que vous ajoutez des lignes à la table (à la fin, c'est ainsi que fonctionne notre table conceptuelle), vous devez mettre à jour l'index à chaque fois. Donc, vous travaillez un peu plus pendant que vous écrivez de nouvelles lignes, mais vous gagnez une tonne de temps lorsque vous cherchez quelque chose.

Ainsi, en général, l'indexation crée un compromis entre l'efficacité de la lecture et l'efficacité de l'écriture. Sans index, les insertions peuvent être très rapides - le moteur de base de données ajoute simplement une ligne à la table. Lorsque vous ajoutez des index, le moteur doit mettre à jour chaque index lors de l'insertion.

Par contre, les lectures deviennent beaucoup plus rapides.

J'espère que cela couvre vos deux premières questions (comme d'autres l'ont répondu - vous devez trouver le bon équilibre).

Votre troisième scénario est un peu plus compliqué. Si vous utilisez LIKE, les moteurs d'indexation vous aideront généralement à atteindre votre vitesse de lecture jusqu'au premier "%". En d'autres termes, si vous sélectionnez la colonne WHERE LIKE 'foo% bar%', la base de données utilisera l'index pour rechercher toutes les lignes où la colonne commence par "foo", puis doit analyser cet ensemble de lignes intermédiaire pour rechercher le sous-ensemble. qui contient "bar". SELECT ... WHERE, la colonne LIKE '% bar%' ne peut pas utiliser l'index. J'espère que vous pouvez voir pourquoi.

Enfin, vous devez commencer à penser aux index de plusieurs colonnes. Le concept est le même et se comporte de la même manière que LIKE: si vous avez un index sur (a, b, c), le moteur continue à utiliser l'index de gauche à droite du mieux qu'il peut. Ainsi, une recherche sur la colonne a pourrait utiliser l'index (a, b, c), comme on le ferait sur (a, b). Cependant, le moteur devra effectuer une analyse complète de la table si vous recherchez WHERE b = 5 AND c = 1).

Espérons que cela aide à éclaircir un peu, mais je dois rappeler que vous feriez mieux de passer quelques heures à chercher de bons articles qui expliquent ces choses en profondeur. C'est également une bonne idée de lire la documentation de votre serveur de base de données. La manière dont les index sont implémentés et utilisés par les planificateurs de requêtes peut varier considérablement.

226
timdev

Découvrez des présentations telles que Plus maîtrise de l'art de l'indexation .

Mise à jour 12/2012: J'ai posté une nouvelle présentation de la mienne: Comment concevoir des index, vraiment . Je l'ai présenté en octobre 2012 à la ZendCon de Santa Clara et en décembre 2012 à Percona Live London.

La conception des meilleurs index est un processus qui doit correspondre aux requêtes que vous exécutez dans votre application.

Il est difficile de recommander des règles générales sur les colonnes qu'il convient d'indexer ou d'indiquer si vous devez indexer toutes les colonnes, pas de colonnes, quels index doivent couvrir plusieurs colonnes, etc. Cela dépend des requêtes que vous devez exécuter.

Oui, il y a des frais généraux, vous ne devez donc pas créer d'index inutilement. Mais vous devriez créer les index utiles aux requêtes à exécuter rapidement. Les frais généraux d'un indice sont généralement largement compensés par ses avantages.

Pour une colonne de type VARCHAR (2500), vous souhaiterez probablement utiliser un index FULLTEXT ou un index de préfixe:

CREATE INDEX i ON SomeTable(longVarchar(100));

Notez qu'un index conventionnel ne peut pas aider si vous recherchez des mots qui peuvent être au milieu de cette longue varchar. Pour cela, utilisez un index en texte intégral.

53
Bill Karwin

Je ne répéterai pas certains des bons conseils dans d'autres réponses, mais j'ajouterai:

Indices composés

Vous pouvez créer des index composés - un index comprenant plusieurs colonnes. MySQL peut les utiliser de à gauche à à droite . Donc si vous avez:

Table A
Id
Name
Category
Age
Description

si vous avez un index composé qui inclut Nom/Catégorie/Âge dans cet ordre, ces clauses WHERE utiliseraient l'index:

WHERE Name='Eric' and Category='A'

WHERE Name='Eric' and Category='A' and Age > 18

mais

WHERE Category='A' and Age > 18

n'utiliserais pas cet index car tout doit être utilisé de gauche à droite.

Expliquez

Utilisez Explain/Explain Extended pour comprendre les index disponibles pour MySQL et ceux qu’il sélectionne réellement. MySQL utilisera seulement [~ # ~] une [~ # ~] clé par requête.

EXPLAIN EXTENDED SELECT * from Table WHERE Something='ABC'

Journal de requête lent

Activez le journal de requête lent pour voir quelles requêtes s'exécutent lentement.

Colonnes larges

Si vous avez une colonne large où la plupart des différences apparaissent dans les premiers caractères, vous ne pouvez utiliser que les N premiers caractères de votre index. Exemple: nous avons une colonne ReferenceNumber définie comme varchar (255) mais dans 97% des cas, le numéro de référence est inférieur ou égal à 10 caractères. J'ai modifié l'index pour ne regarder que les 10 premiers caractères et améliorer un peu les performances.

44
Eric J.

Si une table a six colonnes et qu'elles sont toutes consultables, dois-je les indexer toutes ou aucune

Recherchez-vous champ par champ ou certaines recherches utilisent-elles plusieurs champs? Quels sont les champs la plupart sur lesquels la recherche a été effectuée? Quels sont les types de champs? (Index fonctionne mieux sur les INT que sur les VARCHAR, par exemple) Avez-vous essayé d'utiliser EXPLAIN sur les requêtes en cours d'exécution?

Quels sont les impacts négatifs de l'indexation sur les performances

UPDATEs et INSERTs seront plus lents. Il y a aussi les besoins en espace de stockage supplémentaire, mais ce n'est généralement pas important de nos jours.

Si j'ai une colonne VARCHAR 2500 consultable à partir de certaines parties de mon site, dois-je l'indexer?

Non, sauf si c'est UNIQUE (c'est-à-dire qu'il est déjà indexé) ou que vous recherchez uniquement les correspondances exactes sur ce champ (sans utiliser LIKE ni la recherche en texte intégral de MySQL).

Généralement, je mets un index sur les champs que je rechercherai ou sélectionnerai à l'aide d'une clause WHERE

Normalement, j'indexerais les champs les plus interrogés, puis les INT/BOOLEANs/ENUM plutôt que les champs qui sont VARCHARS. N'oubliez pas que vous devez souvent créer un index sur des champs combinés, plutôt qu'un index sur un champ individuel. Utilisez EXPLAIN et consultez le journal lent.

20
Pete

Load Data Efficiently: les index accélèrent les extractions, mais ralentissent les insertions et les suppressions, ainsi que les mises à jour des valeurs dans les colonnes indexées. C'est-à-dire que les index ralentissent la plupart des opérations impliquant l'écriture. Cela est dû au fait que l'écriture d'une ligne nécessite non seulement l'écriture de la ligne de données, mais également la modification de tous les index. Plus le nombre d'index d'une table est élevé, plus le nombre de modifications à effectuer est important et plus la dégradation des performances moyenne est importante. La plupart des tables reçoivent beaucoup de lectures et peu d'écritures, mais pour une table avec un fort pourcentage d'écritures, le coût de la mise à jour de l'index peut être important.

Éviter les index: Si vous n’avez pas besoin d’un index particulier pour améliorer les performances des requêtes, ne le créez pas.

Espace disque: Un index occupe de l'espace disque et plusieurs index occupent par conséquent davantage d'espace. Cela pourrait vous amener à atteindre une limite de taille de table plus rapidement que s'il n'y avait pas d'index. Évitez les index autant que possible.

à emporter: ne pas trop indexer

11
Srikar Doddi

En général, les index permettent d’accélérer la recherche dans la base de données, avec l’avantage d’utiliser de l’espace disque supplémentaire et de ralentir les requêtes INSERT/UPDATE/DELETE. Utilisez EXPLAIN et lisez les résultats pour savoir quand MySQL utilise vos index.

Si une table a six colonnes et que toutes peuvent être interrogées, dois-je les indexer toutes ou aucune?

L'indexation des six colonnes n'est pas toujours la meilleure pratique.

(a) Allez-vous utiliser l'une de ces colonnes pour rechercher des informations spécifiques?

(b) Quelle est la sélectivité de ces colonnes (combien de valeurs distinctes sont stockées par rapport au nombre total d'enregistrements sur la table)?

MySQL utilise un optimiseur basé sur les coûts, qui essaie de trouver le chemin "le moins cher" lors de l'exécution d'une requête. Et les domaines peu sélectifs ne sont pas de bons candidats.

Quels sont les impacts négatifs sur la performance de l'indexation?

Déjà répondu: espace disque supplémentaire, performances inférieures lors de l'insertion, de la mise à jour et de la suppression.

Si j'ai une colonne VARCHAR 2500 consultable dans certaines parties de mon site, dois-je l'indexer?

Essayez le FULLTEXT Index .

5
Anax

1/2) Les index accélèrent certaines opérations de sélection, mais ils ralentissent d’autres opérations telles que l’insertion, la mise à jour et la suppression. Cela peut être un bon équilibre.

3) utiliser un index de texte intégral ou peut-être sphinx

4
Paul Creasey