Postgres哈希连接与嵌套循环决策
Postgres hash join vs nested loop decision making
我有一个很长的查询,我将在这里总结一下并粘贴在底部:
select * from
a
left join b t1 on a.x = b.x
left join b t2 on a.y = b.x
left join b t3 on a.z = b.x
left join c on a.1 = c.1 and a.2 = c.2 and a.3 = c.3 --call this predicate 1
where c.z is null
a 和 c 有主键 1,2,3 未聚集
a.x y 或 z 可以为空
您会在下面链接的内容中看到 a 是 40k 行,c 是 500k 行,b 是 7k 行。此查询需要 10 分钟。在 excel 中手动完成会更快。即使在我 运行 vacuum full analyze 之后,我的行数估计都是错误的,它在不应该
的地方有嵌套循环
这里是完整的
https://explain.depesz.com/s/w2uN
当我删除谓词 1 时,所有嵌套循环都消失了,行估计仍然是错误的。在我重置 postgre 之后 运行 也需要不到一秒的时间,所以没有缓存
https://explain.depesz.com/s/O7R
关于如何强制散列连接的任何想法?或者我可以在 40k table 上构建 3 个索引,我一直在 运行 分类并加载,因为这实际上是一个每周刷新的暂存 table。似乎矫枉过正,但可能不会伤害任何人。除了 vacuum analyze 之外,关于如何在规划器中正确获取行数的内容也很少。对此有什么想法吗?
最后,这是完整的代码
SELECT
ar.cocd,
ar.customer,
ar.sales_doc,
ar.documentno,
ar.headertext,
ar.clrng_doc,
ar.typ,
ar.net_due_dt,
ar.amt,
ar.lcurr,
ar.amount_in_dc,
ar.curr,
ar.text,
ar.doc_date,
ar.clearing,
ar.po_number,
ar.payt,
ar.st,
ar.arrear,
ar.gl,
ar.user_name,
ar.tcod,
ar.itm,
ar.inv_ref,
ar.amount_in_loccurr2,
ar.pmnt_date,
ar.pk,
ar.pstng_date,
ar.account,
ar.accty,
ar.aging_bucket,
ar.billdoc,
ar.ftyp,
ar.general_ledger_amt,
ar.offstacct,
ar.pmtmthsu,
ar.purchdoc,
ar.rcd,
ar.transtype,
ar.ym,
COALESCE(ar_f2.branch, ar_f2.subbranch, ar_f2.account) AS forecast_company,
ar_f.customer_name AS paying_company,
ar_f3.customer_name AS shipping_company
FROM h_ar_open ar
LEFT JOIN h_ar_forecast ar_f ON ar.customer = ar_f.customer
LEFT JOIN h_ar_forecast ar_f2 ON ar.soldto::double precision = ar_f2.customer
LEFT JOIN h_ar_forecast ar_f3 ON ar.shipto::double precision = ar_f3.customer
LEFT JOIN h_ar_hist hist ON ar.cocd = hist.cocd AND ar.itm = hist.itm AND ar.documentno = hist.documentno
WHERE hist.documentno IS NULL;
您评论中的索引很有帮助,因为它使嵌套循环连接速度更快。超过 7000 行的 46417 次顺序扫描很糟糕。
你的问题是估计错了
也许您可以使用如下技巧强制加入顺序:
SELECT ...
FROM (SELECT ...
FROM a
LEFT JOIN b t1 ...
LEFT JOIN b t3 ...
LEFT JOIN b t3 ...
OFFSET 0) x
LEFT JOIN c ...;
如果c
是最后加入的,误判也无妨。
我有一个很长的查询,我将在这里总结一下并粘贴在底部:
select * from
a
left join b t1 on a.x = b.x
left join b t2 on a.y = b.x
left join b t3 on a.z = b.x
left join c on a.1 = c.1 and a.2 = c.2 and a.3 = c.3 --call this predicate 1
where c.z is null
a 和 c 有主键 1,2,3 未聚集 a.x y 或 z 可以为空 您会在下面链接的内容中看到 a 是 40k 行,c 是 500k 行,b 是 7k 行。此查询需要 10 分钟。在 excel 中手动完成会更快。即使在我 运行 vacuum full analyze 之后,我的行数估计都是错误的,它在不应该
的地方有嵌套循环这里是完整的 https://explain.depesz.com/s/w2uN
当我删除谓词 1 时,所有嵌套循环都消失了,行估计仍然是错误的。在我重置 postgre 之后 运行 也需要不到一秒的时间,所以没有缓存
https://explain.depesz.com/s/O7R
关于如何强制散列连接的任何想法?或者我可以在 40k table 上构建 3 个索引,我一直在 运行 分类并加载,因为这实际上是一个每周刷新的暂存 table。似乎矫枉过正,但可能不会伤害任何人。除了 vacuum analyze 之外,关于如何在规划器中正确获取行数的内容也很少。对此有什么想法吗?
最后,这是完整的代码
SELECT
ar.cocd,
ar.customer,
ar.sales_doc,
ar.documentno,
ar.headertext,
ar.clrng_doc,
ar.typ,
ar.net_due_dt,
ar.amt,
ar.lcurr,
ar.amount_in_dc,
ar.curr,
ar.text,
ar.doc_date,
ar.clearing,
ar.po_number,
ar.payt,
ar.st,
ar.arrear,
ar.gl,
ar.user_name,
ar.tcod,
ar.itm,
ar.inv_ref,
ar.amount_in_loccurr2,
ar.pmnt_date,
ar.pk,
ar.pstng_date,
ar.account,
ar.accty,
ar.aging_bucket,
ar.billdoc,
ar.ftyp,
ar.general_ledger_amt,
ar.offstacct,
ar.pmtmthsu,
ar.purchdoc,
ar.rcd,
ar.transtype,
ar.ym,
COALESCE(ar_f2.branch, ar_f2.subbranch, ar_f2.account) AS forecast_company,
ar_f.customer_name AS paying_company,
ar_f3.customer_name AS shipping_company
FROM h_ar_open ar
LEFT JOIN h_ar_forecast ar_f ON ar.customer = ar_f.customer
LEFT JOIN h_ar_forecast ar_f2 ON ar.soldto::double precision = ar_f2.customer
LEFT JOIN h_ar_forecast ar_f3 ON ar.shipto::double precision = ar_f3.customer
LEFT JOIN h_ar_hist hist ON ar.cocd = hist.cocd AND ar.itm = hist.itm AND ar.documentno = hist.documentno
WHERE hist.documentno IS NULL;
您评论中的索引很有帮助,因为它使嵌套循环连接速度更快。超过 7000 行的 46417 次顺序扫描很糟糕。
你的问题是估计错了
也许您可以使用如下技巧强制加入顺序:
SELECT ...
FROM (SELECT ...
FROM a
LEFT JOIN b t1 ...
LEFT JOIN b t3 ...
LEFT JOIN b t3 ...
OFFSET 0) x
LEFT JOIN c ...;
如果c
是最后加入的,误判也无妨。