作者:Adrien Grand
你是否有興趣了解 Elasticsearch 用于向量搜索(vector search)的特性以及設(shè)計(jì)是什么樣子? 一如既往,設(shè)計(jì)決策有利有弊。 本博客旨在詳細(xì)介紹我們?nèi)绾芜x擇在 Elasticsearch 中構(gòu)建向量搜索。
向量搜索通過 Apache Lucene 集成到 Elasticsearch 中
首先是有關(guān) Lucene 的一些背景知識(shí):Lucene 將數(shù)據(jù)組織成定期合并的不可變段(segments)。 添加更多文檔需要添加更多段。 修改現(xiàn)有文檔需要自動(dòng)添加更多段并將這些文檔的先前版本標(biāo)記為已刪除。 段內(nèi)的每個(gè)文檔都由文檔 ID 標(biāo)識(shí),文檔 ID 是該文檔在段內(nèi)的索引,類似于數(shù)組的索引。 這種方法的動(dòng)機(jī)是管理倒排索引,倒排索引不擅長(zhǎng)就地修改,但可以有效地合并。
除了倒排索引之外,Lucene 還支持存儲(chǔ)字段(stored fields,一個(gè)文檔存儲(chǔ))、文檔值(doc values,列式存儲(chǔ))、術(shù)語向量(term vectors, 每個(gè)文檔的倒排索引)及其段中的多維點(diǎn)。 向量已以相同的方式積分:
- 新向量在索引時(shí)緩沖到內(nèi)存中。
- 當(dāng)超過索引時(shí)間緩沖區(qū)的大小或必須使更改可見時(shí),這些內(nèi)存中的緩沖區(qū)將被序列化為段的一部分。
- 段(segements)會(huì)在后臺(tái)定期合并在一起,以控??制段總數(shù)并限制每個(gè)段的總體搜索時(shí)間開銷。 由于它們是段的一部分,因此向量也需要合并。
- 搜索必須組合索引中所有段的頂部向量命中。
- 對(duì)向量的搜索必須查看實(shí)時(shí)文檔集,以便排除標(biāo)記為已刪除的文檔。
上面的系統(tǒng)是由 Lucene 的工作方式驅(qū)動(dòng)的。
Lucene 目前使用分層可導(dǎo)航小世界 (Hierarchical Navigable Small World - HNSW) 算法來索引向量。 在較高層次上,HNSW 將向量組織成一個(gè)圖表,其中相似的向量可能會(huì)連接起來。 HNSW 是向量搜索的熱門選擇,因?yàn)樗喈?dāng)簡(jiǎn)單,在向量搜索算法的比較基準(zhǔn)上表現(xiàn)良好,并且支持增量插入。 Lucene 對(duì) HNSW 的實(shí)現(xiàn)遵循 Lucene 將數(shù)據(jù)保留在磁盤上并依靠頁面緩存來加速對(duì)頻繁訪問的數(shù)據(jù)的訪問的準(zhǔn)則。
近似向量搜索通過 knn 部分在 Elasticsearch 的 _search API 中公開。 使用此功能將直接利用 Lucene 的向量搜索功能。 向量還集成在 Elasticsearch 的腳本 API 中,允許執(zhí)行精確的強(qiáng)力搜索(brute-force search),或利用向量進(jìn)行重新評(píng)分。
現(xiàn)在讓我們深入探討通過 Apache Lucene 集成向量搜索的優(yōu)缺點(diǎn)。
缺點(diǎn)
利用 Apache Lucene 進(jìn)行向量搜索的主要缺點(diǎn)是 Lucene 將向量與段聯(lián)系起來。 然而,正如我們稍后將在 優(yōu)點(diǎn) ”部分中看到的,將向量與段聯(lián)系起來也是實(shí)現(xiàn)高效預(yù)過濾、高效混合搜索和可見性一致性等主要功能的原因。
合并需要重新計(jì)算 HNSW 圖
段合并需要采用 N 個(gè)輸入段(默認(rèn)合并策略通常為 10 個(gè)),并將它們合并為單個(gè)段。Lucene 當(dāng)前從沒有刪除操作的最大輸入段創(chuàng)建 HNSW 圖的副本,然后將來自其他段的向量添加到此 HNSW 圖。 與在索引的生命周期內(nèi)就地改變單個(gè) HNSW 圖相比,這種方法會(huì)產(chǎn)生索引時(shí)間開銷,因?yàn)槎问呛喜⒌摹?/p>
搜索需要合并多個(gè)細(xì)分的結(jié)果
由于索引由多個(gè)段組成,因此搜索需要計(jì)算每個(gè)段上的 top-k 向量,然后將這些每個(gè)段的 top-k 命中合并為全局 top-k 命中。 通過并行搜索段可以減輕對(duì)延遲的影響,但與搜索單個(gè) HNSW 圖相比,這種方法仍然會(huì)產(chǎn)生一些開銷。
RAM 需要隨著數(shù)據(jù)集的大小進(jìn)行擴(kuò)展以保持最佳性能
遍歷 HNSW 圖會(huì)產(chǎn)生大量隨機(jī)訪問。 為了高效執(zhí)行,數(shù)據(jù)集應(yīng)適合頁面緩存,這需要根據(jù)所管理的向量數(shù)據(jù)集的大小調(diào)整 RAM 的大小。 除了 HNSW 之外,還存在其他用于向量搜索的算法,它們具有更適合磁盤的訪問模式,但它們也有其他缺點(diǎn),例如更高的查詢延遲或更差的召回率。
優(yōu)點(diǎn)
數(shù)據(jù)集可以擴(kuò)展到超出 RAM 總大小
由于數(shù)據(jù)存儲(chǔ)在磁盤上,Elasticsearch 將允許數(shù)據(jù)集大于本地主機(jī)上可用的 RAM 總量,并且隨著頁面緩存中可容納的 HNSW 數(shù)據(jù)比例的降低,性能將會(huì)下降。 如上一節(jié)所述,注重性能的用戶需要根據(jù)數(shù)據(jù)集的大小來調(diào)整 RAM 大小,以保持最佳性能。
無鎖搜索
就地更新數(shù)據(jù)結(jié)構(gòu)的系統(tǒng)通常需要加鎖,以保證并發(fā)索引和搜索下的線程安全。 Lucene 基于段的索引從不需要在搜索時(shí)鎖定,即使在并發(fā)索引的情況下也是如此。 相反,索引所組成的段集會(huì)定期以原子方式更新。
支持增量更改
可以隨時(shí)添加、刪除或更新新向量。 其他一些近似最近鄰搜索(approximate nearest neighbor search)算法需要提供整個(gè)向量數(shù)據(jù)集。 然后,一旦提供了所有向量,就執(zhí)行索引訓(xùn)練步驟。 對(duì)于這些其他算法,對(duì)向量數(shù)據(jù)集的任何重大更新都需要再次完成訓(xùn)練步驟,這可能會(huì)導(dǎo)致計(jì)算成本高昂。
與其他數(shù)據(jù)結(jié)構(gòu)的可見性一致性
在如此低的級(jí)別集成到 Lucene 的一個(gè)好處是,在查看索引的時(shí)間點(diǎn)視圖時(shí),我們可以與其他開箱即用的數(shù)據(jù)結(jié)構(gòu)保持一致。 如果你執(zhí)行文檔更新以更新其向量和某些其他關(guān)鍵字字段,則并發(fā)搜索保證會(huì)看到向量字段的舊值和關(guān)鍵字字段的舊值 -- 如果時(shí)間點(diǎn)視圖是在更新之前創(chuàng)建的,或者是向量場(chǎng)的新值和關(guān)鍵字字段的新值(如果時(shí)間點(diǎn)視圖是在更新之后創(chuàng)建的)。 與刪除類似,如果文檔被標(biāo)記為已刪除,那么包括向量存儲(chǔ)在內(nèi)的所有數(shù)據(jù)結(jié)構(gòu)都將忽略它,或者如果它們對(duì)刪除之前創(chuàng)建的時(shí)間點(diǎn)視圖進(jìn)行操作,則它們將看到它。
增量快照
向量是段的一部分,這一事實(shí)有助于快照通過利用兩個(gè)后續(xù)快照通常共享其大部分段(尤其是較大的段)的事實(shí)來保持增量。 使用就地修改的單個(gè) HNSW 圖不可能實(shí)現(xiàn)增量快照(incremental snapshot)。
過濾和混合支持
直接集成到 Lucene 中還可以與其他 Lucene 功能高效集成,例如使用任意 Lucene 過濾器預(yù)過濾向量搜索或?qū)碜韵蛄坎樵兊拿信c來自傳統(tǒng)全文查詢的命中組合起來。
通過擁有自己的與段關(guān)聯(lián)的 HNSW 圖,并且其中節(jié)點(diǎn)由文檔 ID 索引,Lucene 可以就如何最好地預(yù)過濾向量搜索做出有趣的決定:要么通過線性掃描與過濾器匹配的文檔(如果有選擇性),或者通過遍歷圖并僅考慮與過濾器匹配的節(jié)點(diǎn)作為 top-k 向量的候選節(jié)點(diǎn)。
與其他功能的兼容性
由于向量存儲(chǔ)與任何其他 Lucene 數(shù)據(jù)結(jié)構(gòu)一樣,因此許多功能與向量和向量搜索自動(dòng)兼容,包括:
- 聚合
- 文檔級(jí)安全性
- 字段級(jí)安全
- 索引排序
通過腳本訪問向量(例如,從 script_score 查詢或重新排序)
展望未來:索引和搜索分離
正如另一篇博客中所討論的,Elasticsearch 的未來版本將在不同的實(shí)例上運(yùn)行索引和搜索工作負(fù)載。 該實(shí)現(xiàn)本質(zhì)上看起來就像你不斷在索引節(jié)點(diǎn)上創(chuàng)建快照并在搜索節(jié)點(diǎn)上恢復(fù)它們??。 這將有助于防止向量索引的高成本影響搜索。 使用單個(gè)共享 HNSW 圖而不是多個(gè)段來實(shí)現(xiàn)索引和搜索的這種分離是不可能的,除非每次需要在新搜索中反映更改時(shí)通過網(wǎng)絡(luò)發(fā)送完整的 HNSW 圖。
結(jié)論
總的來說,Elasticsearch 提供了出色的向量搜索功能,并與其他 Elasticsearch 功能集成:
- 向量搜索可以通過任何支持的過濾器進(jìn)行預(yù)過濾,包括最復(fù)雜的過濾器。
- 向量命中可以與任意查詢的命中相結(jié)合。
- 向量搜索與聚合、文檔級(jí)安全性、字段級(jí)安全性、索引排序等兼容。
- 包含向量的索引仍然遵循與其他索引相同的語義,包括 _refresh、_flush 和 _snapshot API。 它們還將支持無狀態(tài) Elasticsearch 中索引和搜索的分離。
這是以一些索引時(shí)間和搜索時(shí)間開銷為代價(jià)完成的。 也就是說,向量搜索通常仍然以數(shù)十或數(shù)百毫秒的數(shù)量級(jí)運(yùn)行,并且比強(qiáng)力(brute force)精確搜索快得多。 更一般地說,與現(xiàn)有比較基準(zhǔn)*中的其他向量存儲(chǔ)相比,索引時(shí)間和搜索時(shí)間開銷似乎都是可控的(查找 “l(fā)uceneknn” 行)。 我們還相信,通過將向量搜索與其他功能相結(jié)合,可以釋放向量搜索的許多價(jià)值。 此外,我們建議你查看 KNN 搜索調(diào)整指南,其中列出了許多有助于減輕上述缺點(diǎn)的負(fù)面影響的措施。
我希望你喜歡這個(gè)博客。 如果你有疑問,請(qǐng)隨時(shí)通過討論與我們聯(lián)系。你可以隨意在現(xiàn)有部署中嘗試向量搜索,或者在 Elastic Cloud 上免費(fèi)試用 Elasticsearch Service(始終具有最新版本的 Elasticsearch)。
*在撰寫本文時(shí),這些基準(zhǔn)測(cè)試尚未利用向量化。 有關(guān)向量化的更多信息,請(qǐng)閱讀此博客。
本文中描述的任何特性或功能的發(fā)布和時(shí)間安排均由 Elastic 自行決定。 當(dāng)前不可用的任何特性或功能可能無法按時(shí)交付或根本無法交付。文章來源:http://www.zghlxwxcb.cn/news/detail-591394.html
原文:Vector search in Elasticsearch: The rationale behind the design | Elastic Blog文章來源地址http://www.zghlxwxcb.cn/news/detail-591394.html
到了這里,關(guān)于Elasticsearch 中的矢量搜索:設(shè)計(jì)背后的基本原理的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!