Postgresql 获取分区表的表大小(Postgres 10+;)

Postgresql 获取分区表的表大小(Postgres 10+;),postgresql,postgresql-10,postgresql-11,Postgresql,Postgresql 10,Postgresql 11,我遇到了这个查询,其中以字节为单位显示了表、表大小、toast大小和索引大小: SELECT relname AS table_name, pg_size_pretty(pg_total_relation_size(relid)) AS total, pg_size_pretty(pg_relation_size(relid)) AS internal, pg_size_pretty(pg_table_size(relid) - pg_relation_size(relid))

我遇到了这个查询,其中以字节为单位显示了表、表大小、toast大小和索引大小:

SELECT
  relname AS table_name,
  pg_size_pretty(pg_total_relation_size(relid)) AS total,
  pg_size_pretty(pg_relation_size(relid)) AS internal,
  pg_size_pretty(pg_table_size(relid) - pg_relation_size(relid)) AS external,
  pg_size_pretty(pg_indexes_size(relid)) AS indexes
FROM pg_catalog.pg_statio_user_tables 
ORDER BY pg_total_relation_size(relid) DESC;

我知道Postgres正在为每个分区创建一个表,因此我将分别为每个分区获取条目,但是否有方法可以为每个表获取一行,而不管该表是否已分区?

当然,但您必须与一组其他目录表合并,并使用
GROUP BY

  • 目录
    pg_class
    中的属性
    relkind
    将告诉您一个关系是分区的(
    p
    ),还是不分区的(
    r

  • 目录
    pg_inherits
    将告诉您哪个分区(
    inhrelid
    )属于哪个分区表(
    inhparent


由于分区可以再次分区,如果您想覆盖所有的基,就必须编写一个递归公共表表达式。

按照@Laurenz的指示,尽管我创建了一个满足需要的查询。这将获得特定数据库中所有分区表的总内存

SELECT
   pi.inhparent::regclass AS parent_table_name, 
   pg_size_pretty(sum(pg_total_relation_size(psu.relid))) AS total,
   pg_size_pretty(sum(pg_relation_size(psu.relid))) AS internal,
   pg_size_pretty(sum(pg_table_size(psu.relid) - pg_relation_size(psu.relid))) AS external, -- toast
   pg_size_pretty(sum(pg_indexes_size(psu.relid))) AS indexes
FROM pg_catalog.pg_statio_user_tables psu
   JOIN pg_class pc ON psu.relname = pc.relname
   JOIN pg_database pd ON pc.relowner = pd.datdba
   JOIN pg_inherits pi ON pi.inhrelid = pc.oid
WHERE pd.datname = :database_name
GROUP BY pi.inhparent
ORDER BY sum(pg_total_relation_size(psu.relid)) DESC;

请注意,在分区的情况下,根表不会有一行,但每个父表都有自己的行,即使有多个分区级别,这也会为每个父表提供表大小:

WITH RECURSIVE tables AS (
  SELECT
    c.oid AS parent,
    c.oid AS relid,
    1     AS level
  FROM pg_catalog.pg_class c
  LEFT JOIN pg_catalog.pg_inherits AS i ON c.oid = i.inhrelid
    -- p = partitioned table, r = normal table
  WHERE c.relkind IN ('p', 'r')
    -- not having a parent table -> we only get the partition heads
    AND i.inhrelid IS NULL
  UNION ALL
  SELECT
    p.parent         AS parent,
    c.oid            AS relid,
    p.level + 1      AS level
  FROM tables AS p
  LEFT JOIN pg_catalog.pg_inherits AS i ON p.relid = i.inhparent
  LEFT JOIN pg_catalog.pg_class AS c ON c.oid = i.inhrelid AND c.relispartition
  WHERE c.oid IS NOT NULL
)
SELECT
  parent ::REGCLASS                                  AS table_name,
  array_agg(relid :: REGCLASS)                       AS all_partitions,
  pg_size_pretty(sum(pg_total_relation_size(relid))) AS pretty_total_size,
  sum(pg_total_relation_size(relid))                 AS total_size
FROM tables
GROUP BY parent
ORDER BY sum(pg_total_relation_size(relid)) DESC

实际上,每个分区只需要一行。用
psu.relname
替换group by中的
pi.inhparent
,并将select中的
pi.inhparent::regclass替换为win的父表名称。