为什么分区 table 大小大于具有相同数据的正常 table 大小
Why a partitioned table size is larger than a normal table size with the same data
我把相同的数据插入到两个table中:一个是分区的,一个是正常的。
我用下面的命令来确定正常大小 table:
select pg_size_pretty (pg_total_relation_size ('test_normal'))
输出为:6512 MB
我使用以下命令来确定分区的大小 table:
select sum(to_number(pg_size_pretty(pg_total_relation_size(inhrelid::regclass)),'999999999')) from pg_inherits where inhparent = 'test_partition'::regclass
输出为:6712.1 MB
分区table有1001个分区。
两个 table 都没有索引或约束。
如果空分区的大小为 0 字节,为什么两个 table 之间存在如此大的差异 (200 MB)?
主要问题是你调用to_number(pg_size_pretty(...),'999999999')
。 pg_size_pretty
returns 类似123 MB
或123 GB
的值,两者都会变成123,所以总和是错误的。即使所有单位恰好相同,您仍然会出现舍入误差。
所以在 求和尺寸后调用 to_number
。
未分区的 table 和分区的 table 之间当然可能仍然存在小差异。
非常感谢劳伦斯
我搜索了另一种方法来确定分区 table 的大小,我发现了这个 post:
所以我试试这个:
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')
-- 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,
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
结果现在更有意义了!
我把相同的数据插入到两个table中:一个是分区的,一个是正常的。 我用下面的命令来确定正常大小 table:
select pg_size_pretty (pg_total_relation_size ('test_normal'))
输出为:6512 MB
我使用以下命令来确定分区的大小 table:
select sum(to_number(pg_size_pretty(pg_total_relation_size(inhrelid::regclass)),'999999999')) from pg_inherits where inhparent = 'test_partition'::regclass
输出为:6712.1 MB
分区table有1001个分区。 两个 table 都没有索引或约束。
如果空分区的大小为 0 字节,为什么两个 table 之间存在如此大的差异 (200 MB)?
主要问题是你调用to_number(pg_size_pretty(...),'999999999')
。 pg_size_pretty
returns 类似123 MB
或123 GB
的值,两者都会变成123,所以总和是错误的。即使所有单位恰好相同,您仍然会出现舍入误差。
所以在 求和尺寸后调用 to_number
。
未分区的 table 和分区的 table 之间当然可能仍然存在小差异。
非常感谢劳伦斯
我搜索了另一种方法来确定分区 table 的大小,我发现了这个 post:
所以我试试这个:
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')
-- 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,
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
结果现在更有意义了!