Dire que j'ai une relation 1-à-N (person_id, pet_id)
. J'ai une table où pet_id
est la clé primaire.
Je comprends qu'un index secondaire InnoDB est essentiellement un arbre B où les valeurs sont les valeurs de clé primaire correspondantes pour la ligne.
Maintenant, supposons qu'une personne puisse avoir des milliers d'animaux de compagnie et je veux souvent les animaux de compagnie d'une personne dans l'ordre pet_id
. Ensuite, il importerait que les enregistrements de l'index secondaire soient triés par (person_id, pet_id)
ou simplement person_id
avec les pet_id
«pour» qui ne sont person_id
pas triés. Deviner le plus tard.
Donc, si ce person_id
n'est pas unique, les enregistrements sont-ils triés physiquement par (person_id, pet_id)
ou JUSTE pet_id
?
Merci
la source
person_id
n'est pas unique, les enregistrements sont-ils triés physiquement par(person_id, pet_id)
ou JUSTEperson_id
?"Réponses:
Non. Si votre table a le moteur InnoDB et le
PRIMARY KEY
is(pet_id)
, définissez un index secondaire comme(person_id)
ou(person_id, pet_id)
ne fait aucune différence.L'index inclut également la
pet_id
colonne afin que les valeurs soient triées comme(person_id, pet_id)
dans les deux cas.Une requête comme celle que vous avez:
devra accéder uniquement à l'index pour obtenir les valeurs et encore plus, il n'aura pas besoin de faire de tri, car les
pet_id
valeurs sont déjà triées dans l'index. Vous pouvez le vérifier en regardant les plans d'exécution (EXPLAIN
):Tout d'abord, nous essayons avec une table MyISAM:
Remarquez le tri de fichiers!
Maintenant, MyISAM avec index composite:
Filesort a disparu , comme prévu.
Essayons maintenant la même chose avec le moteur InnoDB:
Pas de tri de fichiers non plus! Même si l'index n'a pas explicitement la
pet_id
colonne, les valeurs sont là et triées. Vous pouvez vérifier que si vous définissez l'index avec(person_id, pet_id)
, leEXPLAIN
est identique.Permet de le faire, avec InnoDB et l'index composite:
Plans identiques au cas précédent.
Pour être sûr à 100%, j'ai également exécuté les 2 derniers cas (moteur InnoDB, avec des index simples et composites) permettant le
file_per_table
paramétrage et ajoutant quelques milliers de lignes dans le tableau:Dans les deux cas, la vérification de la taille réelle des fichiers donne des résultats identiques :
la source
(<some_column>)
et(<some_column>, <pk>)
parce qu'ilON (<some_column>)
est équivalent àON (<some_column>) INCLUDE (<pk>)
et nonON (<some_column>, <pk>)
. Dans la plupart des cas, cela n'a pratiquement aucune signification, mais si votre PK est aléatoire (c'est-à-dire un UUID), celaON (<s_c>,<pk>)
peut entraîner une fragmentation supplémentaire ou si votre PK a un sens autre que d'être une clé et vous pourriezORDER BY s_c, pk
alors que ces tris seront plus rapides que l'index est déjà pleinement en ordre.INCLUDE (columns)
fonctionnalité. C'est une autre raison pour laquelle j'ai conclu que l'(s_c)
indice est équivalent à(s_c, pk)
.Selon la documentation MySQL sur les index cluster et secondaire
Par conséquent, l'ajout de la CLÉ PRIMAIRE à un index secondaire est définitivement redondant. Votre entrée d'index voudrait
(person_id, pet_id, pet_id)
. Cela alourdirait également inutilement l'index secondaire en ayant 2 copies du fichierPRIMARY KEY
.Pour l'index avec
(person_id)
, si vous deviez exécuter une requête comme celle-ciLe
PRIMARY KEY
serait pleinement engagé dans cette requête et produirait dePRIMARY KEY
toute façon les résultats commandés par . D'un point de vue physique, les lignes sont classées par ordre d'insertion. Si le pet_id est AUTO_INCREMENT, alors il est ordonné par le numéro automatique.la source
(owner_id, pet_id)
mais vous pouvez créer une clé(vet_id, pet_id[, owner_id])
pour utiliser un ordre de colonne différent.Astuce 1:
est parfaitement valable. Il présente l'avantage de performances d'être plus efficace lorsque de nombreuses requêtes doivent trouver plusieurs lignes
WHERE x = 123
. Autrement dit, il est légèrement plus efficace que le «évident»La seule règle concernant
AUTO_INCREMENT
(pour InnoDB) est qu'ilid
doit s'agir de la première colonne d' un index. Notez que cette règle ne dit rien à propos dePRIMARY
ouUNIQUE
ou 'seulement la colonne'.L'astuce est utile pour les énormes tables qui sont souvent récupérées
x
avec d'autres choses.Astuce 2: Supposons que vous ayez
Il s'agit d'un indice "couvrant":
Autrement dit, la requête entière peut être effectuée à l'intérieur du BTree de l'index. L'EXPLAIN dira "Utilisation de l'index".
la source