Question

Je suis en cours d'exécution de la requête suivante:

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

Mais très lentement.Ici, le plan d'Expliquer: http://explain.depesz.com/s/DnXH

Était-ce utile?

La solution

Essayez cette version réécrite:

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;

La syntaxe de JOINTURE et la séquence de la rejoint

En particulier, j'ai fixé la trompeuse LEFT JOIN pour conciliacao_vendas, qui est forcé d'agir comme une plaine [INNER] JOIN par le plus tard WHERE condition de toute façon.Cela devrait simplifier la requête de la planification et permettent d'éliminer les lignes plus tôt dans le processus, ce qui devrait rendre les choses beaucoup moins cher.Réponse similaire avec explication détaillée:

USING est juste une syntaxe abrégée.

Car il y a beaucoup de tables impliquées dans la requête et de l'ordonnance de la requête réécrite joint des tables est optimal maintenant, vous pouvez affiner ce avec SET LOCAL join_collapse_limit = 1 pour enregistrer la planification de frais généraux et d'éviter inférieure plans de requête.Exécuter dans un seule transaction:

BEGIN;
SET LOCAL join_collapse_limit = 1;
SELECT ...;  -- read data here
COMMIT;      -- or ROOLBACK;

Plus à ce sujet:

Index

Ajouter quelques indices sur les tables de recherche avec des lots ou des lignes (pas nécessaire pour seulement quelques dizaines), en particulier (prises à partir de votre plan de requête):

Seq Scan sur le public.conta ct ... rows=6771
Seq Scan sur le public.loja lj ... rows=1568
Seq Scan sur le public.loja_extensao le ... rows=16394

C'est particulièrement étrange, parce que ces colonnes ressembler colonnes de clé primaire et devrait déjà ont un indice ...

Donc:

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);

Pour faire ce vraiment fat, un index multicolonne serait d'un grand service:

CREATE INDEX foo ON Table1 (parcela, data_venda, data_credito);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top