4

我每周在 Postgres上遇到这个查询,它显示了表格、它们的大小、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 正在为每个分区创建一个表,所以我分别为每个分区获取条目,但是有没有办法让每个表有一行,不管这个表是否分区?

4

3 回答 3

7

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

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;

请注意,在我们有分区分区的情况下,根表不会有一行,但每个父表都有自己的行

于 2019-03-01T11:31:29.297 回答
4

即使我们有多个分区级别,这也会给出每个父表的表大小:

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
于 2019-12-10T12:11:37.190 回答
1

当然可以,但是您必须加入一堆其他目录表并使用GROUP BY.

  • relkind目录中的属性pg_class将告诉您关系是否已分区 ( p) 或未分区 ( r)。

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

由于分区可以再次分区,因此如果要覆盖所有基础,则必须编写递归公用表表达式。

于 2019-02-28T08:22:57.780 回答