矢量數據庫對比和選擇指南
矢量數據庫是為實現高維矢量數據的高效存儲、檢索和相似性搜索而設計的。使用一種稱為嵌入的過程,將向量數據表示為一個連續的、有意義的高維向量。
本文將研究存儲/檢索向量數據和執行相似性搜索的實用方法,在我們深入研究之前,首先先介紹矢量數據庫的兩個關鍵功能:
1、執行搜索的能力
當給定查詢向量時,向量數據庫可以根據指定的相似度度量(如余弦相似度或歐幾里得距離)檢索最相似的向量。這允許應用程序根據它們與給定查詢的相似性來查找相關項或數據點。
2、高性能
矢量數據庫通常使用索引技術,比如近似最近鄰(ANN)算法來加速搜索過程。這些索引方法旨在降低在高維向量空間中搜索的計算復雜度,而傳統的方法如空間分解由于高維而變得不切實際。
簡介
矢量數據庫領域現在正在急速的擴展,如何權衡選擇呢,這里我整理了5個主要的方向:
- 像Pinecone這樣的純矢量數據庫,比如Pinecone也是建立在下面的Faiss之上的
- 全文搜索數據庫,如ElasticSearch,以前是作為搜索引擎現在增加了矢量存儲和檢索的功能
- 矢量庫,如Faiss, Annoy和Hnswlib,還不能作為數據庫,只是矢量的處理
- 支持矢量的NoSQL數據庫,如MongoDB、Cosmos DB和Cassandra,都是老牌的數據存儲,但是加入了矢量的功能
- 支持矢量的SQL數據庫,如SingleStoreDB或PostgreSQL,與上面不同的是這些數據庫支持SQL語句
除了上面提到的五種主要方法外,還有如Vertex AI和Databricks,它們的功能超越了數據庫,我們不進行討論。
1、純矢量數據庫
純矢量數據庫是專門為存儲和檢索矢量而設計的。包括Chroma, LanceDB, Marqo, Milvus/ Zilliz, Pinecone, Qdrant, Vald, Vespa, Weaviate等。數據是基于對象或數據點的向量表示來組織和索引。這些向量可以是各種類型數據的數字表示,包括圖像、文本文檔、音頻文件或任何其他形式的結構化或非結構化數據。
優點
- 利用索引技術進行高效的相似度搜索
- 大型數據集和高查詢工作負載的可伸縮性
- 支持高維數據
- 支持基于HTTP和json的api
- 原生支持向量運算,包括加法,減法,點積,余弦相似度
缺點
純矢量數據庫:純矢量數據庫可以存儲矢量和一些元數據,但是其他就不行了。對于大多數用例,可能還需要包括諸如實體、屬性和層次結構(圖)、位置(地理空間)等描述的數據,這就要其他存儲的整合。
有限或沒有SQL支持:純矢量數據庫通常使用自己的查詢語言,這使得很難對矢量和相關信息運行傳統的分析,也很難將矢量和其他數據類型結合起來。
沒有完整的CRUD:純矢量數據庫并不是真正為創建、更新和刪除操作而設計的。所以必須首先對數據進行矢量化和索引,這些數據庫的重點是獲取向量數據,并基于向量相似度查詢最近鄰,而索引是很耗時的。索引矢量數據計算量大、成本高、耗時長。這使得基本上無法進行實時的操作。例如,Pinecone的IMI索引(反向多索引,人工神經網絡的一種變體)會產生存儲開銷,并且是計算密集型。它主要是為靜態或半靜態數據集設計的,如果經常添加、修改或刪除向量,基本上不太可能。而Milvus使用的索引被稱為產品量化和分層可導航小世界(HNSW),這是一種近似的技術,在搜索準確性和效率之間進行權衡。它的索引需要配置各種參數,使用不正確的參數選擇可能會影響搜索結果的質量或導致效率低下。
功能性不強:許多矢量數據庫在基本特性上嚴重落后,包括ACID事務、災難恢復、RBAC、元數據過濾、數據庫可管理性、可觀察性等。這可能會導致嚴重的業務問題,要解決這些問題,則需要我們自己來處理了這會導致開發量大增。
2、全文檢索數據庫
這類數據庫包括Elastic/Lucene、OpenSearch和Solr。
優點
- 高可伸縮性和性能,特別是對于非結構化文本文檔
- 豐富的文本檢索功能,如內置的外語支持,可定制的標記器,詞干器,停止列表和N-grams
- 大部分基于開源庫(Apache Lucene)
- 成熟的且有大型集成生態系統,包括矢量庫
缺點
- 沒有優化向量搜索或相似匹配
- 主要設計用于全文搜索,而不是語義搜索,因此基于它構建的應用程序將不具有檢索增強生成(RAG)和其他的完整上下文。為了實現語義搜索功能,這些數據庫需要使用其他工具以及大量自定義評分和相關模型進行增強。
- 其他數據格式(圖像、音頻、視頻)的有限應用
- 基本上不支持GPU
一般選擇這些庫的原因都是因為在以前項目上增加新的功能,并且數據量小,對主業務也不會產生多大影響時使用。如果需要重新構架大型項目,不建議使用。
3、開源矢量庫
對于許多開發者來說,Faiss、Annoy和Hnswlib等開源矢量庫是一個很好的起點。Faiss是一個用于密集向量相似性搜索和聚類的庫。Annoy (Approximate Nearest Neighbors Oh Yeah)是一個用于人工神經網絡搜索的輕量級庫。Hnswlib是一個實現HNSW ANN搜索算法的庫。
優點
- 快速近鄰搜索
- 為高維構建
- 支持面向人工神經網絡的索引結構,包括倒排文件,產品量化和隨機投影
- 支持推薦系統、圖像搜索和自然語言處理的用例
- SIMD(單指令,多數據)和GPU支持,加快向量相似度搜索操作
缺點
- 維護和集成麻煩
- 與精確方法相比,可能會犧牲搜索準確性
- 需要自己部署和維護:需要你構建和維護復雜的基礎設施,為應用程序需求提供足夠的CPU、GPU和內存資源。
- 對元數據過濾、SQL、CRUD操作、事務、高可用性、災難恢復以及備份和還原的支持有限或不支持
他們之所以稱為庫(或者包)而不是數據庫是因為它們只提供了很少的但是卻非常專業功能,如果你想入門學習或者做一個簡單的demo,它們都是很好開始,但不建議直接應用到生產中。
4、支持矢量的NoSQL數據庫
這些數據庫包括:NoSQL數據庫,如MongoDB, Cassandra/ DataStax Astra, CosmosDB和Rockset。還有像像Redis這樣的鍵值數據庫和其他特殊用途的數據庫,如Neo4j(圖數據庫)
幾乎所有這些NoSQL數據庫都是最近才添加矢量搜索擴展而具備矢量能力的,所以如果要是用的話一定要做好測試。
優點
對于特定的數據模型,NoSQL數據庫提供了高性能和可擴展性。Neo4j可以與llm一起用于社交網絡或知識圖譜。一個具有矢量能力的時間序列數據庫(如kdb)可能能夠將矢量數據與金融市場數據結合起來。
缺點
NoSQL數據庫的矢量功能是基本的/新生的/未經測試的。今年,許多NoSQL數據庫添加了向量支持。比如:
今年5月,Cassandra宣布了增加矢量搜索的計劃。
4月,Rockset宣布支持基本矢量搜索,
5月Azure Cosmos DB宣布支持MongoDB vCore的矢量搜索。
DataStax和MongoDB在本月(6月)宣布了矢量搜索功能(都是預覽版)!
NoSQL數據庫的矢量搜索性能可能差別很大,這取決于所支持的矢量函數、索引方法和硬件加速。而且NoSQL數據庫的查詢效率本來就不高,再加上矢量的功能,一定不會快。
我的觀點一直沒有變,那就是如果復雜數據一定要存到關系型數據庫中,像MongoDB這樣的當作輔助存儲是沒問題,但當作主要存儲和主要查詢那是所謂的自稱為“全棧”的前端干出來的事,因為什么都不懂,所以覺得什么都簡單。
5、支持矢量的SQL數據庫
這些庫與上面的類似,但是它們基本都是關系型數據庫并且支持sql查詢,例如SingleStoreDB, PostgreSQL, Clickhouse和Kinetica的pgvector/Supabase Vector(測試版)。
在一個已建立的數據庫中添加基本的矢量功能并不是一件難事。比如矢量數據庫Chroma就是來自ClickHouse
優點
包含矢量搜索功能,如點積,余弦相似度,歐幾里得距離和曼哈頓距離。
使用相似度分數找到k個最近鄰
多模型SQL數據庫提供混合查詢,并且可以將向量與其他數據結合起來以獲得更有意義的結果
大多數SQL數據庫都可以作為服務部署,可以在云上進行完全管理。
缺點
SQL數據庫是為結構化數據而設計的。而矢量是非結構化數據,如圖像、音頻和文本。雖然關系數據庫通常可以存儲文本和blob,但大多數數據庫不會將這些非結構化數據矢量化以用于機器學習。
大多數SQL數據庫(還)沒有針對向量搜索進行優化。關系數據庫的索引和查詢機制主要是為結構化數據設計的,而不是為高維矢量數據設計的。雖然用于向量數據處理的SQL數據庫的性能可能不是特別好,但支持向量的SQL數據庫可能會添加擴展或新功能來支持向量搜索。
傳統的SQL數據庫不能向外擴展,它們的性能會隨著數據的增長而下降。使用SQL數據庫處理高維向量的大型數據集可能需要進行額外的優化,比如對數據進行分區或使用專門的索引技術來保持高效的查詢性能。
總結
所以,那么如何選擇呢?
1、如果入門或者demo的話可以直接使用開源的矢量庫,比如Faiss可以支持本地的億級數據,但是無法提供對外服務。
2、對于產品,如果要開發新的功能并且上線,那就要將矢量存儲和現有的存儲分開,專業的人做專業的事,可選擇純矢量數據庫或開源矢量庫自行開發(如果功能簡單的話),保證系統的穩定性。
3、如果非要在現有系統上使用矢量功能,比如Elastic、MongoDB 上存儲和檢索大量的矢量數據,那么一定要做好測試,并且自求多福吧,沒準你遇到的問題不僅chatgpt不知道,stackoverflow上也沒有。
4、現在矢量存儲還是再發展階段,所以有些功能還不完善,所以盡量使用成熟版本,對于生產環境不要冒險嘗鮮。
最后說說架構的建議:
微服務架構是一種軟件架構風格,其中應用程序被拆分為一組小型、獨立的服務,每個服務都專注于提供特定的業務功能,每個微服務都應該專注于解決一個具體的業務問題或提供一項特定的功能。這種精細化的劃分使得每個微服務可以根據需要進行獨立的擴展、部署和維護。
矢量搜索也不例外應該獨立成單獨的服務,服務都獨立了存儲不是也應該獨立嗎。
當然如果非要把矢量存儲和業務數據放在一起也可以,我沒有任何意見,反正出問題又不是我來解決,我就看個熱鬧就行了??