Ich habe darüber gelesen composite indexes
und bin etwas verwirrt über die Bestellung. Diese Dokumentation (etwas weniger als die Hälfte) sagt
Im Allgemeinen sollten Sie die Spalte, von der erwartet wird, dass sie am häufigsten verwendet wird, zuerst in den Index aufnehmen.
Doch kurz danach heißt es
Erstellen Sie einen zusammengesetzten Index, in dem die selektivste Spalte an erster Stelle steht. das ist die Spalte mit den meisten Werten.
Oracle sagt es auch hier mit anderen Worten
Wenn alle Schlüssel in WHERE-Klauseln gleich häufig verwendet werden, wird die Abfrageleistung am besten verbessert, wenn diese Schlüssel in der Anweisung CREATE INDEX von am selektivsten zu am wenigsten selektiv sortiert werden.
Ich habe jedoch eine SO-Antwort gefunden , die anders aussagt. Es sagt
Ordnen Sie die Spalten mit der am wenigsten ausgewählten Spalte zuerst und der am meisten ausgewählten Spalte zuletzt an. Im Falle eines Unentschieden führen Sie mit der Säule, die eher für sich allein verwendet wird.
Die erste Dokumentation, auf die ich verwiesen habe, besagt, dass Sie zuerst die am häufigsten verwendete verwenden sollten, während die SO-Antwort besagt, dass dies nur zum Brechen von Krawatten sein sollte. Dann unterscheiden sie sich auch in der Bestellung.
Diese Dokumentation spricht auch über skip scanning
und sagt
Das Überspringen von Scans ist vorteilhaft, wenn in der ersten Spalte des zusammengesetzten Index nur wenige unterschiedliche Werte und im nicht führenden Schlüssel des Index viele unterschiedliche Werte vorhanden sind.
Ein anderer Artikel sagt
Die Präfixspalte sollte die unterscheidendste und in Abfragen am häufigsten verwendete sein
Was meiner Meinung nach am diskriminierendsten ist, würde am unterscheidendsten bedeuten.
All diese Nachforschungen führen mich immer noch zu derselben Frage. sollte die selektivste Spalte zuerst oder zuletzt sein? Sollte die erste Spalte bei einem Gleichstand die am häufigsten verwendete und nur die selektivste sein?
Diese Artikel scheinen sich zu widersprechen, aber sie bieten einige Beispiele. Nach allem, was ich gesammelt habe, scheint es effizienter least selective column
zu sein, als Erster in der Bestellung zu sein, wenn Sie damit rechnen Index Skip Scans
. Aber ich bin mir nicht sicher, ob das richtig ist.
quelle
Antworten:
Von AskTom
Eines der Argumente für das Anordnen von Spalten im zusammengesetzten Index in der Reihenfolge von den am wenigsten unterscheidenden (weniger unterschiedlichen Werten) bis zu den am meisten unterscheidenden (mehr unterschiedlichen Werten) ist die Komprimierung von Indexschlüsseln.
Laut Indexstatistik ist der erste Index komprimierbarer.
Zum anderen wird der Index in Ihren Abfragen verwendet. Wenn Ihre Abfragen meistens verwenden
col1
,Wenn Sie beispielsweise Fragen haben,
select * from t where col1 = :a and col2 = :b;
select * from t where col1 = :a;
-dann
index(col1,col2)
würde besser abschneiden .Wenn Ihre Abfragen meistens verwenden
col2
,select * from t where col1 = :a and col2 = :b;
select * from t where col2 = :b;
-dann
index(col2,col1)
würde besser abschneiden . Wenn alle Ihre Abfragen immer beide Spalten angeben, spielt es keine Rolle, welche Spalte im zusammengesetzten Index an erster Stelle steht.Zusammenfassend lässt sich sagen, dass die wichtigsten Überlegungen bei der Spaltenreihenfolge des zusammengesetzten Index die Komprimierung des Indexschlüssels sind und wie Sie diesen Index in Ihren Abfragen verwenden werden.
Verweise:
quelle
Das selektivste zuerst ist nur dann sinnvoll, wenn sich diese Spalte in der tatsächlichen WHERE-Klausel befindet.
Wenn SELECT von einer größeren Gruppe (weniger selektiv) und möglicherweise von anderen, nicht indizierten Werten stammt, kann ein Index mit weniger selektiven Spalten dennoch nützlich sein (wenn es einen Grund gibt, keinen weiteren zu erstellen).
Wenn es eine Tischadresse gibt, mit
COUNTRY CITY STREET, noch etwas ...
Indizieren von STREET, CITY, COUNTRY liefert die schnellsten Abfragen mit einem Straßennamen. Wenn jedoch alle Straßen einer Stadt abgefragt werden, ist der Index unbrauchbar und die Abfrage führt wahrscheinlich einen vollständigen Tabellenscan durch.
Die Indizierung von COUNTRY, CITY, STREET kann für einzelne Straßen etwas langsamer sein, aber der Index kann für andere Abfragen verwendet werden, wobei nur nach Land und / oder Stadt ausgewählt wird.
quelle
Bei der Auswahl der Reihenfolge der Indexspalten gilt Folgendes:
Gibt es (Gleichheits-) Prädikate für diese Spalte in meinen Abfragen?
Wenn eine Spalte in einer where-Klausel niemals vorkommt, lohnt es sich nicht, sie zu indizieren (1)
OK, Sie haben also eine Tabelle und Abfragen für jede Spalte. Manchmal mehr als eins.
Wie entscheiden Sie, was Sie indizieren möchten?
Schauen wir uns ein Beispiel an. Hier ist eine Tabelle mit drei Spalten. Einer enthält 10 Werte, weitere 1.000, die letzten 10.000:
Dies sind Zahlen, die mit Nullen aufgefüllt bleiben. Auf diese Weise können Sie später auf die Komprimierung eingehen.
Sie haben also drei häufig gestellte Fragen:
Was indexierst du?
Ein Index für nur wenige Werte ist nur unwesentlich besser als ein vollständiger Tabellenscan:
Es ist also unwahrscheinlich, dass es sich lohnt, eine eigene Indexierung vorzunehmen. Abfragen auf lots_vals geben nur wenige Zeilen zurück (in diesem Fall nur 1). Das ist also definitiv eine Indizierung wert.
Aber was ist mit den Abfragen für beide Spalten?
Sollten Sie indizieren:
ODER
Fangfrage!
Die Antwort ist weder.
Sicher, few_vals ist eine lange Zeichenfolge. Sie können also eine gute Komprimierung erzielen. Und Sie erhalten (möglicherweise) einen Index-Skip-Scan für die Abfragen mit (few_vals, lots_vals), die nur Prädikate für lots_vals enthalten. Aber ich bin nicht hier, obwohl es deutlich besser abschneidet als ein vollständiger Scan:
Spielen Sie gerne? (2)
Sie benötigen also weiterhin einen Index mit lots_vals als führende Spalte. Und zumindest in diesem Fall erledigt der zusammengesetzte Index (wenige, Lose) die gleiche Menge an Arbeit wie einer an nur (Losen).
In einigen Fällen werden Sie durch den zusammengesetzten Index 1-2 E / A-Vorgänge sparen. Aber lohnt es sich, zwei Indizes für diese Einsparung zu haben?
Und es gibt ein weiteres Problem mit dem zusammengesetzten Index. Vergleichen Sie den Clustering-Faktor für die drei Indizes, einschließlich LOTS_VALS:
Beachten Sie, dass der Clustering-Faktor für wenige_Lose 10x höher ist als für Lose und Lose_Wenige! Und das ist in einer Demo-Tabelle mit perfektem Clustering zu Beginn. In Datenbanken der realen Welt ist der Effekt wahrscheinlich schlechter.
Was ist daran so schlimm?
Der Clustering-Faktor ist einer der Schlüsseltreiber für die Attraktivität eines Index. Je höher dieser Wert ist, desto unwahrscheinlicher ist es, dass der Optimierer ihn auswählt. Insbesondere, wenn lots_vals nicht eindeutig sind, aber normalerweise nur wenige Zeilen pro Wert enthalten. Wenn Sie Pech haben, könnte dies ausreichen, um den Optimierer zu veranlassen, einen vollständigen Scan für billiger zu halten ...
OK, also haben zusammengesetzte Indizes mit few_vals und lots_vals nur Vorteile in Bezug auf Groß- und Kleinschreibung.
Was ist mit Abfragen, die wenige_Werte und viele_Werte filtern?
Einzelne Spaltenindizes bieten nur geringe Vorteile. Zusammen liefern sie jedoch nur wenige Werte. Ein zusammengesetzter Index ist also eine gute Idee. Aber in welche Richtung?
Wenn Sie einige zuerst platzieren, wird diese durch Komprimieren der führenden Spalte kleiner
Mit weniger unterschiedlichen Werten in der führenden Spalte wird besser komprimiert. Es ist also etwas weniger Arbeit, diesen Index zu lesen. Aber nur geringfügig. Und beide sind bereits ein gutes Stück kleiner als das Original (25% Größenreduzierung).
Und Sie können noch weiter gehen und den gesamten Index komprimieren!
Jetzt haben beide Indizes wieder dieselbe Größe. Beachten Sie, dass dies die Tatsache ausnutzt, dass es eine Beziehung zwischen wenigen und vielen gibt. Wieder ist es unwahrscheinlich, dass Sie diese Art von Nutzen in der realen Welt sehen werden.
Bisher haben wir nur über Gleichstellungsprüfungen gesprochen. Bei zusammengesetzten Indizes tritt häufig eine Ungleichung mit einer der Spalten auf. zB Abfragen wie "Aufträge / Lieferungen / Rechnungen für einen Kunden in den letzten N Tagen abrufen".
Wenn Sie diese Art von Abfragen haben, möchten Sie die Gleichheit mit der ersten Spalte des Index:
Beachten Sie, dass sie den entgegengesetzten Index verwenden.
TL; DR
1: In einigen Fällen kann es sinnvoll sein, eine Spalte in einen Index aufzunehmen, wenn dies bedeutet, dass sich alle Spalten in Ihrer Abfrage im Index befinden. Dadurch wird nur ein Index-Scan aktiviert, sodass Sie nicht auf die Tabelle zugreifen müssen.
2: Wenn Sie für Diagnostics and Tuning lizenziert sind, können Sie den Plan mit SQL Plan Management zu einem Skip-Scan zwingen
ADDEDNDA
PS - die Dokumente, die Sie dort zitiert haben, stammen von 9i. Das ist wirklich alt. Ich würde Stick mit etwas aktuellere
quelle
select count (distinct few_vals || ':' || many_vals || ':' || lots_vals )
wirklich üblich? Lässt Oracle die Syntax nicht zuselect count (distinct few_vals, many_vals, lots_vals )
- die keine Verkettung von Zeichenfolgen vornimmt, die Spalten nicht als Texttypen benötigt und nicht auf die Abwesenheit von:
Zeichen angewiesen ist ?count ( distinct x, y, z )
In Oracle ist das nicht möglich. Sie müssen also eine bestimmte Unterabfrage durchführen und die Ergebnisse oder eine Verkettung wie oben zählen. Ich habe es gerade hier gemacht, um einen Tabellenzugriff zu erzwingen (anstatt nur einen Index zu scannen) und nur eine Zeile im Ergebnis zu habenEs gibt weitere Elemente der Abfrage, die zur endgültigen Entscheidung beitragen, womit ein zusammengesetzter Index beginnen und / oder neben der Selektivität der Spalte enthalten soll.
beispielsweise:
">,> =, <, <=" haben
Um die Konversation dennoch relevant zu halten, gilt die unten stehende Antwort für die folgende Situation:
string"
Meiner Erfahrung nach sollte DBA beides berücksichtigen.
1) Wenn ich einen Index erstelle, dessen selektivste Spalte jedoch von den meisten Abfragen in dieser Tabelle nicht verwendet wird, ist dies für die Datenbank-Engine nicht sinnvoll.
2) Wenn ich einen Index mit der am häufigsten verwendeten Spalte in einer Abfrage erst im Index anlege, die Spalte jedoch eine geringe Selektivität aufweist, ist auch meine Abfrageleistung nicht gut.
Ich werde Spalten auflisten, die in 90% der Tabellenabfragen am häufigsten verwendet werden. Dann setzen Sie diese nur in der Reihenfolge der meisten Kardinalität auf die geringste Kardinalität.
Wir verwenden Indizes, um die Leistung von Leseabfragen zu verbessern, und dieser Workflow (Arten von Leseabfragen) sollte nur die Indexerstellung vorantreiben. Tatsächlich kann der komprimierte Index mit wachsender Datenmenge (Milliarden von Zeilen) zwar Speicherplatz sparen, die Leseabfrageleistung jedoch beeinträchtigen.
quelle
Theoretisch ergibt die selektivste Spalte die schnellste Suche. Aber bei der Arbeit bin ich nur auf eine Situation gestoßen, in der wir einen zusammengesetzten Index von 3 Teilen haben, wobei der selektivste Teil zuerst steht. (Datum, Autor, Verlag sagen wir mal, in dieser Reihenfolge überwacht die Tabelle die Daumen nach oben bei Beiträgen) und ich habe eine Abfrage, die alle drei Teile verwendet. Mysql verwendet standardmäßig den Autorenindex, wobei der zusammengesetzte Index mit Firma und Datum übersprungen wird, obwohl er in meiner Abfrage vorhanden ist. Ich habe Force-Index verwendet, um das Composite zu verwenden, und die Abfrage wurde tatsächlich langsamer ausgeführt. Warum ist das passiert? Ich werde dir sagen:
Ich habe einen Bereich am Datum ausgewählt, und obwohl das Datum sehr selektiv ist, hat die Tatsache, dass wir ihn für Bereichsscans verwenden (obwohl der Bereich relativ kurz ist, 6 Monate von 6 Jahren Daten), den Verbund für schädlich gemacht MySQL. Um das Composite in diesem speziellen Fall zu verwenden, muss mysql alle Artikel abrufen, die seit Neujahr geschrieben wurden, und sich dann damit befassen, wer der Autor ist. Da der Autor nicht so viele Artikel im Vergleich zu anderen Autoren geschrieben hat, hat mysql es vorgezogen, nur diesen Autor zu finden .
In einem anderen Fall lief die Abfrage auf dem Composite sehr viel schneller. Damals war ein Autor äußerst beliebt und besaß die meisten Datensätze. Eine Sortierung nach Datum war sinnvoll. Aber MySQL hat diesen Fall nicht automatisch erkannt. Ich musste den Index erzwingen. Bereichsscans können Ihre selektive Spalte unbrauchbar machen. Die Verteilung der Daten kann zu Fällen führen, in denen Spalten für verschiedene Datensätze selektiver sind ...
Was ich anders machen würde, ist, das Datum (was theoretisch am selektivsten ist) nach rechts zu verschieben, da ich weiß, dass ich jetzt einen Entfernungsscan durchführen werde, und das macht einen Unterschied.
quelle
WHERE (date BETWEEN @x AND @y) AND (author = @a) AND (publishing company = @p)
ein Index für(author, publishing_company, date)
oder(publishing_company, author, date)
für besser und würde verwendet werden - ohne ihn zu erzwingen.Unterschiedliche Fälle für unterschiedliche Situationen. Kennen Sie Ihr Ziel; Erstellen Sie dann Ihre Indizes und führen Sie Erklärungspläne für jeden aus, um die beste Antwort für Ihre Situation zu erhalten.
quelle
Aus der Spaltenreihenfolge im Index auf Ask Tom:
Stimmen Sie zu, dass wir Spalten basierend auf der where-Klausel sortieren müssen, aber die Aussage "(Selektivität von a oder b zählt überhaupt nicht)" ist nicht korrekt ("where-Klausel")
quelle