我在Oracle Linux Server 6.3版上使用Postgresql 9.2.
根据the storage layout documentation,页面布局包含:
> PageHeaderData(24字节)
> n个项目数(索引项/表项)AKA ItemIdData(4个字节)
>自由空间
> n个项目
>特殊空间
我测试它以制作一些公式来估计预期的表格大小……(TOAST概念可能会被忽略.)
postgres=# \d t1; Table "public.t1" Column ',' Type ',' Modifiers ---------------+------------------------+------------------------------ code |character varying(8) |not null name |character varying(100) |not null act_yn |character(1) |not null default 'N'::bpchar desc |character varying(100) |not null org_code1 |character varying(3) | org_cole2 |character varying(10) | postgres=# insert into t1 values( '11111111',-- 8 '1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111',<-- 100 'Y','1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111',<-- 100 '111','1111111111'); postgres=# select * from pgstattuple('t1'); table_len | tuple_count | tuple_len | tuple_percent | dead_tuple_count | dead_tuple_len | dead_tuple_percent | free_space | free_percent -----------+-------------+-----------+---------------+------------------+----------------+--------------------+------------+-------------- 8192 | 1 | 252 | 3.08 | 1 | 252 | 3.08 | 7644 | 93.31 (1 row)
为什么tuple_len 252而不是249? (“所有列的最大长度的222字节”PLUS
“27个字节的元组头后跟一个可选的空位图,一个可选的对象ID字段和用户数据”)
3个字节来自哪里?
我的配方有问题吗?
你的计算在几点都没有.
> varchar或text的存储大小是(引用手册here):
The storage requirement for a short string (up to 126 bytes) is 1 byte
plus the actual string,which includes the space padding in the case
of character. Longer strings have 4 bytes of overhead instead of 1.
Long strings are compressed by the system automatically,so the
physical requirement on disk might be less.
大胆强调我的评论中的问题.
> HeapTupeHeader occupies 23 bytes,而不是27个字节.
> 1个字节的填充由于数据对齐(8的倍数),在这种情况下用于NULL位掩码.
>类型varchar没有填充.
所以,实际的计算是:
23 -- heaptupleheader + 1 -- NULL bit mask (or padding if all columns are NOT NULL) + 8 -- columns + 100 + 1 + 100 + 3 + 10 + 6 -- 1 byte overhead per varchar column,6 columns
– > 252个字节.