在PostgreSQL中存储我的字符串的最紧凑和最快捷的方法

时间:2010-06-22 18:27:25

标签: sql postgresql

我有一个大的十六进制(16字节,32位十六进制数字)数据项,它始终具有以下格式:

00d980113901429fa6de7fb7e2da705a

这是来自我的源代码的ASCII字符串(即,上面的零是字符零0x30,而不是0x00),我想知道人们对存储的最佳方式(irt存储和速度)的意见这在PostgreSQL中。

显而易见的事情是将其存储为varchar,但以二进制形式存储肯定会节省空间。通过以二进制形式存储,我会看到select和insert带来的性能提升吗? bytea或bit会更好吗?这两者在内部代表方面是否存在差异?

另一个想法是将它存储为两个bigint / int8或四个整数/ int4,分成多个列。

空间和时间是一个问题,因为我有很多这些(超过一万亿)。

3 个答案:

答案 0 :(得分:3)

比较这两个10M记录表:

create table test (a int8 not null, b int8 not null, primary key(a,b));
insert into test
  select generate_series(1,10000000), generate_series(1,10000000);
select pg_size_pretty(pg_total_relation_size('test'));
723 MB
create table test_bytea (a bytea not null);
insert into test_bytea
  select decode(lpad(to_hex(a),16,'0')||lpad(to_hex(b),16,'0'),'hex') from test;
alter table test_bytea add primary key (a);
select pg_size_pretty(pg_total_relation_size('test_bytea'));
804 MB

索引的bytea2*int8大11%。这并不多,但这意味着缓存中的行数减少了11%。顺序扫描将减慢11%等。

如果你的数据没有改变,你应该考虑一个排序值而不是数据库的平面文件存储 - 每10M记录只有152MB,搜索将是O(log(n))。

答案 1 :(得分:1)

您必须确定数据最常用的用途,以确定适当的数据类型。远离数据类型的转换意味着引用该列的索引是无用的。

答案 2 :(得分:1)

我怀疑与VARCHAR表示相比,BYTEA的空间要小2倍,比较速度要快2倍(>,<,=)。

在其他数据库引擎中,您甚至可以避免长度标头开销。例如:

MS-SQL:   BINARY(16)
Oracle:   RAW(16)
MySQL:    BINARY(16)

或者如果您喜欢length-headers:

MS-SQL:   VARBINARY(16)
Oracle:   BLOB
MySQL:    VARBINARY(16)

PostgreSQL只支持BYTEA,因此你总是支付长度标题,但在这种情况下我仍然使用BYTEA。