介紹 Milvus Ngram 索引:更快的關鍵字比對和代理工作量的 LIKE 查詢
在代理系統中,情境擷取是整個管道的基礎建構區塊,為下游推理、規劃和行動提供基礎。矢量搜尋可協助代理系統擷取語意相關的情境,以捕捉大型非結構化資料集的意圖和意義。然而,僅有語意相關性往往是不夠的。代理程式管道也仰賴全文檢索來強制執行精確的關鍵字限制,例如產品名稱、功能呼叫、錯誤代碼或法律上重要的詞彙。此支援層可確保擷取的上下文不僅相關,而且明確地滿足硬性文字需求。
真實的工作負載持續反映出這種需求:
客戶支援助理必須找到提及特定產品或成份的對話。
編碼副駕駛尋找包含精確函式名稱、API 呼叫或錯誤字串的片段。
法律、醫療和學術代理過濾文件中必須逐字出現的條款或引文。
傳統上,系統會使用 SQLLIKE 運算符號來處理。像name LIKE '%rod%' 這樣的查詢很簡單,也受到廣泛的支援,但在高並發和大量資料的情況下,這種簡單性會帶來重大的效能代價。
如果沒有索引,
LIKE查詢會掃描整個上下文儲存區,並逐行套用模式匹配。當記錄數量達到數百萬筆時,即使是單一查詢也可能需要數秒,對於即時代理互動來說,這實在太慢了。即使使用傳統的反向索引,通配符模式 (例如
%rod%) 仍然難以最佳化,因為引擎仍必須遍歷整個字典,並在每個項目上執行模式匹配。此作業可避免行掃描,但基本上仍是線性的,因此只能帶來微不足道的改善。
這在混合式檢索系統中造成了明顯的差距:向量搜尋能有效率地處理語意相關性,但精確關鍵字篩選往往成為管道中最慢的步驟。
Milvus 原生支援混合向量與全文檢索,並具備元資料篩選功能。為了解決關鍵字比對的限制,Milvus 引進了Ngram 索引,透過將文字分割成小的子串並建立索引以進行有效的查詢,從而改善LIKE 的效能。這可大幅減少查詢執行時所檢視的資料量,在實際代理工作負載中提供數十倍至數百倍的 LIKE 查詢速度。
本篇文章的其餘部分將介紹 Ngram 索引如何在 Milvus 中運作,並評估其在真實情境中的效能。
什麼是 Ngram 索引?
在資料庫中,文字篩選通常使用SQL 來表達,SQL 是用來擷取和管理資料的標準查詢語言。其最廣泛使用的文字運算符之一是LIKE ,它支援基於模式的字串匹配。
根據通配符的使用方式,LIKE 表達式大致可分為四種常見的模式類型:
Infix match(
name LIKE '%rod%'):匹配子串 rod 在文本中任何位置出現的記錄。前綴匹配(
name LIKE 'rod%'):匹配文字以 rod 開頭的記錄。後綴匹配(
name LIKE '%rod'):匹配文字以 rod 結尾的記錄。通配符匹配(
name LIKE '%rod%aab%bc_de'):將多個子串條件 (%) 與單字元通配符 (_) 結合為單一模式。
雖然這些模式在外觀和表達力上有所不同,但 Milvus 中的Ngram 索引使用相同的基本方法加速所有這些模式。
在建立索引之前,Milvus 會將每個文字值分割成固定長度的短小、重疊子串,稱為n-gram。例如,當 n = 3 時,單字「Milvus」會被分解成下列 3 個字元:"Mil"、 "ilv"、" lvu 「和」vus"。然後,每個 n-gram 會儲存在一個反向索引中,該索引會將子串映射到出現該子串的文件 ID 集。在查詢時,LIKE 條件會轉換成 n-gram 查詢的組合,讓 Milvus 可以快速篩選出大部分不匹配的記錄,並針對小得多的候選集評估模式。這就是將昂貴的字串掃描轉變為高效率的索引式查詢的原因。
兩個參數控制 Ngram 索引的建構方式:min_gram 和max_gram 。這兩個參數一起定義了 Milvus 產生和索引的子串長度範圍。
min_gram:要索引的最短子串長度。實際上,這也設定了可以從 Ngram 索引獲益的最小查詢子串長度。max_gram:要索引的最長子串長度。在查詢時,它還決定了將較長的查詢字串分割成 n-gram 時所使用的最大視窗大小。
透過索引所有長度介於min_gram 與max_gram 之間的連續子串,Milvus 建立了一致且有效率的基礎,以加速所有支援的LIKE 模式類型。
Ngram 索引如何運作?
Milvus 在兩個階段的過程中實現 Ngram 索引:
建立索引:在資料擷取過程中,為每個文件產生 n-grams,並建立反向索引。
加速查詢:使用索引將搜尋範圍縮小到一個小的候選集,然後在這些候選集上驗證精確的
LIKE匹配。
一個具體的例子可以讓您更容易理解這個過程。
階段 1:建立索引
將文字分解成 n-gram:
假設我們以下列設定為文字「Apple」建立索引:
min_gram = 2max_gram = 3
在此設定下,Milvus 會產生所有長度為 2 和 3 的連續子串:
2-grams:
Ap,pp,pl、le3-grams:
App,ppl、ple
建立反向索引:
現在考慮一個包含五筆記錄的小型資料集:
文件 0:
Apple文件 1:
Pineapple文件 2:
Maple文件 3:
Apply文件 4:
Snapple
在擷取過程中,Milvus 會為每條記錄產生 n-grams,並將它們插入一個倒轉索引中。在這個索引中
鍵是 n-grams(子串)
值是出現 n-gram 的文件 ID 清單。
"Ap" -> [0, 3]
"App" -> [0, 3]
"Ma" -> [2]
"Map" -> [2]
"Pi" -> [1]
"Pin" -> [1]
"Sn" -> [4]
"Sna" -> [4]
"ap" -> [1, 2, 4]
"apl" -> [2]
"app" -> [1, 4]
"ea" -> [1]
"eap" -> [1]
"in" -> [1]
"ine" -> [1]
"le" -> [0, 1, 2, 4]
"ly" -> [3]
"na" -> [4]
"nap" -> [4]
"ne" -> [1]
"nea" -> [1]
"pl" -> [0, 1, 2, 3, 4]
"ple" -> [0, 1, 2, 4]
"ply" -> [3]
"pp" -> [0, 1, 3, 4]
"ppl" -> [0, 1, 3, 4]
現在索引已完全建立。
第二階段:加速查詢
當LIKE 過濾器執行時,Milvus 會使用 Ngram 索引,透過下列步驟加速查詢評估:
1.擷取查詢字詞:從LIKE 表達式中萃取沒有通配符的連續子串 (例如,'%apple%' 變成apple)。
2.分解查詢詞:根據查詢詞的長度 (L) 以及配置的min_gram 和max_gram ,將查詢詞分解為 n 個字元。
3.尋找每個gram & intersect:Milvus 在倒排索引中尋找查詢的 n-gram 並將它們的文件 ID 清單相交,以產生一個小的候選集。
4.驗證並返回結果:原始的LIKE 條件僅應用於此候選集,以決定最終結果。
實際上,將查詢分割成 n-gram 的方式取決於模式本身的形狀。為了瞭解其運作方式,我們將集中討論兩種常見的情況:後綴匹配 (infix matches) 和通配符匹配 (wildcard matches)。前綴和後綴匹配的行為與後綴匹配相同,因此我們將不會單獨介紹它們。
次序匹配
對於中位數匹配,執行取決於字面子串 (L) 相對於min_gram 和max_gram 的長度。
1.min_gram ≤ L ≤ max_gram(例如strField LIKE '%ppl%')
字面子串ppl 完全在設定的 n-gram 範圍內。Milvus 直接在倒排索引中查找 n-gram"ppl" ,產生候選文件 ID[0, 1, 3, 4] 。
由於字面本身就是索引的 n-gram,因此所有候選文件都已經滿足後綴條件。最後的驗證步驟不會消除任何記錄,結果仍然是[0, 1, 3, 4] 。
2.L > max_gram(例如strField LIKE '%pple%')
字面子串pple 比max_gram 長,因此使用max_gram 的視窗大小將其分解為重疊的 n-gram。加上max_gram = 3 ,就產生了 n-gram:"ppl" 和"ple" 。
Milvus 在倒排索引中查找每個 n-gram:
"ppl"→[0, 1, 3, 4]"ple"→[0, 1, 2, 4]
將這些列表相交,得到候選集[0, 1, 4] 。然後,原始的LIKE '%pple%' 過濾器會套用在這些候選字上。三者都滿足條件,因此最終結果仍是[0, 1, 4] 。
3.L < min_gram(例如strField LIKE '%pp%')
字面子串短於min_gram ,因此無法分解成索引的 n-gram。在這種情況下,無法使用 Ngram 索引,Milvus 會回到預設的執行路徑,透過模式匹配的完整掃描來評估LIKE 條件。
通配符匹配(例如strField LIKE '%Ap%pple%')
此模式包含多個通配符,因此 Milvus 首先將其分割為連續的字面意義:"Ap" 和"pple" 。
然後 Milvus 獨立處理每個字面:
"Ap"長度為 2 且在 n-gram 範圍內。"pple"比max_gram長,並分解為"ppl"和"ple"。
這將查詢縮小為以下 n 個字元:
"Ap"→[0, 3]"ppl"→[0, 1, 3, 4]"ple"→[0, 1, 2, 4]
將這些列表相交會產生單一的候選字:[0] 。
最後,原始的LIKE '%Ap%pple%' 過濾器會套用到第 0 個文件 ("Apple")。由於它不滿足完整模式,最終結果集為空。
Ngram 索引的限制與取捨
雖然 Ngram 索引可以顯著改善LIKE 的查詢效能,但它也引入了在實際部署中應該考慮的權衡。
- 索引大小增加
Ngram 索引的主要成本是較高的儲存開銷。由於索引會儲存所有長度介於min_gram 和max_gram 之間的連續子串,因此當這個範圍擴大時,產生的 n-gram 數量會快速增加。每增加一個 n-gram 長度,就會有效地為每個文字值增加一整套重疊的子串,同時增加索引鍵的數量和它們的發佈清單。實際上,與標準的倒置索引相比,只要將範圍擴大一個字元,索引大小就會增加約一倍。
- 並非對所有工作負載都有效
Ngram 索引並不能加速每種工作負載。如果查詢模式非常不規則、包含非常短的字面意義、或在篩選階段未能將資料集縮減為小的候選集,其效能效益可能有限。在這種情況下,即使索引存在,查詢的執行成本仍可能接近完整掃描的成本。
評估 Ngram 索引在 LIKE 查詢上的效能
本基準的目標是評估 Ngram 索引在實際中如何有效地加速LIKE 查詢。
測試方法
為了讓其效能符合實際情況,我們將其與兩種基線執行模式進行比較:
主模式:不使用任何索引的強制執行。
Master-inverted:使用傳統反轉索引執行。
我們設計了兩個測試情境,以涵蓋不同的資料特性:
Wiki 文字資料集:100,000 行,每個文字欄位截斷為 1 KB。
單字資料集:1,000,000 行,每行包含一個單字。
在這兩種情況下,都會一致地套用下列設定:
查詢使用下位元匹配模式(
%xxx%)Ngram 索引配置為
min_gram = 2和max_gram = 4為了隔離查詢執行成本並避免結果實體化開銷,所有查詢都會傳回
count(*),而非完整的結果集。
結果
wiki 測試,每行為內容長度截斷為 1000 的 wiki 文字,100K 行
| 字面意義 | 時間(ms) | 加速 | 計數 | |
|---|---|---|---|---|
| 大師 | 體育館 | 207.8 | 335 | |
| 主-倒置 | 2095 | 335 | ||
| Ngram | 1.09 | 190 / 1922 | 335 | |
| 大師 | 中學 | 204.8 | 340 | |
| 碩士轉換 | 2000 | 340 | ||
| Ngram | 1.26 | 162.5 / 1587 | 340 | |
| 大師 | 是一所男女合校的中學。 | 223.9 | 1 | |
| 師資轉換 | 2100 | 1 | ||
| Ngram | 1.69 | 132.5 / 1242.6 | 1 |
單字測試,1M 行
| 字面意義 | 時間(毫秒) | 速度提升 | 計數 | |
|---|---|---|---|---|
| 主程式 | 主 | 128.6 | 40430 | |
| 主反向 | 66.5 | 40430 | ||
| Ngram | 1.38 | 93.2 / 48.2 | 40430 | |
| 大師 | 寧 | 122 | 5200 | |
| 主-反相 | 65.1 | 5200 | ||
| Ngram | 1.27 | 96 / 51.3 | 5200 | |
| 大師 | 寧 | 118.8 | 1630 | |
| 主-反相 | 66.9 | 1630 | ||
| Ngram | 1.21 | 98.2 / 55.3 | 1630 | |
| 大師 | 國家 | 118.4 | 1100 | |
| 主-反相 | 65.1 | 1100 | ||
| Ngram | 1.33 | 89 / 48.9 | 1100 | |
| 主 | 國家 | 118 | 1100 | |
| 主-倒置 | 63.3 | 1100 | ||
| Ngram | 1.4 | 84.3 / 45.2 | 1100 |
註:這些結果是基於五月份進行的基準測試。自此之後,Master 分支進行了額外的效能最佳化,因此在此觀察到的效能差距,預計在目前的版本中會較小。
基準測試結果突顯了一個明顯的模式:Ngram 索引在所有情況下都能顯著加速 LIKE 查詢,而查詢執行速度的快慢在很大程度上取決於底層文字資料的結構和長度。
對於長文字欄位,例如截短至 1,000 位元組的 Wiki 式文件,效能提升尤其明顯。與沒有索引的暴力執行相比,Ngram 索引的速度提升了約100-200×。如果與傳統的倒轉式索引比較,改善幅度更大,可達1,200-1,900 倍。這是因為對於傳統索引方法來說,長文本的 LIKE 查詢成本特別高,而 N-gram 查詢則可以快速將搜尋空間縮小到很小的候選詞集合。
在由單字條目組成的資料集上,收益較小,但仍然可觀。在這種情況下,N-gram 索引的執行速度約比暴力執行快80-100 倍,比傳統的倒序索引快45-55 倍。雖然較短的文字本質上掃描成本較低,但基於「n-gram」的方法仍可避免不必要的比較,並持續降低查詢成本。
結論
Ngram 索引透過將文字分割成固定長度的 n-gram,並使用倒置結構為其編制索引,加速LIKE 查詢。此設計可將昂貴的子串比對轉變為高效率的 n-gram 查詢,然後再進行最少的驗證。因此,可以避免全文掃描,同時保留LIKE 的精確語意。
實際上,這種方法在各種工作負載中都很有效,尤其在長文字欄位的模糊比對上有很好的效果。因此,Ngram 索引非常適合用於即時情境,例如代碼搜尋、客戶支援代理、法律與醫療文件檢索、企業知識庫以及學術搜尋,在這些情境中,精確的關鍵字比對仍然是不可或缺的。
與此同時,Ngram Index 也能從仔細的配置中獲益。選擇適當的min_gram 和max_gram 值對平衡索引大小和查詢效能至關重要。當調整到反映真實查詢模式時,Ngram 索引可為生產系統中的高效能LIKE 查詢提供實用、可擴充的解決方案。
如需更多關於 Ngram 索引的資訊,請參閱下列說明文件:
對最新 Milvus 的任何功能有問題或想要深入瞭解?加入我們的 Discord 頻道或在 GitHub 上提出問題。您也可以透過 Milvus Office Hours 預約 20 分鐘的一對一課程,以獲得深入的瞭解、指導和問題解答。
進一步了解 Milvus 2.6 功能
Try Managed Milvus for Free
Zilliz Cloud is hassle-free, powered by Milvus and 10x faster.
Get StartedLike the article? Spread the word



