我使用的是 9.1 版本,dpi
数据库中有一个名为 的表,采用 UTF-8 编码,目前有 18,628 行。TEXT
其中有一列名为foto
,它包含代表唯一图像文件的 B64 字符串。
我正在尝试计算一行占用多少磁盘空间。有 18050 行没有值,NULL
所有行的总和为 87384 foto
。length()
我不明白的是这一点。运行select * from pgstattuple('dpi');
返回:
-[ RECORD 1 ]------+--------
table_len | 5890048
tuple_count | 18628
tuple_len | 5656063
tuple_percent | 96.03
dead_tuple_count | 0
dead_tuple_len | 0
dead_tuple_percent | 0
free_space | 92752
free_percent | 1.57
跑步
select pg_size_pretty(pg_relation_size(c.oid)) AS "size"
from pg_class c
where relname = 'dpi';
我得到以下信息:
size
---------
5752 kB
(1 row)
这到底是怎么回事?为什么这个表这么小?
编辑:另外,我检查了一下,/var/lib/postgresql/9.1/main
它的大小是 574.5MiB。运行:
SELECT nspname || '.' || relname AS "relation",
pg_size_pretty(pg_relation_size(C.oid)) AS "size"
FROM pg_class C
LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
WHERE nspname NOT IN ('pg_catalog', 'information_schema')
ORDER BY pg_relation_size(C.oid) DESC
LIMIT 3;
产量:
relation | size
-------------------------------+---------
pg_toast.pg_toast_17048 | 501 MB
public.dpi | 5752 kB
pg_toast.pg_toast_17048_index | 5752 kB
(3 rows)
编辑 2:使用select pg_total_relation_size('dpi');
我得到的539262976
字节。这是否意味着我可以将其除以 18628,这将得到每行的平均大小(28 KiB)?每行的大小是否会随时间变化(由于索引或类似原因)?
即便如此,每行 28 KiB 似乎也非常小。foto
仅一个值就应该是 85 KiB(假设只有 1 字节字符)。
答案是,默认情况下,PostgreSQL TOAST 机制不仅会分解非常大的列,而且根据数据类型,它实际上会首先尝试压缩它们。非常巧妙。
来源:http://www.postgresql.org/docs/9.1/static/storage-toast.html
答案1
Postgresql 没有“blobs 类型”。它会自动将“大列”(即大于 1 页,8k)切分为“toast”表。
在这里postgresql 管理函数您将在其中了解到您感兴趣的功能pg_table_size
:pg_total_relation_size
两者都考虑了 toast 空间。第一个不计算索引空间,第二个计算索引空间。