繁体   English   中英

MySQL按位运算,布隆过滤器

[英]MySQL bitwise operations, bloom filter

我想使用MySQL实现布隆过滤器 (其他建议的替代方法)。

问题如下:

假设我有一个存储8位整数的表,这些表具有以下值:

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

我想找到所有按位与之相关的结果:

00011000

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

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

创建一个带有int列的表(使用此链接选择正确的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'

考虑不为此使用MySQL。

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

其次,每个查询都需要全表扫描,因为MySQL不能为您的查询使用索引。 因此,除非您的桌子很小,否则不会很快。

Bloom过滤器的性质要求进行表扫描以评估匹配项。 在MySQL中,没有Bloom筛选器类型。 一种简单的解决方案是将Bloom筛选器的字节映射到BitInteger(8字节字)上并在查询中执行检查。 因此,假设Bloom过滤器过滤了8个字节或更少的字节(一个很小的过滤器),则可以执行以下准备语句:

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

并用所需的值替换参数。 但是,对于较大的过滤器,您必须创建多个filter列并将目标过滤器拆分为多个单词。 您必须强制转换为unsigned才能正确执行检查。

由于许多合理的布隆过滤器的大小都在千字节至兆字节范围内,因此使用斑点存储它们是有意义的。 一旦切换到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;
}

此解决方案已实现,可在此处获得

切换到PostgreSQL并使用bit(n)

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

在64b以上,请使用MySQL(VAR)BINARY类型。 这些是原始字节缓冲区。 例如BINARY(16)适合128位。

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM