PostgreSQL:"bytea"和"bit varying"类型之间的区别

Vic*_*tor 13 postgresql bit-manipulation

PostgreSQL类型byteabit varying声音类似:

文档没有提到任何一个的最大大小.难道是1GB喜欢character varying

我有两个单独的用例,都在一个包含数百万行的表中:

存储MD5哈希值

这将是一个bytea长度为16个字节或a bit(128).它将用于:

  • 重复数据删除:大量使用GROUP BY,我想有一个索引.
  • WHERE md5 =仅查询完全匹配.
  • 显示为人类使用的十六进制字符串.

存储任意二进制数据

长度不超过4kB的二进制数据字符串:

  • 按位运算以查找与某个掩码匹配的字符串.这篇文章末尾的例子.
  • 提取一些字节,例如获取字符串中字节14的整数值.
  • 一些重复数据删除.

使用按位操作的工作示例bit varying.掩码是X'00FF00',它只返回行X'AAAAAA'.我缩短了示例的字符串,但它将超过它们的全长,高达4kB.是否可以做类似的事情bytea

CREATE TABLE test1 (mystring bit varying);
INSERT INTO test1 VALUES (X'AAAAAA'), (X'ABCABC');
SELECT * FROM test1 WHERE mystring & X'00FF00' = X'00AA00';
Run Code Online (Sandbox Code Playgroud)

其中的byteabit varying是比较合适的?

我看到这个UUID类型正好存储了16个字节,那么存储MD5会有什么好处吗?

Cra*_*ger 10

通常,如果您不使用按位操作,则应使用bytea.

我存储较大的值,bytea然后bit varying在可能的情况下将子串转换为按位运算,主要是因为客户端byteabit varyingI/O格式更紧凑并且I/O格式更紧凑.

MD5值应存储为bytea.对它们进行逐位运算没有任何意义,您通常希望将它们作为二进制文件获取.

我认为bit varying真的有两个用途:

  • 存储字面字符串的字段字段; 和
  • 作为内部计算的临时数据类型

对于其他一切,请使用bytea.

但是,如果存在4k位域,那么没有什么可以阻止你存储它.


Bag*_*aja 7

  1. 它的最大长度似乎bytea是1 GB.[1]
  2. 用于按位操作使用bit varying(解释见下文)
  3. 用于存储MD5哈希使用bytea.它需要的存储空间比bit varying
  4. 使用的好处UUIDUUID算法以某种方式保证您的唯一性,不仅在您的表中,而且在您的数据库中,甚至在您的数据库中(即使您UUID在应用程序中生成).我认为如果您使用UUID而不使用短划线,那么存储,比较和排序会更有效UUID(比较byteaUUID看下面).

用于按位操作使用 bit varying

如果你担心存储: bit varying需要更多的存储空间bytea.如果你没事,那么你应该尝试比较它们提供的功能:

位变化bytea

到目前为止,我可以看到bit varying更适合您进行按位操作,尽管bytea通常可以接受存储任意数据的方式.

PostgreSQL提供单个bytea运算符:连接.您可以使用连接运算符将一个byte值附加到另一个bytea||.[1]

请注意bytea,即使是相等/不等式,也无法比较两个值.当然,您可以bytea使用the 将值转换为另一个值CAST(),从而打开其他运算符.[1]

比较UUIDbytea

  create table u(uuid uuid primary key, payload character(300));
  create table b( bytea bytea primary key, payload character(300));

  INSERT INTO u                                                  
  SELECT uuid_generate_v4()                                                     
  FROM generate_series(1,1000*1000);

  INSERT INTO b                                                   
  SELECT random_bytea(16)                                                       
  FROM generate_series(1,1000*1000);

  VACUUM ANALYZE u;
  VACUUM ANALYZE b;

  ## Your table size
  SELECT pg_size_pretty(pg_total_relation_size('u'));
  pg_size_pretty 
  ---------------- 
  81 MB

  SELECT pg_size_pretty(pg_total_relation_size('b'));
  pg_size_pretty 
  ---------------- 
  101 MB

  ## Speed comparison
  \timing on

  ## Common select
  select * from u limit 1000;
  Time: 1.433 ms

  select * from b limit 1000;
  Time: 1.396 ms

  ## Random Select
  SELECT * FROM u OFFSET random()*1000 LIMIT 10000;
  Time: 42.453 ms

  SELECT * FROM b OFFSET random()*1000 LIMIT 10000;
  Time: 10.962 ms
Run Code Online (Sandbox Code Playgroud)

结论:UUID除了它的独特性和更小的尺寸(插入速度更快)之外,我认为不会有更多的好处.

注意:没有索引,只有一个连接

一些来源:

  1. PostgreSQL:"构建,编程和管理PostgreSQL数据库的综合指南"一书