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

时间:2014-10-29 16:18:45

标签: postgresql bit-manipulation

PostgreSQL类型byteabit varying听起来类似:

文档未提及任何一个的最大大小。它是1GB,如character varying吗?

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

存储MD5哈希

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

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

存储任意二进制数据

不同长度的二进制数据字符串,最高可达4kB:

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

使用bit varying进行按位操作的工作示例。面具是X&00; 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';

哪个byteabit varying更合适?

我看到UUID类型用于存储16个字节,这对存储MD5有什么好处吗?

2 个答案:

答案 0 :(得分:10)

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

我在bytea中存储较大的值,然后在可能的情况下将子字符串转换为bit varying以进行按位运算,主要是因为客户端比bytea和{I}更加一致地理解bit varying / O格式更紧凑。

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

我认为bit varying确实有两种用途:

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

对于其他所有内容,请使用bytea

如果那就是存储4k位字段,那就没有什么可以阻止你了。

答案 1 :(得分:7)

  1. 似乎bytea的最大长度为1 GB。 [1]
  2. 对于按位操作,请使用bit varying(解释见下文)
  3. 用于存储MD5哈希使用bytea。它将比bit varying
  4. 占用更少的存储空间
  5. 使用UUID的优势是UUID算法以某种方式保证您的唯一性,不仅在您的表中,而且在您的数据库中,甚至在您的数据库中(即使您生成UUID你的申请)。我认为如果你使用没有短划线的UUID,那么在UUID中进行存储,比较和排序会更有效(byteaUUID之间的比较,见下文)。
  6. 对于按位操作,请使用bit varying

    如果您担心存储空间: bit varying占用的存储空间超过bytea。如果你没事,那么你应该尝试比较它们提供的功能:

    bit varying VS bytea

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

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

    请注意,即使是相等/不等式,也无法比较两个bytea值。当然,您可以使用byteaCAST()值转换为另一个值,从而打开其他运算符。 [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
    

    结论:我不认为使用UUID会有更多好处,除了它的唯一性和更小的尺寸(插入速度会更快)

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

    有些消息来源:

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