乾貨分享|Bitset 應用詳解

Zilliz發表於2022-02-28

作者:蔡宇東

編者按:
Milvus 2.0 帶來了不少新功能。在這些新功能中,時間旅行(time travel)、屬性過濾和刪除操作相互關聯,因為這三個功能是通過一個共同的機制——Bitset 實現的。Milvus 研發工程師蔡宇東將為大家解析 Milvus 中 Bitset 的概念,並通過三個例子解釋它是如何支援刪除操作、時間旅行和屬性過濾的。

什麼是 Bitset?

從 Milvus 0.7.0 版本開始,為了支援 Delete 功能,我們引入了 Bitset,用於標記 segment 中的每行 entity 是否已被刪除(若 Bitset 對應的 bit 位為 1,表明該行 entity 已被刪除,該行 entity 在查詢時不參與運算)。
在 Milvus 2.0 版本,我們進一步擴充套件了 Bitset 的使用。Bitset 最基本的語義保持不變——若對應的 bit 位為 1,表明該行 entity 不參與查詢運算。但 Bitset 的使用不再侷限於 Delete 操作,有 3 種操作會影響 Bitset,它們分別是:

  1. 屬性過濾
  2. 資料刪除
  3. 時間旅行

在 Milvus 中,Bitset 是如何計算的?

接下來,我們用三個例子來說明 Bitset 是如何計算的。
假設有 1 個 segment ,我們對這個 segment 依次執行了 3 次 DML(data manipulation language)操作:
image.png
Order of DML events

  • 在 ts = 100 時,執行插入操作,插入了 4 條 entity,它們的 primary_keys 分別為 [1, 2, 3, 4];
  • 在 ts = 200 時,執行第二次插入操作,插入另外 4 條 entity,它們的 primary_keys 分別為 [5, 6, 7, 8];
  • 在 ts = 300 時,執行 Delete 操作,刪除了 2 條 entity,它們的 primary_key 分別為 [7, 8]。
  • 同時假設在進行查詢時,通過屬性過濾得到的結果為 primary_key = [1, 3, 5, 7] 。

案例一

image.png
Search with time_traval = 150
假設使用者執行第一次查詢,指定time_travel = 150。Bitset 的計算過程如上圖所示。
filter_bitset 初始狀態為 [1, 0, 1, 0, 1, 0, 1, 0] (此時 bit 位為 1 表示有效),因為查詢時指定的 time_travel = 150,該時刻 pk = [5, 6, 7, 8] 的 entity 還沒有插入,所以 pk = [5, 6, 7, 8] 的 entity 在 Bitset 中對應 bit 位都要清零。計算得到 filter_bitset_2 = [1, 0, 1, 0, 0, 0, 0, 0]。又因為最終結果 bitset 中的 1 應該表示該行 entity 無效,所以需要對 filter_bitset_2 中所有 bit 位取反,得到 filter_bitset_3 = [0, 1, 0, 1, 1, 1, 1, 1]。
del_bitset 初始狀態為 [0, 0, 0, 0, 0, 0, 1, 1],考慮查詢時指定的 time_travel = 150,該時刻 delete 操作還沒有執行,所以 Bitset 所有 bit 位都應該清零,表示所有的資料都是有效的。這樣就得到了 del_bitset_2 = [0, 0, 0, 0, 0, 0, 0, 0]。
把 filter_bitset_3 和 del_bitset_2 進行 OR 操作,可得到最終 result_bitset = [0, 1, 0, 1, 1, 1, 1, 1]。
最終,我們會用 result_bitset 去參與查詢運算。

案例二

image.png

Search with time_traval = 250
假設使用者執行第二次查詢,指定time_travel = 250。Bitset 的計算過程如上圖所示。
與第一個案例一樣,filter_bitset 初始狀態應該是 [1, 0, 1, 0, 1, 0, 1, 0]。
當 ts = 250 時,所有 entity [1, 2, 3, 4, 5, 6, 7, 8] 已經被插入到 Milvus 中。因此,filter_bitset_2和之前 filter_bitset 的結果保持不變。同樣,我們要對 filter_bitset_2 的所有 bit 位取反,得到 [0, 1, 0, 1, 0, 1, 0, 1]。
del_bitset 初始狀態為 [0, 0, 0, 0, 0, 1, 1]。同樣考慮查詢時指定的 time_travel = 250,該時刻 delete 操作還沒有執行,所以 Bitset 所有 bit 位都應該清零,表示所有的資料都是有效的。因此,time travel 後的 del_bitset_2 = [0, 0, 0, 0, 0, 0, 0]。
把 filter_bitset_3 和 del_bitset_2 進行 OR 操作,可得到最終 result_bitset = [0, 1, 0, 1, 0, 1, 0, 1]。
最終只有 entities [1, 3, 5, 7] 會參與之後的查詢運算。

案例三

假設使用者執行第三次查詢,指定time_travel = 350。那麼,Bitset 的計算過程是什麼樣的?參考上方兩個案例進行思考。
image.png

預告

不久之前,我們還介紹了 Milvus 2.0 中的資料刪除設計。
在接下來的文章中,我們將繼續介紹 Milvus 2.0 中資料壓縮、動態負載均衡等功能背後的邏輯,歡迎大家繼續關注!

Milvus 專案地址:https://github.com/milvus-io/...
Milvus 主頁及文件地址:https://milvus.io/
Milvus Slack Channel:milvusio.slack.com

相關文章