【问题标题】:Most efficient way of manipulating a very large text database of SHA256 hashes?操作非常大的 SHA256 哈希文本数据库的最有效方法?
【发布时间】:2014-06-06 17:54:03
【问题描述】:

我必须经常在大型(高达 1G)格式的 CSV 数据库中搜索哈希

sha256_hash, md5_hash, sha1_hash, field1, field2, field3 etc

在 C 中。这需要非常快,并且内存使用不是问题(最低 32G)。我发现this 与我的想法非常接近:将数据加载到 RAM 中,按哈希对数据库进行一次性排序,按哈希的前 'n' 个字节索引,然后搜索较小的子列表。但是上面的线程似乎没有解决我中间的一个问题。由于我不是密码学专家,我想知道哈希的分布以及它是否可以用来更快地搜索子列表。关于这个或我的一般方法有什么建议吗?

【问题讨论】:

    标签: c database hash lookup


    【解决方案1】:

    是的,布隆过滤器可用于通过散列位的分布及早剔除“明确的否定”。

    http://en.wikipedia.org/wiki/Bloom_filter

    要为给定的存储桶创建布隆过滤器,逻辑或所有哈希值一起创建您的过滤器。然后将过滤器与您的目标哈希进行逻辑与。如果结果

    必须注意桶的大小,以便生成有意义的过滤器,因为所有高位的过滤器对任何人都没有价值。

    【讨论】:

    • 阅读 Wiki 文章,这正是我想要的。谢谢。看起来 Murmur3 是与 Bloom 过滤器一起使用的推荐散列。对此有何评论?
    • 你可以使用 Murmur3,但我担心你会进一步减少你的位空间。由于您从一开始就使用散列,因此我认为不需要再次对其进行重新散列,我认为您可以将源材料用于过滤器。当然,如果情况并非如此,并且您需要先对密钥进行哈希处理,那么 Murmur3 是一个不错的选择,因为您可以调整密钥大小(32/128 位)以适应您的预期分布,而且计算成本非常低。 CityHash 也是一个不错的选择。
    【解决方案2】:

    这是一个非常容易解决的问题,需要大量内存。使散列成为散列表的键。将您提供给表的散列设为散列的前 N ​​个字节(因为它们是如此随机,以至于地球上没有人可以将它们与真正的随机数据区分开来)。

    不确定您的想法是如何使用键的前缀键入表并具有子列表。任何库存库提供的哈希表都可以轻松解决您的问题。

    或将其放入任何数据库中,并将哈希作为主键。

    【讨论】:

    • “完全随机”是不正确的术语:您要查找的术语是均匀分布
    • @DietrichEpp 你可能是对的。它们是如此随机,以至于地球上没有人能从真正随机的数据中分辨出来。
    • 某事要么是随机的,要么不是随机的,我们不知道这些特定的哈希是否是随机的。但是,它们确实具有特定的分布。 “随机”是错误的术语。
    • @usr 这不是统一分布的意思,也不是这里的相关属性。随机变量可以具有无限数量的分布(描述每个值的可能性)。例如,随机比特流输出 1 的频率可能远高于 0。只有均匀分布(所有输出的可能性相同)或非常相似的东西才能使哈希表快速。 人类是否能注意到这不是“真正随机的”,这无关紧要。
    • @delnan:看到你的评论,我有点困惑:“这不是均匀分布的意思”......这句话所指的“那个”是什么?
    【解决方案3】:

    散列的分布是均匀的,这很有帮助,因为您可以将散列放在散列表中。

    // something like this...
    struct entry {
        bool used;
        unsigned char sha256[32];
        char field1[20];
        char field2[20];
    };
    

    如果您不需要从哈希表中删除条目,只需创建一个 struct entry 的大数组并将 CSV 中的记录插入到与 SHA-256 哈希中的某些位相对应的索引中。使用线性探测插入条目:如果条目 i 被占用,则使用 i+1i+2,直到找到空闲条目。

    struct table {
        int nbits;
        struct entry *entries;
    };
    
    unsigned read_int(unsigned char *data)
    {
        unsigned v = data[0] | (data[1] << 8) |
                     (data[2] << 16) | ((unsigned)data[3] << 24);
    }
    
    struct entry *find_entry(struct table *table, unsigned char *sha256)
    {
        unsigned index = read_int(sha256);
        unsigned mask = (1u << table->nbits) - 1;
        while (1) {
            struct entry *e = &table->entries[index & mask];
            if (!e->used)
                return NULL;
            if (!memcmp(e->sha256, sha256, 32))
                return e;
            index++;
        }
    }
    

    【讨论】:

    • 你会建议什么哈希函数?只是将整个 SHA-256 哈希取模表大小(大概是 2 的幂)?
    • @delnan:是的,只需从 SHA-256 哈希中切掉一些位。
    猜你喜欢
    • 1970-01-01
    • 2011-07-15
    • 2014-01-29
    • 2019-08-23
    • 2010-09-27
    • 1970-01-01
    • 2011-06-08
    • 2019-01-23
    • 1970-01-01
    相关资源
    最近更新 更多