MySQL按位运算,布隆过滤器

时间:2008-12-11 20:54:39

标签: mysql bit-manipulation

我想使用MySQL(其他建议的替代方案)实现bloom filter

问题如下:

假设我有一个存储8位整数的表,其中包含以下值:

1: 10011010
2: 00110101
3: 10010100
4: 00100110
5: 00111011
6: 01101010

我想找到与此相关的所有结果:

00011000

结果应该是第1行和第5行。

然而,在我的问题中,它们不是8位整数,而是n位整数。我该如何存储,以及如何查询?速度是关键。

6 个答案:

答案 0 :(得分:19)

使用int列创建一个表(使用this link来选择正确的int大小)。不要将数字存储为0和1的序列。

对于您的数据,它将如下所示:

number

154
53
148
38
59
106

,您需要找到与24匹配的所有条目。

然后你可以运行像

这样的查询
SELECT * FROM test WHERE number & 24 = 24

如果您想避免在应用程序中转换为10个基本数字,可以将其交给mysql:

INSERT INTO test SET number = b'00110101';

并像这样搜索

SELECT bin(number) FROM test WHERE number & b'00011000' = b'00011000'

答案 1 :(得分:8)

考虑不使用MySQL。

首先,可能没有超过64位表的内置方法。您必须使用用C编写的用户定义函数。

其次,每个查询都需要进行全表扫描,因为MySQL无法使用索引进行查询。所以,除非你的桌子非常小,否则这不会很快。

答案 2 :(得分:2)

切换到PostgreSQL并使用bit(n)

答案 3 :(得分:2)

布隆过滤器本质上需要表扫描来评估匹配。在MySQL中,没有布隆过滤器类型。简单的解决方案是将布隆过滤器的字节映射到BitInteger(8字节字)并在查询中执行检查。因此,假设bloom过滤8个字节或更少(一个非常小的过滤器),你可以执行一个准备好的语句,如:

SELECT * FROM test WHERE cast(filter, UNSIGNED) & cast(?, UNSIGNED) = cast(?, UNSIGNED)

并将参数替换为您要查找的值。但是,对于较大的过滤器,您必须创建多个filter列,并将目标过滤器拆分为多个单词。你必须转为无符号才能正确地进行检查。

由于许多合理的布隆过滤器在Kilo到Megabyte范围内,因此使用blob来存储它们是有意义的。切换到blob后,没有本机机制来执行字节级比较。并且在整个网络中提取整个大型blob表以在本地代码中进行过滤没有多大意义。

我找到的唯一合理的解决方案是UDF。 UDF应接受char*并对其进行迭代,将char*转换为unsigned char*并执行target & candidate = target检查。此代码看起来像:

my_bool bloommatch(UDF_INIT *initid, UDF_ARGS *args, char* result, unsigned long* length, char *is_null, char *error)
{
    if (args->lengths[0] > args->lengths[1])
    {
        return 0;
    }
    char* b1=args->args[0];
    char* b2=args->args[1];
    int limit = args->lengths[0];
    unsigned char a;
    unsigned char b;
    int i;
    for (i=0;i<limit;i++)
    {
        a = (unsigned char) b1[i];
        b = (unsigned char) b2[i];
        if ((a & b) != a)
        {
            return 0;
        }
    }
    return 1;
}

此解决方案已实施且可用here

答案 4 :(得分:0)

对于最多64位,您可以使用MySQL整数类型,如tinyint(8b),int(16b),mediumint(24b)和bigint(64b)。使用无符号变体。

高于64b,使用MySQL(VAR)BINARY类型。那些是原始字节缓冲区。 例如,BINARY(16)适用于128位。

为了防止表扫描,每个有用位需要一个索引,和/或每个相关位的索引。您可以为其创建虚拟列,并为每个列添加索引。

答案 5 :(得分:0)

要使用数据库实现布隆过滤器,我会有所不同。

我将进行两级过滤。使用单个多位哈希函数生成ID(这更像是哈希表存储区索引),然后将行中的位用于更经典的其余k-1个哈希函数。在该行中,它可能是(例如)100 bigint列(我也将性能与BLOB进行比较)。

实际上是N个单独的Bloom过滤器,其中N是第一个哈希函数的域。这个想法是通过选择一个哈希桶来减少所需的Bloom过滤器的大小。它不具有内存内Bloom过滤器的全部效率,但是与将所有值放入数据库并为其建立索引相比,它仍然可以大大减少需要存储的数据量。大概首先使用数据库的原因是缺少用于完整Bloom筛选器的内存。