pgstattuple查询性能

时间:2014-07-28 22:26:53

标签: performance postgresql statistics query-performance

我正在尝试构建查询,使用pgstattuple扩展来检查所有用户表中的死元组,实时元组百分比,可用空间等。所以,我提出了这个问题:

SELECT schemaname, 
relname, 
(pgstattuple(schemaname ||'.'||relname)).*
FROM pg_statio_user_tables;

pg_statio_user_tables是一个pg_catalog视图,它使用另一个系统视图。所以乍一看这个查询看起来很简单,但最终在db中的882个对象的总执行时间为27分钟。

此查询的执行计划: execution plan

有没有办法使用pgstattuple重写查询,所以它会表现得体面?

1 个答案:

答案 0 :(得分:2)

如果在子查询中运行该函数并且仅在下一级别分解生成的行类型,它会快得多:

SELECT s.schemaname, s.relname, st.*
FROM pg_statio_user_tables s
    ,pgstattuple(s.schemaname ||'.'|| s.relname) AS st;

(这是一个隐含的LATERAL JOIN。在Postgres 9.3的版本中,使用子查询代替。)

这样,该函数仅在pg_statio_user_tables中每行调用一次。不幸的是,你在Postgres查询规划器(解析器)中遇到了一个弱点。克雷格在这个相关答案中详细解释了:

如果pg_statio_user_tables视图中只需要表格和模式名称,那么可以更快,但

SELECT c.oid::regclass::text AS tbl, (st).*
FROM   pg_class c
JOIN   pg_namespace n ON n.oid = c.relnamespace
      ,pgstattuple(c.oid::regclass::text) st
WHERE  c.relkind = 'r'            -- only tables
AND    n.nspname NOT LIKE 'pg_%'  -- exclude system schemas
ORDER  BY 1;