我不明白Postgresql(9.2)如何计算列大小(以kb为单位),我有这个表:
Table d2:
Column | Type |
---------+---------------|
id | serial |
n | numeric(17,2) |
Table d4:
Column | Type |
---------+---------------|
id | serial |
n | numeric(19,4) |
Table d18:
Column | Type |
---------+---------------|
id | serial |
n | numeric(35,18)|
Table b1:
Column | Type |
---------+---------------|
id | serial |
n | numeric(16,2) |
Table b2:
Column | Type |
---------+---------------|
id | serial |
n | numeric(4,2) |
我用这段代码填充它们,以便每个表有10000行;
$tests = array(2, 4, 18);
foreach($tests AS $n)
{
$m = number_format(999999999999999.66549865, $n, '.', '');
$prp_name = "insert_$n";
$prp = pg_prepare($db, $prp_name, "INSERT INTO d_$n (n) VALUES ($1)");
for($i = 0; $i < 10000; $i++)
{
pg_execute($db, $prp_name, array($m));
}
}
$prp = pg_prepare($db, 'insert_b1', "INSERT INTO b1 (n) VALUES ($1)");
$m = 16512.67;
for($i = 0; $i < 10000; $i++)
{
pg_execute($db, 'insert_b1', array($m));
}
$prp = pg_prepare($db, 'insert_b2', "INSERT INTO b2 (n) VALUES ($1)");
$m = 99.36;
for($i = 0; $i < 10000; $i++)
{
pg_execute($db, 'insert_b2', array($m));
}
现在,我不明白的是怎么可能:
SELECT pg_size_pretty(pg_total_relation_size('d2')) AS size_d2;
size_d2
---------
752 kB
SELECT pg_size_pretty(pg_total_relation_size('d4')) AS size_d4;
size_d4
---------
752 kB
SELECT pg_size_pretty(pg_total_relation_size('d18')) AS size_d18;
size_d18
----------
752 kB
SELECT pg_size_pretty(pg_total_relation_size('b1')) AS size_b1;
size_b1
---------
440 kB
SELECT pg_size_pretty(pg_total_relation_size('b2')) AS size_b2;
size_b2
---------
680 kB
因此,d_ *表具有相同的大小,即使精度(以及存储的数据的长度)非常不同;
即使精度更高,表b1也小于b2。
所有表格都已在pg_total_relazion_size
之前刷新(真空,分析)。
我无法在Postgresql's datatypes documentations中找到答案,所以我会在这里问一下: kb的大小与数字列的精度有关吗?
我正在进行此测试以确定用于在CMS的数据库中存储货币类型的精度/比例,我希望所有商品的价格只有1个精度/比例值(不是总数,其中比例必须是2位小数。)
对于用户来说,我可以存储的小数点越多越好(因此当客户要求为特定项目存储12位小数时我没有限制),但我想了解这个决定将如何影响数据库大小和性能
答案 0 :(得分:19)
来自manual:
数字值是物理存储的,没有任何额外的前导或尾随 零。因此,列的声明精度和比例是最大值, 不固定的分配。 (在这个意义上,数字类型更类似于 varchar(n)而不是char(n)。)实际存储要求是两个字节 对于每组四个十进制数字,加上三到八个字节的开销。
pg_total_relation_size函数的结果包括索引。要插入的每个值的正确列大小为:
select pg_column_size(a)
from (values
(999999999999999.62::numeric(17,2)),
(999999999999999.6250::numeric(19,4)),
(999999999999999.625000000000000000::numeric(35,18)),
(16512.67::numeric(16,2)),
(99.36::numeric(4,2))
) s(a)
;
pg_column_size
----------------
16
16
16
12
10
因此,如果您想让用户拥有最多n
个小数,请将其定义为numeric(35, n)
。它将仅使用最大为现有小数的空格,因为不存储尾随零。
答案 1 :(得分:4)
根据Postgresql doc,整数有4个字节,bigint - 8个字节。
的大小NUMERIC (p, s)
11+(p / 2)字节,其中p =精度,s =比例
存储由数字类型的大小决定,没有填充。例如:
SELECT pg_column_size('123'::numeric(21,7)); --8
SELECT pg_column_size('123.1'::numeric(21,7)); --10
SELECT pg_column_size('123.12'::numeric(21,7)); --10
SELECT pg_column_size('123.123'::numeric(21,7)); --10
SELECT pg_column_size('123.1234'::numeric(21,7)); --10
SELECT pg_column_size('123.12345'::numeric(21,7)); --12
SELECT pg_column_size('123.123456'::numeric(21,7)); --12
SELECT pg_column_size('123.1234567'::numeric(21,7)); --12