这个Postgres数据库拥有各种大小的表,最大可达1000万行。几乎所有的主键都有一个从1开始计数的BIGINT。
由于BIGINT是64位,但1000万行完全在INT的最大值20亿以内,因此将这些BIGINT列转换为INT(32位(和SMALLINT(16位(以加快一些重载SQL是否值得?更紧凑地存储索引/表应该会给我们带来更高的缓存命中率。如果有的话,我还能期待多大的加速?不使用BIGINT有什么缺点吗?(假设达到INT/SMLINT的最大值永远不会成为问题(
它在很大程度上取决于实际的表和索引定义。该开关为列保存了4个字节,但由于所有存储都是以8个字节的倍数完成的,因此如果幸运的话,这可能会被对齐填充所吞噬或释放8个字节。
支持PK的标准btree索引的大小不会改变,因为对齐填充丢失了4个字节但是如果您在覆盖索引中使用额外的4字节列,则会节省8个字节而不是4个字节,这将使索引元组的总字节数从28个变为20个。
bigint
主键只是开始。如果有外键引用,效果会成倍增加。或者您有涉及多个FK列的多列索引。然后开关可以很好地实现您想要的良好加速。尤其是在缓存内存有限的情况下。这完全取决于情况。
如果你确信在表的生命周期内不会燃烧超过3^31个数字(而不是2^32:Postgres使用有符号整数,你也必须使用负的一半(,和实际上可以节省表和索引中的空间,那么,无论如何,切换到纯integer
。我已经多次看到实际的差异。但是在修改之前,您需要对Postgres存储机制有一些了解。
相关:
- 在PostgreSQL中计算和节省空间
- 为读取性能配置PostgreSQL
只有负载测试才能给出可靠的答案,但我预计您不会看到明显的性能提升。
这里bigint
是正确的数据类型。即使你确信你不会耗尽integer
的极限,也要考虑一下:
-
如果使用序列生成值,则可能不会使用所有可能的数字–交易可以回滚
-
曾经有几个聪明的人认为232将是比任何人都可能需要更多的IP地址
对于像您这样的小桌子,节省空间和性能是不值得的。有了一个大表,您就不想承受将它从integer
转换为bigint
的痛苦。
过早的优化是万恶之源。
数据通常存储在与8字节边界对齐的磁盘上。单列索引在bigint上的大小与在int上的大小相同。对于表或多列索引,它可能能够更紧密地封装int,这取决于哪些相邻列可以合并在一起以容纳8个字节。
性能变化可能很小或根本不存在,而且很难预测。要知道答案,你必须做测试。但这可能不值得花时间去做