簡體   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