PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Impatto delle prestazioni della vista sulla funzione aggregata rispetto alla limitazione del set di risultati

Query non strettamente equivalenti

Per chiarire il contesto:

  • max(id) esclude NULL i valori. Ma ORDER BY ... LIMIT 1 no.
  • NULL i valori ordinano per ultimo in ordine crescente e per primo in ordine decrescente. Quindi un Index Scan Backward potrebbe non trovare il valore massimo (secondo max() ) prima, ma un numero qualsiasi di NULL valori.

L'equivalente formale di:

SELECT max(id) FROM testview;

non è:

SELECT id FROM testview ORDER BY id DESC LIMIT 1;

ma:

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

Quest'ultima query non ottiene il piano di query rapido. Ma lo farebbe con un indice con ordinamento corrispondente:(id DESC NULLS LAST) .

È diverso per le funzioni aggregate min() e max() . Quelli ottengono un piano veloce quando prendono di mira la tabella test1 utilizzando direttamente l'indice PK semplice su (id) . Ma non quando si basa sulla vista (o direttamente sulla query di join sottostante:la vista non è il blocco). Un indice che ordina i valori NULL nel posto giusto non ha quasi alcun effetto.

Noi sappi che id in questa query non può mai essere NULL . La colonna è definita NOT NULL . E il join nella vista è effettivamente un INNER JOIN che non può introdurre NULL valori per id .
Noi sappi anche che l'indice su test.id non può contenere valori NULL.
Ma il pianificatore di query di Postgres non è un'intelligenza artificiale. (Né prova ad esserlo, potrebbe sfuggire di mano rapidamente.) Vedo due carenze :

  • min() e max() ottieni il piano veloce solo quando scegli come target la tabella, indipendentemente dall'ordinamento dell'indice, viene aggiunta una condizione dell'indice:Index Cond: (id IS NOT NULL)
  • ORDER BY ... LIMIT 1 ottiene il piano veloce solo con l'ordinamento dell'indice esattamente corrispondente.

Non sono sicuro se potrebbe essere migliorato (facilmente).

db<>violino qui - dimostrando tutto quanto sopra

Indici

Questo indice è completamente inutile:

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

Il PK su test.id è implementato con un indice univoco sulla colonna, che copre già tutto ciò che l'indice aggiuntivo potrebbe fare per te.

Potrebbero essercene altri, in attesa che la domanda si risolva.

Test case distorto

Il test case è troppo lontano dal caso d'uso effettivo per essere significativo.

Nella configurazione del test, ogni tabella ha 100.000 righe, non vi è alcuna garanzia che ogni valore in joincol ha una corrispondenza sull'altro lato ed entrambe le colonne possono essere NULL

Il tuo caso reale ha 10 milioni di righe in table1 e <100 righe in table2 , ogni valore in table1.joincol ha una corrispondenza in table2.joincol , entrambi sono definiti NOT NULL e table2.joincol è unico. Una classica relazione uno-a-molti. Dovrebbe esserci un UNIQUE vincolo su table2.joincol e un vincolo FK t1.joincol --> t2.joincol .

Ma questo è attualmente tutto contorto nella domanda. In attesa finché non viene ripulito.