我不明白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中找到答案,所以我会在这里问:How does the size in kb grow in relation of the precision of numeric columns?

我做这些测试是为了决定在CMS数据库中存储货币类型的精度/刻度,我希望所有商品的价格只有1个精度/刻度值(不是总数,刻度必须是2位小数).

我可以存储的小数位数越多,对用户来说就越好(因此,当客户要求为特定项目存储12个小数位数时,我没有限制),但我想了解这一决定将如何影响数据库大小和性能.

推荐答案

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)即可.由于不存储尾随零,因此它将仅使用最多为现有小数位数的空间.

Database相关问答推荐

如何将使用模块创建的 Redis RDB 文件迁移到没有该模块的部署? (RedisStack 版本 7.2+ 中不再包含 RedisGraph)

无法初始化数据库,出现错误无法连接到`host=db user=database=`:拨号错误(dial tcp xxxx: connect: connection refused)

数据库约束 - 保留(keep)还是忽略(ignore)?

当您达到 SQL Server Express 4GB / 10GB 限制时会发生什么?

Spring 的 JdbcTemplate 是否在查询超时后关闭连接?

将 `tsv` 文件插入 postgresql 数据库

向表中添加大量索引是否有缺点?

B+ 树相对于 BST 的优势?

连接池策略效果怎样?

Boxed与原始类型作为实体 id

表别名如何影响性能?

具有多列的单个固定表与灵活的抽象表

限制一个 sqlite 表的最大行数

面向文档的数据库是否旨在取代关系数据库?

如何删除除了postgres中的少数数据库之外的所有数据库

字符串列上的postgresql索引

MySQL:为什么使用 VARCHAR(20) 而不是 VARCHAR(255)?

Data Mapper 是不是比 Active Record 更现代的趋势

获取 xp_cmdshell 的执行权限

有任何使用协议缓冲区的经验吗?