如何确定 Postgres 数据库中 1 行将占用多少空间?



我对Postgres很陌生,所以我的数学可以在这里...

这是我的表:

CREATE TABLE audit (
id BIGSERIAL PRIMARY KEY,
content_id VARCHAR (50) NULL, 
type VARCHAR (100) NOT NULL, 
size bigint NOT NULL, 
timestamp1 timestamp NOT NULL DEFAULT NOW(), 
timestamp2 timestamp NOT NULL DEFAULT NOW());

我想对 1 行将占用多少空间进行一些估计。所以我做了这样的事情:

1 row = id + content_id + type + size + timestamp1 + timestamp2 
= 8 + 100 + 50 + 8 + 8 + 8 bytes
= 182 bytes

我还在本地帖子中创建了相同的表,但数字不匹配

INSERT INTO public.audit(
content_id, type, size)
VALUES ('aaa', 'bbb', 100);

SELECT pg_size_pretty( pg_total_relation_size('audit') );  -- returns 24 kb
INSERT INTO public.audit(
content_id, type, size)
VALUES ('aaaaaaaaaaaaa', 'bbbbbbbbbbbbbb', 100000000000);
SELECT pg_size_pretty( pg_total_relation_size('audit') ); -- still returns 24 kb

这让我认为 Postgres 首先保留了 24 kb 的空间,当我输入更多数据时,一旦我超过 132 kb,它就会增加 24 字节?但是我内心的某种东西说这不可能是对的。

我想看看 1 行在 Postgres 数据库中会占用多少空间,以便我可以分析我可以在其中存储多少数据。

编辑

在阅读更多之后,我想出了这个,正确吗?

1 row =
23 (heaptupleheader)
+ 1 (padding)
+ 8 (id)
+ 50 (content_id)
+ 6 (padding)
+ 100 (type)
+ 4 (padding)
+ 8 (size)
+ 8 (timestamp)
+ 8 (timestamp)
= 216 bytes

"我内心的某些东西说不可能是对的"是错误的。实际上尝试id确定每行的大小是不切实际的。您可以计算平均行,给定大量行,平均行越好。部分原因是可变长度的列。您的定义 varchar(50( 不需要存储字节,除非它包含 50 个字节,如果它有 20 个字节,那么它只占用 20 字节(加上开销(,即使这样它也不精确,因为填充可能会改变。该定义仅指定最大值而不是实际值,存储为实际值。
就您的 24kb 而言,这似乎一点也不出格。请记住,物理 I/O 是可能最慢的单个操作,尝试调整到 I/O 的各个行会使您的系统戛然而止。因此,Postgres 只读取完整的块(并分配相同的空间(和/或多个块。通常块大小为 8K(8192 字节(。这是 I/O 性能与空间分配之间的权衡。您的系统似乎具有 3 个块的多块读取 (??(。如果有什么令人惊讶的,那就是那么小。
简而言之,试图获得一行的大小不是盗版的,而是获得几百个代表性行并计算平均值。
顺便说一句,您只需重新排列列即可更改长度:

1 row =
23 (heaptupleheader)
+ 1 (padding)
+ 8 (id)
+ 8 (size)
+ 8 (timestamp)
+ 8 (timestamp)
+ 50 (content_id)
+ 2 (padding)      (if content contains all 50 char)
+ 100 (type)       (if type contains all 100 char)
= 208 bytes

最新更新