我正在运行以下查询:
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
但很慢。这里是解释计划:http://explain.depesz.com/s/DnXH
答案 0 :(得分:0)
试试这个改写版本:
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;
我特别将误导性LEFT JOIN
修正为conciliacao_vendas
,后者被[INNER] JOIN
条件强制作为普通WHERE
。无论如何。这应该简化查询计划,并允许在流程早期消除行,这应该使一切都便宜很多。相关答案详细解释:
USING
只是一种语法简写。
由于查询中涉及许多表,并且重写的查询连接表的顺序现在是最佳的,您可以使用SET LOCAL join_collapse_limit = 1
对其进行微调,以节省计划开销并避免劣质查询计划。在 单笔交易 :
BEGIN;
SET LOCAL join_collapse_limit = 1;
SELECT ...; -- read data here
COMMIT; -- or ROOLBACK;
更多相关信息:
在具有批次或行的查找表上添加一些索引(对于几十个不是必需的),特别是(从您的查询计划中获取):
seq Scan on public.conta ct ... rows = 6771
seq Scan on public.loja lj ... rows = 1568
seq Scan on public.loja_extensao le ... rows = 16394
这特别奇怪,因为这些列看起来像主键列,并且应该已经拥有索引......
所以:
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);
为了使这个真的很胖,多列索引将会提供很好的服务:
CREATE INDEX foo ON Table1 (parcela, data_venda, data_credito);