Ho pubblicato il tuo piano di query su describe.depesz.com, dai un'occhiata.
Le stime del pianificatore di query in alcuni punti sono terribilmente errate. Hai eseguito ANALYZE
di recente?
Leggi i capitoli del manuale sulle statistiche utilizzate dal pianificatore e sulle costanti di costo del pianificatore. Presta particolare attenzione ai capitoli su random_page_cost
e default_statistics_target
.
Puoi provare:
ALTER TABLE diplomas ALTER COLUMN number SET STATISTICS 1000;
ANALYZE diplomas;
Oppure vai ancora più in alto per una tabella con 10 milioni di righe. Dipende dalla distribuzione dei dati e dalle query effettive . Sperimentare. Il valore predefinito è 100, il massimo è 10000.
Per un database di quelle dimensioni, solo 1 o 5 MB di work_mem
generalmente non sono sufficienti. Leggi la pagina Wiki di Postgres su Tuning Postgres a cui @aleroot si è collegato.
Poiché la tua query ha bisogno di 430104 kB di memoria su disco secondo EXPLAIN
output, devi impostare work_mem
a qualcosa come 500 MB o più per consentire l'ordinamento in memoria. La rappresentazione in memoria dei dati richiede più spazio rispetto alla rappresentazione su disco. Potresti essere interessato a ciò che Tom Lane ha pubblicato di recente sull'argomento.
work_mem
in aumento solo un po', come hai provato tu, non aiuterà molto o può anche rallentare. Impostarlo su un livello elevato a livello globale può persino far male, specialmente con l'accesso simultaneo. Più sessioni potrebbero affamare l'un l'altro per le risorse. L'allocazione di più per uno scopo sottrae memoria a un altro se la risorsa è limitata. La migliore configurazione dipende dalla situazione completa.
Per evitare effetti collaterali, impostalo solo sufficientemente alto localmente nella tua sessione e temporaneamente per la query:
SET work_mem = '500MB';
Ripristina le impostazioni predefinite in seguito:
RESET work_mem;
Oppure usa SET LOCAL
per impostarlo solo per iniziare la transazione corrente.