Abfragen nicht unbedingt gleichwertig
Um den Zusammenhang deutlich zu machen:
max(id)
schließtNULL
aus Werte. AberORDER BY ... LIMIT 1
nicht.NULL
Werte sortieren in aufsteigender Sortierreihenfolge zuletzt und in absteigender Reihenfolge zuerst. Also einIndex Scan Backward
findet möglicherweise nicht den größten Wert (gemäßmax()
) zuerst, aber eine beliebige Anzahl vonNULL
Werte.
Das formale Äquivalent von:
SELECT max(id) FROM testview;
ist nicht:
SELECT id FROM testview ORDER BY id DESC LIMIT 1;
aber:
SELECT id FROM testview ORDER BY id DESC NULLS LAST LIMIT 1;
Die letztere Abfrage erhält nicht den schnellen Abfrageplan. Aber es wäre mit einem Index mit passender Sortierreihenfolge:(id DESC NULLS LAST)
.
Anders bei den Aggregatfunktionen min()
und max()
. Diese erhalten einen schnellen Plan, wenn sie auf die Tabelle test1
abzielen direkt mit dem einfachen PK-Index auf (id)
. Aber nicht, wenn es auf der Ansicht basiert (oder direkt auf der zugrunde liegenden Join-Abfrage - die Ansicht ist nicht der Blocker). Ein Index, der NULL-Werte an der richtigen Stelle sortiert, hat kaum Auswirkungen.
Wir Kennen Sie diese id
in dieser Abfrage darf niemals NULL
sein . Die Spalte ist NOT NULL
definiert . Und der Join in der Ansicht ist effektiv ein INNER JOIN
die NULL
nicht einführen kann Werte für id
.
Wir auch wissen, dass der Index auf test.id
kann keine NULL-Werte enthalten.
Aber der Postgres-Abfrageplaner ist keine KI. (Das versucht es auch nicht, das könnte schnell außer Kontrolle geraten.) Ich sehe zwei Mängel :
min()
undmax()
den schnellen Plan nur erhalten, wenn auf die Tabelle abgezielt wird, unabhängig von der Sortierreihenfolge des Indexes, wird eine Indexbedingung hinzugefügt:Index Cond: (id IS NOT NULL)
ORDER BY ... LIMIT 1
bekommt den schnellen Plan nur mit der exakt passenden Index-Sortierreihenfolge.
Nicht sicher, ob das (einfach) verbessert werden könnte.
db<>fiddle hier - Demonstrieren aller oben genannten Punkte
Indizes
Dieser Index ist völlig nutzlos:
CREATE INDEX ON "test" ("id");
Die PK auf test.id
wird mit einem eindeutigen Index auf der Spalte implementiert, der bereits alles abdeckt, was der zusätzliche Index für Sie tun könnte.
Möglicherweise gibt es noch mehr, die darauf warten, dass die Frage geklärt wird.
Verzerrter Testfall
Der Testfall ist zu weit vom tatsächlichen Anwendungsfall entfernt, um sinnvoll zu sein.
Im Testaufbau hat jede Tabelle 100.000 Zeilen, es gibt keine Garantie dafür, dass jeder Wert in joincol
enthalten ist hat eine Übereinstimmung auf der anderen Seite, und beide Spalten können NULL sein
Ihr realer Fall hat 10 Millionen Zeilen in table1
und <100 Zeilen in table2
, jeder Wert in table1.joincol
hat eine Übereinstimmung in table2.joincol
, beide sind definiert NOT NULL
und table2.joincol
ist einzigartig. Eine klassische Eins-zu-Viele-Beziehung. Es sollte einen UNIQUE
geben Beschränkung auf table2.joincol
und eine FK-Einschränkung t1.joincol --> t2.joincol
.
Aber das ist derzeit alles in der Frage verdreht. Bereitstehen, bis das aufgeräumt ist.