【问题标题】:Generate hash id for records in DB为数据库中的记录生成哈希 id
【发布时间】:2021-11-26 17:56:07
【问题描述】:

我有一组单元测试,它们在运行时将数据保存在 DB (postgres) 中。 偶尔会因为一些重复数据,导致机器性能变慢,所以我们需要清理db(数据不重要,但需要保存一段时间以供内部处理)。

我想,作为一个临时解决方案,延长删除数据的时间段, 为保存在数据库中的每条记录在 my 中生成一个哈希 id,以避免重复(因此,如果哈希 id 存在,则不会保存)。

我知道一组不同的数据可能会产生相同的哈希 id - 没关系,我会处理这个逻辑。

我需要生成那些散列的 id,在 java 中,它需要在 long 类型的范围内。 java的内置方法“Objects.hash()”产生int类型的结果。 我寻找的任何其他解决方案都是使用 UUID 或任何其他产生字符序列的散列算法。

【问题讨论】:

    标签: java postgresql hash hashcode


    【解决方案1】:

    Postgres 14 为记录添加哈希函数。其中一个返回bigint

    hash_record_extended(record, bigint) --> bigint
    

    它会为记录生成一个bigint 哈希,这正是您要寻找的。 (但在 Postgres 中生成,而不是在 Java 中生成。)
    请参阅 pgsql-hackers 中这些线程中的讨论:

    如果你问我,这很重要。但它没有在发行说明中宣传,也没有在手册中记录。它旨在供内部使用,以支持UNION [DISTINCT]、散列连接和散列分区。

    但我认为没有什么可以阻止您将其用于您的目的。这是对这个相关解决方案的增量改进(目前基于 Postgres 13):

    附有bigint 哈希的碰撞概率的详细评估。 TLDR:几乎不可能达到几百万行。

    【讨论】:

      【解决方案2】:

      一个简单的 64 位散列可以通过结合 CRC32 和 Adler32 来实现。

      这是 Java 中的一个示例:

      package com.example;
      
      import java.util.zip.Adler32;
      import java.util.zip.CRC32;
      
      public class MySimpleHash {
      
          /**
           * Calculate a 64 bits hash by combining CRC32 with Adler32.
           * 
           * @param bytes a byte array
           * @return a hash number
           */
          public static long getHash(byte[] bytes) {
      
              CRC32 crc32 = new CRC32();
              Adler32 adl32 = new Adler32();
      
              crc32.update(bytes);
              adl32.update(bytes);
      
              long crc = crc32.getValue();
              long adl = adl32.getValue();
      
              return (crc << 32) | adl;
          }
      
          public static void main(String[] args) {
              String string = "This is a test string";
              long hash = getHash(string.getBytes());
              System.out.println("output: " + hash);
          }
      }
      
      output: 7732385261082445741
      

      这是另一个在 Python 中执行相同操作的示例:

      #!/usr/bin/python3
      
      import zlib
      
      def get_hash(bytes):
          return zlib.crc32(bytes) << 32 | zlib.adler32(bytes)
      
      string = "This is a test string"
      hash = get_hash(string.encode())
      print("output:", hash)
      
      output: 7732385261082445741
      

      我有一个要点,它比较了一些生成 32 位和 64 位哈希的策略: https://gist.github.com/fabiolimace/507eac3d35900050eeb9772e5b1871ba

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-01-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-29
        • 1970-01-01
        相关资源
        最近更新 更多