Angenommen, ich habe eine 1-zu-N-Beziehung (person_id, pet_id)
. Ich habe eine Tabelle, in der pet_id
sich der Primärschlüssel befindet.
Ich verstehe, dass ein InnoDB-Sekundärindex im Wesentlichen ein B-Baum ist, in dem die Werte die entsprechenden Primärschlüsselwerte für die Zeile sind.
Angenommen, eine Person kann Tausende von Haustieren haben, und ich möchte oft die Haustiere einer Person in der Reihenfolge von pet_id
. Dann wäre es wichtig, ob Datensätze im Sekundärindex nach (person_id, pet_id)
oder nur person_id
mit den pet_id
's sortiert werden , person_id
die unsortiert sind. Ich rate das später.
Wenn dies person_id
nicht eindeutig ist, werden Datensätze physisch nach (person_id, pet_id)
oder NUR sortiert pet_id
?
Vielen Dank
mysql
innodb
primary-key
clustered-index
user3391564
quelle
quelle
person_id
nicht eindeutig sind, werden Datensätze physisch nach(person_id, pet_id)
oder NUR sortiertperson_id
?"Antworten:
Nein. Wenn Ihre Tabelle über die InnoDB-Engine und die
PRIMARY KEY
is verfügt(pet_id)
, definiert die Definition eines Sekundärindex keinen(person_id)
oder(person_id, pet_id)
keinen Unterschied.Der Index enthält auch die
pet_id
Spalte, sodass die Werte wie(person_id, pet_id)
in beiden Fällen sortiert sind.Eine Abfrage wie die, die Sie haben:
muss nur auf den Index zugreifen, um die Werte zu erhalten, und noch mehr, es muss keine Sortierung durchgeführt werden, da die
pet_id
Werte bereits im Index sortiert sind. Sie können dies überprüfen, indem Sie sich die Ausführungspläne (EXPLAIN
) ansehen :Zuerst versuchen wir es mit einer MyISAM-Tabelle:
Beachten Sie die Dateisortierung!
Jetzt MyISAM mit zusammengesetztem Index:
Filesort ist wie erwartet weg .
Versuchen wir jetzt dasselbe mit der InnoDB-Engine:
Auch kein Dateisort! Obwohl der Index die
pet_id
Spalte nicht explizit enthält, sind die Werte vorhanden und sortiert. Sie können überprüfen , dass , wenn Sie den Index mit definieren(person_id, pet_id)
, dieEXPLAIN
identisch ist.Machen wir es tatsächlich mit InnoDB und dem zusammengesetzten Index:
Identische Pläne mit dem vorherigen Fall.
Um 100% sicher zu sein, führe ich auch die letzten beiden Fälle aus (InnoDB-Engine mit einzelnen und zusammengesetzten Indizes), um die
file_per_table
Einstellung zu ermöglichen und der Tabelle einige tausend Zeilen hinzuzufügen:In beiden Fällen führt die Überprüfung der tatsächlichen Dateigrößen zu identischen Ergebnissen :
quelle
(<some_column>)
und(<some_column>, <pk>)
weilON (<some_column>)
äquivalent zuON (<some_column>) INCLUDE (<pk>)
und nichtON (<some_column>, <pk>)
. In den meisten Fällen hat dies so ziemlich Null Bedeutung, aber wenn Ihr PK zufällig ist (dh ein UUID) , dannON (<s_c>,<pk>)
können zusätzliche Fragmentierung führen oder wenn die PK andere sinnvoll ist , als ein Schlüssel zu sein und man könnteORDER BY s_c, pk
dann wird eine solche Art schneller als der Index ist schon voll in ordnung.INCLUDE (columns)
Funktionalität. Das ist ein weiterer Grund, warum ich zu dem Schluss gekommen bin, dass der(s_c)
Index äquivalent zu ist(s_c, pk)
.Gemäß der MySQL-Dokumentation zu den Cluster- und Sekundärindizes
Daher ist das Hinzufügen des PRIMARY KEY zu einem Sekundärindex definitiv redundant. Ihr Indexeintrag möchte
(person_id, pet_id, pet_id)
. Dies würde auch den Sekundärindex unnötig aufblähen, indem 2 Kopien desPRIMARY KEY
.Für den Index mit
(person_id)
, wenn Sie eine Abfrage wie diese ausführen würdenDer
PRIMARY KEY
würde sich voll und ganz mit dieser Abfrage beschäftigen und die vonPRIMARY KEY
ohnehin geordneten Ergebnisse erzeugen . Aus physikalischer Sicht sind die Zeilen nach Einfügereihenfolge geordnet. Wenn die pet_id AUTO_INCREMENT ist, wird sie nach der automatischen Nummer sortiert.quelle
(owner_id, pet_id)
aber einen Schlüssel erstellen können, um eine(vet_id, pet_id[, owner_id])
andere Spaltenreihenfolge zu verwenden.Tipp 1:
ist vollkommen gültig. Es hat den Leistungsvorteil, effizienter zu sein, wenn viele Abfragen mehrere Zeilen finden müssen
WHERE x = 123
. Das heißt, es ist etwas effizienter als das "Offensichtliche"Die einzige Regel
AUTO_INCREMENT
(für InnoDB) ist,id
dass die erste Spalte in einem Index sein muss. Beachten Sie, dass diese Regel nichts überPRIMARY
oderUNIQUE
oder "nur Spalte" sagt .Der Tipp ist nützlich für große Tische, die oft
x
zusammen mit anderen Dingen abgerufen werden .Tipp 2: Angenommen, Sie haben
Dies ist ein "abdeckender" Index:
Das heißt, die gesamte Abfrage kann im BTree des Index durchgeführt werden. Das EXPLAIN sagt "Using index".
quelle