尝试这个重写版本:
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;
JOIN 语法和连接顺序
特别是我修复了误导性的LEFT JOIN
to conciliacao_vendas
,它被迫充当普通[INNER] JOIN
由后来的WHERE
无论如何条件。这应该会简化查询规划,并允许在过程的早期消除行,这将使一切变得更便宜。相关答案及详细解释:
- 更详细地解释 JOIN 与 LEFT JOIN 以及 WHERE 条件性能建议 https://stackoverflow.com/questions/24876673/explain-join-vs-left-join-and-where-condition-performance-suggestion-in-more-de/24876797#24876797
USING
只是语法简写。
由于查询涉及很多表,并且重写的查询连接表的顺序现在是最佳的,因此您可以使用以下命令对此进行微调SET LOCAL join_collapse_limit = 1
以节省计划开销并避免较差的查询计划。运行在一个单笔交易:
BEGIN;
SET LOCAL join_collapse_limit = 1;
SELECT ...; -- read data here
COMMIT; -- or ROOLBACK;
更多相关内容:
- 显示 PostgreSQL 中基数估计错误的示例查询 https://stackoverflow.com/questions/25002263/sample-query-to-show-cardinality-estimation-error-in-postgresql/25002962#25002962
- 精美的手册使用显式 JOIN 子句控制规划器 http://www.postgresql.org/docs/current/interactive/explicit-joins.html
Index
在包含大量或行的查找表上添加一些索引(对于几十行来说不需要),特别是(取自查询计划):
public.contact 上的序列扫描 ...行=6771
对 public.loja lj 进行序列扫描 ...行=1568
对 public.loja_extensao 文件进行 Seq 扫描 ...行=16394
这特别奇怪,因为这些列看起来像主键列并且应该已经have一个索引...
So:
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);