sql >> Database >  >> RDS >> PostgreSQL

Prestatie-impact van weergave op geaggregeerde functie versus beperking van resultaatset

Vragen niet strikt gelijkwaardig

Om de context duidelijk te maken:

  • max(id) exclusief NULL waarden. Maar ORDER BY ... LIMIT 1 niet.
  • NULL waarden worden als laatste in oplopende sorteervolgorde gesorteerd en als eerste in aflopende volgorde. Dus een Index Scan Backward vindt mogelijk niet de grootste waarde (volgens max() ) eerst, maar een willekeurig aantal NULL 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() en max() 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.



  1. Testen van PostgreSQL-functies die refcursor verbruiken en retourneren

  2. Lees e-mail immap php

  3. 7645 Null of leeg predikaat met volledige tekst

  4. Waarom werkt invoegen niet en wordt er geen fout weergegeven op postresql?