Ist ein zusammengesetzter Index auch für Abfragen im ersten Feld geeignet?


86

Nehmen wir an, ich habe eine Tabelle mit Feldern Aund B. Ich stelle regelmäßig Abfragen zu A+ B, also habe ich einen zusammengesetzten Index zu erstellt (A,B). Würden nur Abfragen über Aden zusammengesetzten Index auch vollständig optimiert?

Außerdem habe ich einen Index für erstellt A, aber Postgres verwendet den zusammengesetzten Index nur für Abfragen für A. Wenn die vorherige Antwort positiv ist, spielt es vermutlich keine Rolle, aber warum wird standardmäßig der zusammengesetzte Index ausgewählt, wenn der einzelne AIndex verfügbar ist?


Ich habe versucht, einen kleinen Test dafür einzurichten. In meinem Fall wurde der zweispaltige Index jedoch nur verwendet, wenn ich den einspaltigen Index gelöscht habe, unabhängig davon, welcher zuerst erstellt wurde. Es ist interessant, dass der ursprüngliche Plan, wenn ich zuerst den zweispaltigen Index erstellt habe, einen Bitmap-Heap-Scan verwendet hat. Wenn ich den einspaltigen Index erstellt habe, führen Sie die Abfrage aus (Verwendeter Index-Scan) und löschen Sie den neu erstellten Index. Der Plan mit dem zweispaltigen Index wurde auf Index-Scan umgestellt. Siehe die Schritte auf SQLFiddle
dezso

@dezso Interessant. Wo liegen die Kosten für jede Abfrage?
Luciano

Bitmap-Index-Scan-Kosten: 107,98, 43 ms Ausführungszeit. Index-Scan einspaltig: Kosten 8,69, zweispaltig: 43,69. Die Ausführungszeiten unterscheiden sich nicht signifikant (die Fluktuation ist größer als die Differenz zwischen den beiden).
Dezso

@Luciano Können Sie den explain analyzeund den Abfragetext anzeigen ?
Craig Ringer

Antworten:


88

Es ist sicherlich. Wir haben das unter dieser verwandten Frage ausführlich besprochen:

Der Speicherplatz wird in Vielfachen von MAXALIGN8 Byte auf einem 64-Bit-Betriebssystem oder (viel seltener) 4 Byte auf einem 32-Bit-Betriebssystem zugewiesen . Wenn Sie sich nicht sicher sind, überprüfen Sie pg_controldata. Dies hängt auch von den Datentypen der indizierten Spalten (einige erfordern Ausrichtungsabstände) und dem tatsächlichen Inhalt ab.

Ein Index für beispielsweise zwei integerSpalten (jeweils 4 Byte) ist in der Regel genau so groß wie ein Index für nur eine Spalte, bei dem weitere 4 Byte durch Ausrichtungsauffüllung verloren gehen.

In einem solchen Fall hat der Abfrageplaner wirklich keinen Nachteil, einen Index für zu verwenden (a,b)- im Vergleich zu einem Index für nur (a). Im Allgemeinen ist es für mehrere Abfragen vorzuziehen, denselben Index zu verwenden. Die Chance, dass es (oder Teile davon) sich im (schnellen) Cache befinden, wächst, wenn es gemeinsam genutzt wird.

Wenn Sie bereits einen Index für pflegen (a,b), ist es nicht sinnvoll, einen weiteren Index nur für zu erstellen (a)- es sei denn, er ist wesentlich kleiner. Das gleiche gilt nicht für wahr (b,a)vs. (a). Folgen Sie dem Link in der ersten Zeile, um mehr darüber zu erfahren.

Wenn Sie aus der entgegengesetzten Richtung kommen und einen solchen zusätzlichen Index benötigen, ziehen Sie in (a,b)Betracht, einen vorhandenen Index nur auf (a)- wenn möglich - abzulegen. Oft nicht möglich, da dies der Index einer PK oder eines UNIQUEConstraints ist. Seit Postgres 11 müssen Sie möglicherweise stattdessen nur bnoch die Einschränkungsdefinition mit der INCLUDEKlausel anhängen . Details im Handbuch.

Oder erstellen Sie (b,a)stattdessen den neuen Index am , um Abfragen nur bzusätzlich abzudecken . Für Gleichheitsbedingungen spielt die Reihenfolge der Indexausdrücke in Btree-Indizes keine Rolle. Dies ist jedoch bei Bereichsbedingungen der Fall. Sehen:

Das Einfügen zusätzlicher Spalten in einen Index birgt potenzielle Nachteile , auch wenn nur der Platz verwendet wird, der ansonsten durch Ausrichtungsauffüllung verloren geht:

  • Immer wenn die zusätzliche Spalte aktualisiert wird, muss der Index jetzt ebenfalls aktualisiert werden, wodurch möglicherweise zusätzliche Kosten für Schreibvorgänge anfallen und der Index aufgebläht wird.
  • HOT-Updates (Heap Only Tuple) für die Tabelle sind nicht möglich, solange eine Indexspalte beteiligt ist.

Mehr zu HOT Updates:

So messen Sie Objektgrößen:


1
Könnten Sie dies so erweitern, dass der Index A gelöscht werden sollte, wenn ich einen Index für Spalte A habe und ein Bedarf besteht, einen zusammengesetzten Index (A, B) hinzuzufügen? Wenn die Wiederverwendung eines Index die Cache-Effizienz verbessert und (A, B) A vollständig optimiert, scheint ein zusätzlicher Index für A Speicherplatz zu verschwenden und möglicherweise zu verlangsamen
jvans

1
@jvans: Im Allgemeinen wahr - mit bemerkenswerten Ausnahmen und Alternativen. Ich habe einen Absatz hinzugefügt, um das anzusprechen.
Erwin Brandstetter

2

Entsprechend Ihrer Frage haben Sie eine Tabelle mit den Feldern A und B. Wenn Ihre Frage lautet:

SELECT * FROM [YOUR TBL]
WHERE A='XXXX'

Optimierer wählt den zusammengesetzten Index, um zufälligen Zugriff zu vermeiden!


-4

Dies ist der Fall, wenn Sie nur das erste Prädikat verwenden.

Es wird gescannt, wenn Sie die ersten Spalten des zusammengesetzten Schlüssels und die Nichtschlüsselspalte des zusammengesetzten Schlüssels verwenden.

Um es auszutricksen, können Sie einfach Prädikate wie diese und dann eine Spalte ohne Schlüssel kopieren:

[A, B] ist Ihr Index, [C] - eine andere Spalte

Um den Index zu verwenden, schreiben Sie als:

SELECT
    A,B,C,D,E
FROM 
    test
WHERE
   A=1
AND
   B=B
AND 
   C=3

... warum wird standardmäßig der zusammengesetzte Index ausgewählt, wenn der einzelne A-Index verfügbar ist?

Der Index wird nur verwendet, wenn ein oder zwei Prädikate [A] oder [A], [B] vorhanden sind. Es wird nicht in der Reihenfolge [B], [A] oder [A], [C] verwendet. Um den Index mit der zusätzlichen Spalte [C] verwenden zu können, müssen Sie den Index erzwingen, indem Sie Prädikate wie [A], [B] und [C] anordnen.


2
Was genau erreichen Sie mit B=B? Ich denke, du erreichst nichts, also stimme ich ab, wenn keine Beweise vorliegen, die nicht nur vom Optimierer ignoriert werden
Jack Douglas

2
B=Bist effektiv das gleiche wie B IS NOT NULL, was unangebracht scheint. Sicherlich nicht erforderlich, um einen Index für zu verwenden (a,b).
Erwin Brandstetter
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.