Postgres 的 pg_total_relation_size 返回基于 zfs 的表空间的意外表大小

Postgres 的 pg_total_relation_size 返回基于 zfs 的表空间的意外表大小

我在 Ubuntu 20.04 上运行 Postgres 15.1。基本文件系统是 ext4,但我已将 zfs 安装到这样的稀疏文件上(用于压缩测试目的):

truncate -s 100G zfspart.dat
zpool create -o ashift=12 -O canmount=on -O atime=off -O recordsize=128k -O compression=zstd pg /root/zfspart.dat
chown postgres:postgres /pg
CREATE TABLESPACE zfs LOCATION '/pg';
zfs -V
zfs-2.1.6-0york1~20.04 zfs-kmod-2.1.6-0york1~20.04

之后,我将一个 12 Gb 的表复制到新创建的表空间中:

create table if not exists a_copy(
                like a
                including defaults
                including constraints
                including indexes
            ) tablespace zfs;

insert into a_copy select * from a;
vacuum full analyze a_copy;

并查询 zfs:

zfs list
NAME   USED  AVAIL     REFER  MOUNTPOINT 
pg    1.22G  95.2G     1.21G /pg

而且它似乎提供了很好的压缩效果:

zfs get compressratio pg
NAME  PROPERTY       VALUE  SOURCE
pg    compressratio  4.89x  -

但是,Postgres 本身认为新表占用的空间不小于原始表:pg_total_relation_size 给出几乎相同的 12Gb:

select pg_total_relation_size('a')
12_033_286_144
select pg_total_relation_size('a_copy')
12_031_442_944

当我进入表空间时,ls -lh 显示文件总共占用约 6Gb:

cd /pg/PG_15_202209061/24412
ls -lh

total 1.3G
-rw------- 1 postgres postgres 1.0G Feb 24 00:12 46072
-rw------- 1 postgres postgres 1.0G Feb 24 00:12 46072.1
-rw------- 1 postgres postgres 1.0G Feb 24 00:13 46072.2
-rw------- 1 postgres postgres 1.0G Feb 24 00:13 46072.3
-rw------- 1 postgres postgres 1.0G Feb 24 00:13 46072.4
-rw------- 1 postgres postgres 945M Feb 24 00:13 46072.5
-rw------- 1 postgres postgres    0 Feb 24 00:12 46075
-rw------- 1 postgres postgres 8.0K Feb 24 00:12 46076

我的问题是,Postgres 如何得出给定的关系文件大小,造成差异的原因是什么,以及谁正确计算了占用空间,Postgres 还是 zfs?我的特定目标是压缩基准,那么如何在此设置中计算关系(PG 表+其索引)在磁盘上的实际大小?

PS:我也尝试过:

du -h
1.3G    .

du -h --apparent-size
6.0G    .

有人向我指出,即使 zfs 压缩是透明的,Postgres 中的 12GB 从何而来仍是一个谜。但后来我意识到新表上的索引仍然是在 pg_default 中创建的。毕竟,我的问题应该改写成这样:有没有一种简单/优雅的方法来获取我的系统上的压缩表(及其索引)的大小,因为我可以同时拥有多个压缩表?它不必是纯 SQL,我对任何 SQL、Python、系统实用程序解决方案都很满意。现在我看到的唯一方法是使用单独的池/表空间来处理每个表,并在相关目录上调用 du -h,但希望我错了。

相关内容