Come ottimizzare le query postgres
-
21-12-2019 - |
Domanda
Sto eseguendo la seguente query:
SELECT fat.*
FROM Table1 fat
LEFT JOIN modo_captura mc ON mc.id = fat.modo_captura_id
INNER JOIN loja lj ON lj.id = fat.loja_id
INNER JOIN rede rd ON rd.id = fat.rede_id
INNER JOIN bandeira bd ON bd.id = fat.bandeira_id
INNER JOIN produto pd ON pd.id = fat.produto_id
INNER JOIN loja_extensao le ON le.id = fat.loja_extensao_id
INNER JOIN conta ct ON ct.id = fat.conta_id
INNER JOIN banco bc ON bc.id = ct.banco_id
LEFT JOIN conciliacao_vendas cv ON fat.empresa_id = cv.empresa_id AND cv.chavefato = fat.chavefato AND fat.rede_id = cv.rede_id
WHERE 1 = 1
AND cv.controle_upload_arquivo_id = 6906
AND fat.parcela = 1
ORDER BY fat.data_venda, fat.data_credito limit 20
.
ma molto lentamente.Qui il piano spiegato: http://explain.depesz.com/s/dnxh
Soluzione
Prova questa versione riscritta:
SELECT fat.*
FROM Table1 fat
JOIN conciliacao_vendas cv USING (empresa_id, chavefato, rede_id)
JOIN loja lj ON lj.id = fat.loja_id
JOIN rede rd ON rd.id = fat.rede_id
JOIN bandeira bd ON bd.id = fat.bandeira_id
JOIN produto pd ON pd.id = fat.produto_id
JOIN loja_extensao le ON le.id = fat.loja_extensao_id
JOIN conta ct ON ct.id = fat.conta_id
JOIN banco bc ON bc.id = ct.banco_id
LEFT JOIN modo_captura mc ON mc.id = fat.modo_captura_id
WHERE cv.controle_upload_arquivo_id = 6906
AND fat.parcela = 1
ORDER BY fat.data_venda, fat.data_credito
LIMIT 20;
.
Iscriviti sintassi e sequenza di join
In particolare ho fissato il LEFT JOIN
Gcode ingannevole a conciliacao_vendas
, che è costretto ad agire come una normale generazioneGoDiceTagCode entro la condizione successiva [INNER] JOIN
comunque. Ciò dovrebbe semplificare la pianificazione della query e consentire di eliminare le righe in precedenza nel processo, il che dovrebbe rendere tutto molto più economico. Risposta correlata con spiegazione dettagliata:
WHERE
è solo una stenografia sintattica.
Poiché ci sono molte tabelle coinvolte nella query e nell'ordine, le tabelle Joins query riscritte sono ottimale ora, è possibile mettere a punto questo con USING
per salvare il sovraccarico di pianificazione ed evitare piani di query inferiori. Corri in un Transazione singola :
BEGIN;
SET LOCAL join_collapse_limit = 1;
SELECT ...; -- read data here
COMMIT; -- or ROOLBACK;
.
Maggiori informazioni su questo:
- .
- Esempio di query per mostrare l'errore di stima della cardinalità a PostgreSQL
- Il manuale fine su Controllo del pianificatore con un join esplicito Clauses
Indice
Aggiungi alcuni indici sulle tabelle di ricerca con lotti o righe (non necessari per solo un paio di dozzine), in particolare (presi dal piano di query):
.SEQ Scan On Public.Conta Ct ... Rows= 6771
Seq Scan On Public.Loja lj ... Rows= 1568
Seq Scan On Public.Loja_extensao Le ... Righe= 16394
È particolarmente strano, perché quelle colonne assomigliano a colonne chiave primarie e dovrebbero già avere un indice ...
Allora:
CREATE INDEX conta_pkey_idx ON public.conta (id);
CREATE INDEX loja_pkey_idx ON public.loja (id);
CREATE INDEX loja_extensao_pkey_idx ON public.loja_extensao (id);
.
Per rendere questo veramente grasso, un indice multicolno
CREATE INDEX foo ON Table1 (parcela, data_venda, data_credito);
.