sql >> Databasteknik >  >> RDS >> PostgreSQL

Prestandapåverkan av vyn på aggregatfunktion kontra begränsning av resultatuppsättningar

Frågor inte strikt likvärdiga

För att göra sammanhanget tydligt:

  • max(id) exkluderar NULL värden. Men ORDER BY ... LIMIT 1 inte.
  • NULL värden sorteras sist i stigande sorteringsordning och först i fallande. Alltså en Index Scan Backward kanske inte hittar det största värdet (enligt max() ) först, men valfritt antal NULL värden.

Den formella motsvarigheten till:

SELECT max(id) FROM testview;

är inte:

SELECT id FROM testview ORDER BY id DESC LIMIT 1;

men:

SELECT id FROM testview ORDER BY id DESC NULLS LAST LIMIT 1;

Den senare frågan får inte den snabba frågeplanen. Men det skulle med ett index med matchande sorteringsordning:(id DESC NULLS LAST) .

Det är annorlunda för de aggregerade funktionerna min() och max() . De får en snabb plan när de riktar in sig på tabellen test1 direkt med det vanliga PK-indexet på (id) . Men inte när den baseras på vyn (eller den underliggande join-frågan direkt - vyn är inte blockeraren). Ett index som sorterar NULL-värden på rätt plats har knappast någon effekt.

Vi vet att id i den här frågan kan aldrig vara NULL . Kolumnen är definierad NOT NULL . Och sammanfogningen i vyn är faktiskt en INNER JOIN som inte kan introducera NULL värden för id .
Vi vet också att indexet på test.id kan inte innehålla NULL-värden.
Men Postgres frågeplanerare är inte en AI. (Det försöker det heller inte vara, det kan snabbt gå ur händerna.) Jag ser två brister :

  • min() och max() få den snabba planen endast när du riktar in tabellen, oavsett indexsorteringsordning, läggs ett indexvillkor till:Index Cond: (id IS NOT NULL)
  • ORDER BY ... LIMIT 1 får den snabba planen endast med exakt matchande indexsorteringsordning.

Inte säker på om det kan förbättras (lätt).

db<>fiol här - demonstrera allt ovan

Index

Detta index är helt värdelöst:

CREATE INDEX ON "test" ("id");

PK på test.id implementeras med ett unikt index på kolumnen, som redan täcker allt det extra indexet kan göra för dig.

Det kan finnas fler som väntar på att frågan ska klarna upp.

Förvrängt testfall

Testfallet är för långt bort från det faktiska användningsfallet för att vara meningsfullt.

I testinställningen har varje tabell 100 000 rader, det finns ingen garanti för att varje värde i joincol har en matchning på andra sidan, och båda kolumnerna kan vara NULL

Ditt riktiga fall har 10 miljoner rader i table1 och <100 rader i table2 , varje värde i table1.joincol har en matchning i table2.joincol , båda är definierade NOT NULL och table2.joincol är unik. En klassisk en-till-många-relation. Det bör finnas en UNIQUE begränsning på table2.joincol och en FK-begränsning t1.joincol --> t2.joincol .

Men det är just nu allt vridet i frågan. Stanna tills det är städat.



  1. UTL_SMTP skillnad mellan DATA, WRITE_DATA och WRITE_RAW_DATA

  2. Kan Mysql dela en kolumn?

  3. MySQL SELECT vanligast efter grupp

  4. Hur man använder förberedda uttalanden med Postgres