Vragen niet strikt gelijkwaardig
Om de context duidelijk te maken:
max(id)
exclusiefNULL
waarden. MaarORDER BY ... LIMIT 1
niet.NULL
waarden worden als laatste in oplopende sorteervolgorde gesorteerd en als eerste in aflopende volgorde. Dus eenIndex Scan Backward
vindt mogelijk niet de grootste waarde (volgensmax()
) eerst, maar een willekeurig aantalNULL
waarden.
Het formele equivalent van:
SELECT max(id) FROM testview;
is niet:
SELECT id FROM testview ORDER BY id DESC LIMIT 1;
maar:
SELECT id FROM testview ORDER BY id DESC NULLS LAST LIMIT 1;
De laatste query krijgt niet het snelle queryplan. Maar het zou met een index met overeenkomende sorteervolgorde:(id DESC NULLS LAST)
.
Dat is anders voor de aggregatiefuncties min()
en max()
. Die krijgen een snel plan bij het targeten van tabel test1
rechtstreeks met behulp van de gewone PK-index op (id)
. Maar niet wanneer deze gebaseerd is op de weergave (of de onderliggende join-query rechtstreeks - de weergave is niet de blokkering). Een index die NULL-waarden op de juiste plaats sorteert, heeft nauwelijks effect.
Wij weet dat id
in deze zoekopdracht kan nooit NULL
zijn . De kolom is gedefinieerd NOT NULL
. En de join in de weergave is in feite een INNER JOIN
die NULL
niet kan introduceren waarden voor id
.
Wij weet ook dat de index op test.id
mag geen NULL-waarden bevatten.
Maar de Postgres-queryplanner is geen AI. (En dat probeert het ook niet te zijn, dat zou snel uit de hand kunnen lopen.) Ik zie twee tekortkomingen :
min()
enmax()
krijg het snelle plan alleen wanneer u de tabel target, ongeacht de indexsorteervolgorde, een indexvoorwaarde wordt toegevoegd:Index Cond: (id IS NOT NULL)
ORDER BY ... LIMIT 1
krijgt het snelle plan alleen met de exact overeenkomende index-sorteervolgorde.
Ik weet niet zeker of dat (gemakkelijk) verbeterd kan worden.
db<>fiddle hier - al het bovenstaande demonstreren
Indexen
Deze index is volkomen nutteloos:
CREATE INDEX ON "test" ("id");
De PK op test.id
is geïmplementeerd met een unieke index op de kolom, die al alles dekt wat de extra index voor u zou kunnen doen.
Er kunnen er meer zijn, wachtend tot de vraag is opgelost.
Vervormde testcase
De testcase is te ver verwijderd van de daadwerkelijke use case om zinvol te zijn.
In de testopstelling heeft elke tabel 100k rijen, er is geen garantie dat elke waarde in joincol
heeft een overeenkomst aan de andere kant, en beide kolommen kunnen NULL zijn
Uw echte geval heeft 10 miljoen rijen in table1
en <100 rijen in table2
, elke waarde in table1.joincol
heeft een overeenkomst in table2.joincol
, beide zijn gedefinieerd NOT NULL
, en table2.joincol
is uniek. Een klassieke één-op-veel relatie. Er moet een UNIQUE
. zijn beperking op table2.joincol
en een FK-beperking t1.joincol --> t2.joincol
.
Maar dat is momenteel allemaal verdraaid in de vraag. Klaarstaan tot dat opgeruimd is.