J'utilise des index sur mes bases de données MySQL depuis un certain temps maintenant mais je ne les ai jamais correctement appris . En général, je mets un index sur tous les champs que je vais rechercher ou sélectionner en utilisant une WHERE
clause, mais parfois cela ne semble pas si noir et blanc.
Quelles sont les meilleures pratiques pour les index MySQL?
Exemples de situations / dilemmes:
Si une table comporte six colonnes et qu'elles sont toutes consultables, dois-je les indexer toutes ou aucune d'entre elles?
Quels sont les impacts négatifs sur les performances de l'indexation?
Si j'ai une colonne VARCHAR 2500 qui peut être recherchée à partir de parties de mon site, dois-je l'indexer?
mysql
indexing
query-optimization
Haroldo
la source
la source
Réponses:
Vous devriez certainement passer du temps à lire sur l'indexation, il y a beaucoup d'écrit à ce sujet et il est important de comprendre ce qui se passe.
D'une manière générale, un index impose un ordre sur les lignes d'une table.
Par souci de simplicité, imaginez qu'une table n'est 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 vous avez ce fichier CSV chargé dans une application de feuille de calcul très rudimentaire. Cette feuille de calcul n'affiche que les données et numérote les lignes dans un ordre séquentiel.
Imaginez maintenant que vous devez trouver toutes les lignes qui ont une valeur "M" dans la troisième colonne. Compte tenu de ce dont vous disposez, vous n'avez qu'une seule option. Vous scannez le tableau en vérifiant la valeur de la troisième colonne pour chaque ligne. Si vous avez beaucoup de lignes, cette méthode (un "scan de table") peut prendre beaucoup de temps!
Imaginez maintenant qu'en plus de ce tableau, vous avez un index. Cet index particulier est l'indice des valeurs dans 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'elles, fournit une liste des numéros de ligne où cette valeur apparaît.
Vous avez maintenant une bonne stratégie pour trouver toutes les lignes où la valeur de la troisième colonne est "M". Par exemple, vous pouvez effectuer une recherche binaire ! Alors que l'analyse de table vous oblige à regarder N lignes (où N est le nombre de lignes), la recherche binaire ne nécessite que de regarder les entrées d'index log-n, dans le pire des cas. Wow, c'est sûr beaucoup plus facile!
Bien sûr, si vous avez cet index et que vous ajoutez des lignes à la table (à la fin, puisque c'est ainsi que fonctionne notre table conceptuelle), vous devez mettre à jour l'index à chaque fois. Vous faites donc un peu plus de travail pendant que vous écrivez de nouvelles lignes, mais vous économisez une tonne de temps lorsque vous recherchez quelque chose.
Ainsi, en général, l'indexation crée un compromis entre l'efficacité de lecture et l'efficacité d'é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.
En revanche, 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 avec votre vitesse de lecture jusqu'au premier "%". En d'autres termes, si vous SÉLECTIONNEZ O WH la colonne COMME 'foo% bar%', la base de données utilisera l'index pour trouver toutes les lignes où la colonne commence par "foo", puis devra analyser cet ensemble de lignes intermédiaire pour trouver le sous-ensemble qui contient "bar". SELECT ... WHERE colonne LIKE '% bar%' ne peut pas utiliser l'index. J'espère que vous pouvez voir pourquoi.
Enfin, vous devez commencer à penser aux index sur plusieurs colonnes. Le concept est le même et se comporte de la même manière que les éléments LIKE - essentiellement, si vous avez un index sur (a, b, c), le moteur continuera à 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), tout comme une sur (a, b). Cependant, le moteur devrait effectuer une analyse complète de la table si vous recherchiez O = b = 5 ET c = 1)
J'espère que cela vous aidera à jeter un peu de lumière, mais je dois répéter que vous feriez mieux de passer quelques heures à fouiller pour trouver 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 particulier. La façon dont les index sont implémentés et utilisés par les planificateurs de requêtes peut varier assez largement.
la source
FULLTEXT
index? Peuvent-ils aider avec des conditions commeLIKE '%bar%'
?FULLTEXT
peut aider avec cette requête s'ilbar
s'agit d'un "mot".FULLTEXT
gère les mots, pas les sous-chaînes arbitraires (comme leLIKE
fait).Découvrez des présentations comme More Mastering the Art of Indexing .
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 au ZendCon de Santa Clara et en décembre 2012 au 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 est préférable d'indexer, ou si vous devez indexer toutes les colonnes, pas de colonnes, quels index doivent s'étendre sur 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 inutilement des index. Mais vous devez créer les indices qui donnent avantage aux requêtes dont vous avez besoin pour exécuter rapidement. Les frais généraux d'un indice sont généralement largement compensés par son avantage.
Pour une colonne qui est VARCHAR (2500), vous souhaiterez probablement utiliser un index FULLTEXT ou un index de préfixe:
Notez qu'un index conventionnel ne peut pas aider si vous recherchez des mots qui peuvent être au milieu de ce long varchar. Pour cela, utilisez un index fulltext.
la source
Je ne répéterai pas certains des bons conseils dans d'autres réponses, mais ajouterai:
Indices composés
Vous pouvez créer des indices composés - un index qui comprend plusieurs colonnes. MySQL peut les utiliser de gauche à droite . Donc si vous avez:
si vous avez un index composé qui inclut Nom / Catégorie / Âge dans cet ordre, ces clauses WHERE utiliseraient l'index:
mais
n'utiliserait pas cet index car tout doit être utilisé de gauche à droite.
Explique
Utilisez Explain / Explain Extended pour comprendre quels indices sont disponibles pour MySQL et lequel il sélectionne réellement. MySQL n'utilisera UNE clé par requête .
Journal des requêtes lentes
Activez le journal des requêtes lentes pour voir quelles requêtes s'exécutent lentement.
Colonnes larges
Si vous avez une large colonne où LA PLUPART de la distinction se produit 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 97% des cas, le numéro de référence est de 10 caractères ou moins. J'ai changé l'index pour ne regarder que les 10 premiers caractères et amélioré un peu les performances.
la source
Recherchez-vous champ par champ ou certaines recherches utilisent-elles plusieurs champs? Sur quels champs sont les plus recherchés? Quels sont les types de champs? (L'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?
Les MISES À JOUR et INSÉRER seront plus lentes. Il y a aussi les besoins d'espace de stockage supplémentaires, mais cela n'a généralement pas d'importance de nos jours.
Non, à moins que ce soit UNIQUE (ce qui signifie qu'il est déjà indexé) ou que vous ne recherchez que des correspondances exactes sur ce champ (sans utiliser LIKE ou la recherche plein texte de mySQL).
J'indexerais normalement les champs qui sont les plus interrogés, puis les INT / BOOLEANs / ENUMs plutôt que les champs qui sont des VARCHARS. N'oubliez pas, vous devez souvent créer un index sur des champs combinés plutôt qu'un index sur un champ individuel. Utilisez EXPLAIN et vérifiez le journal lent.
la source
Charger les données efficacement : les index accélèrent les récupérations mais ralentissent les insertions et les suppressions, ainsi que les mises à jour des valeurs dans les colonnes indexées. Autrement dit, les index ralentissent la plupart des opérations qui impliquent l'écriture. Cela se produit car l'écriture d'une ligne nécessite non seulement d'écrire la ligne de données, mais également de modifier les index. Plus il y a d'index dans une table, plus de modifications doivent être apportées et plus la dégradation moyenne des performances est importante. La plupart des tables reçoivent de nombreuses lectures et peu d'écritures, mais pour une table avec un pourcentage élevé d'écritures, le coût de la mise à jour de l'index peut être important.
Évitez 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 en conséquence plus d'espace. Cela peut vous amener à atteindre une limite de taille de table plus rapidement que s'il n'y a pas d'index. Évitez les index dans la mesure du possible.
À emporter: ne pas trop indexer
la source
En général, les index permettent d'accélérer la recherche dans la base de données, ayant l'inconvénient d'utiliser de l'espace disque supplémentaire et de ralentir les requêtes
INSERT
/UPDATE
/DELETE
. UtilisezEXPLAIN
et lisez les résultats pour savoir quand MySQL utilise vos indices.L'indexation des six colonnes n'est pas toujours la meilleure pratique.
(a) Allez-vous utiliser l'une de ces colonnes lors de la recherche d'informations spécifiques?
(b) Quelle est la sélectivité de ces colonnes (combien de valeurs distinctes y a-t-il en mémoire, 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 à faible sélectivité ne sont pas de bons candidats.
Déjà répondu: espace disque supplémentaire, performances inférieures lors de l'insertion - mise à jour - suppression.
Essayez l' index FULLTEXT .
la source
1/2) Les index accélèrent certaines opérations de sélection mais ralentissent d'autres opérations comme l'insertion, la mise à jour et la suppression. Cela peut être un bon équilibre.
3) utilisez un index de texte intégral ou peut-être un sphinx
la source
slow down other operations like insert, update and deletes
vous pouvez utiliser l'START TRANSACTION;
YOUR CODE HERE;
COMMIT
option Qui peut aider à éviterslowing down
les autres opérations, car elle ne vérifie qu'une seule fois les contraintes. CAVEAT: Si vous utilisezREPLACE INTO
et votreSQL_MODE
<>STRICT_ALL_TABLES
OUTRADITIONAL
LeBulk Load
ignorera le remplacement et insérera des doublons.