我在 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,但希望我错了。