我正在尝试使用 pgstattuple 扩展构建查询来检查所有用户表中的死元组、活元组百分比、可用空间等。所以,我想出了这个问题:
SELECT schemaname,
relname,
(pgstattuple(schemaname ||'.'||relname)).*
FROM pg_statio_user_tables;
pg_statio_user_tables 是一个 pg_catalog 视图,它使用另一个系统视图。乍一看,该查询看起来非常简单,但最终对 db 中的 882 个对象执行了 27 分钟的总时间。
该查询的执行计划:
有没有办法仍然使用 pgstattuple 重写查询,使其性能良好?
如果您在子查询中运行该函数并且仅分解外部
SELECT
列表中的结果行类型,那么速度会快得多:
SELECT s.schemaname, s.relname, st.*
FROM pg_statio_user_tables s
CROSS JOIN LATERAL pgstattuple(s.relid) AS st
ORDER BY 1, 2; -- optional
这样,该函数在
pg_statio_user_tables
中每行仅调用一次。您被 Postgres 查询规划器中的一个弱点绊倒了。参见:
pgstattuple()
可以采用 OID,这是更好的选择。