ES v.s Milvus v.s PG_es和pg是什么向量数据库
需求
对比三种常见系统在向量搜索和全文搜索方面的性能与功能差异:ES(内置 Lucene、提供 k-NN 插件)、Milvus(专用向量数据库)和PostgreSQL(pgvector扩展)。它们各自优势不同:Milvus 设计用于亿级向量数据的高效检索;ES 是分布式全文搜索引擎,也可通过 k-NN 插件进行高维向量近似检索;pgvector 则将向量嵌入与关系数据共存,适用于混合查询场景。
测试环境与数据集
- 数据库版本:ES 8.17.4(docker部署,单节点)、Milvus 2.5.10(docker compose部署,standalone模式)、PostgreSQL 17.4-1+pgvector 0.7.0(Windows部署)。
- 向量数据集:统一采用 768 维嵌入(常见 BERT/CLIP 维度)。例如,MSMARCO/BERT模型输出768维句向量,LAION图像嵌入也为 768 维。
- 索引配置:为消除规模差异,三者均在相同硬件条件下建立索引:ES mapping 定义 dense_vector 字段(dims=768),索引类型设为 hnsw(M=32, ef_construction=100);Milvus 创建 HNSW 或 IVF_FLAT 索引(如 {“index_type”:“IVF_FLAT”,“params”:{“nlist”:1024}});PostgreSQL 使用 pgvector 插件,创建 HNSW 或 IVFFlat 索引:
CREATE INDEX ON items USING hnsw (embedding vector_l2_ops);CREATE INDEX ON items USING ivfflat (embedding vector_l2_ops) WITH (lists = 1024);
其中,HNSW 索引可获得较高召回但构建缓慢、占用内存多,IVFFlat 提升查询速度但略损精度。
- 基准工具:可使用开源工具 VectorDBBench、ANN-Benchmarks或自定义测试脚本。测试指标包括 Top-K 命中率(Recall)、吞吐量(QPS)与延迟等。
Python 查询示例:
# Milvus 查询示例from pymilvus import Collection, connectionsconnections.connect(alias=\"default\", host=\"127.0.0.1\", port=\"19530\")collection = Collection(\"my_collection\")query_vec = [0.1] * 768results = collection.search([query_vec], \"vector_field\", param={\"metric_type\": \"L2\", \"params\": {\"nprobe\": 10}}, limit=5)print([hit.id for hit in results[0]])# PostgreSQL (pgvector) 查询示例import psycopg2conn = psycopg2.connect(\"dbname=test\")cursor = conn.cursor()cursor.execute(\"SELECT id FROM items ORDER BY embedding %s LIMIT 5;\", (query_vec,))print([row[0] for row in cursor.fetchall()])# ES 查询示例from elasticsearch import Elasticsearches = Elasticsearch()body = {\"size\":5, \"query\": {\"knn\": {\"vector_field\": {\"vector\": query_vec, \"k\":5, \"num_candidates\":100}}}}res = es.search(index=\"my_index\", body=body)print([hit[\"_id\"] for hit in res[\"hits\"][\"hits\"]])
向量检索
ES
ES 8.0及以上版本新增向量近邻检索k-nearest neighbor(kNN)search功能,示例:
{ \"settings\": { \"number_of_shards\": 6, \"number_of_replicas\": 1 }, \"mappings\": { \"properties\": { \"id\": { \"type\": \"keyword\" }, \"vector\": { \"type\": \"dense_vector\", \"dims\": 960, // 最高支持2048维度 \"index\": true, \"similarity\": \"cosine\", // 支持 cosine, dot_product, l2_norm \"element_type\": \"float\", // 支持 float, byte \"index_options\": { // hnsw 高级参数配置 \"type\": \"hnsw\", \"m\": 16, \"ef_construction\": 100 } } } }}
向量检索支持的索引类型:
- dense_vector:暴力搜索,存储原始向量,查询时计算目标向量与所有向量的距离(如余弦相似度、欧氏距离);无需额外索引结构,数据写入简单。查询性能随数据量线性下降,适合小规模数据(如数万条)
- HNSW:Hierarchical Navigable Small World,基于图的近似最近邻(ANN)算法,通过多层图结构加速搜索;查询速度快(对数时间复杂度),适合大规模数据;需要额外存储索引,写入速度较慢。
- IVF:Inverted File System,通过聚类将向量分到多个桶(Voronoi 单元),搜索时仅计算目标桶内的向量;适合超大规模数据(亿级以上);需要训练聚类中心,写入延迟较高。
参考
- 腾讯云 ES 8 向量化语义混合检索测试指南
- Elasticsearch 8.8 原生向量检索性能测试
- Elasticsearch向量检索的性能测试和比较
- 使用Elasticsearch的向量近邻检索(kNN)功能
- 知识库文档检索,ES精确检索与Faiss向量检索测试
- https://discuss.elastic.co/t/elasticseach-default-similairty-algorithm-and-bm25-giving-same-results/152470
Milvus
Milvus的强项。
索引类型:
- HNSW
- IVF
参考:
- https://milvus.io/docs/v2.0.x/build_index.md
PG
插件:pg_vector和pg_embdding,基于Faiss(向量数据库)的IVF Flat索引。
参考
- https://zhuanlan.zhihu.com/p/4859988545
全文检索
ES
ES的强项,基于倒排索引。
中文全文检索
需要引入中文分词器:
- IK:默认,两种颗粒度的拆分:
ik_smart
:会做最粗粒度的拆分;ik_max_word
:会将文本做最细粒度的拆分;
- smartCN:
- HanLP:
- jieba:
参考
- https://zhuanlan.zhihu.com/p/13723417907
Milvus
检索+排序;使用 BM25 算法进行相关性评分;
适用于全文检索的 Collection,其 Schema 必须包括三个必要字段:
- 唯一标识 Collection 中每个实体的主字段。
- 一个VARCHAR 字段,用于存储原始文本文档,其enable_analyzer 属性设置为True 。这允许 Milvus 将文本标记为特定术语,以便进行函数处理。
- 一个SPARSE_FLOAT_VECTOR 字段,预留用于存储稀疏嵌入,Milvus 将为VARCHAR 字段自动生成稀疏嵌入。
Milvus 2.5 集成高性能搜索引擎库 Tantivy,并内置 Sparse-BM25 算法,首次实现原生全文检索功能:
- 内置基于 tantivy 构建的分词器:无需额外预处理,通过内置分词器(Analyzer)与稀疏向量提取能力,Milvus 可直接接受文本输入,自动完成分词、停用词过滤与稀疏向量提取,无需依赖外部模型(如BGE-M3等)。
- 实时 BM25 统计:数据插入时动态更新词频(TF)与逆文档频率(IDF),确保搜索结果的实时性与准确性。
- 混合搜索性能增强:基于近似最近邻(Approximate Nearest Neighbor,ANN)算法的稀疏向量检索,性能远超传统关键词系统,支持亿级数据毫秒级响应,同时兼容与稠密向量的混合查询。
对比:BM25和Sparse-BM25
BM25采用Sparse Vector,优势,包括但不限于:
- 对长上下文Query可构建图索引来加速搜索;
- 基于量化和WAND的
drop_ratio
等技术手段做近似匹配来提升性能; - 统一语义检索和全文检索的表达方式,使用体验以及技术优化。
rerank使用 RRF(Reciprocal Rank Fusion) 算法:融合向量和文本检索结果,重新优化排序和权重分配,提升数据召回率和精确性。
参考:
- https://milvus.io/docs/zh/full_text_search_with_milvus.md
- https://milvus.io/docs/zh/full-text-search.md
- https://zilliz.com.cn/blog/semantic-search-vs-full-text-search-which-one-should-i-choose-with-milvus-2-5
- https://xie.infoq.cn/article/2d6c98ec75578495365680363
- https://help.aliyun.com/zh/milvus/use-cases/full-text-retrieval-by-milvus-bm25-algorithm-and-application-of-hybrid-retrieval-to-rag-system
中文全文检索
{\"type\": \"english\"}
:standard 分词器,
{\"type\": \"chinese\"}
:针对中文文本,基于上下文分词并过滤非汉字字符,使用 jieba;Filter采用cnalphanumonly(仅保留汉字和字母数字)。
TODO:
- 读、写性能(向量检索、全文检索)
- 高可用部署的硬件需求
PG
全文检索=匹配+亲和(rank)。
可实现小规模数据量的全文检索功能。
优点:轻量级
索引类型:
- GIN:通用倒排索引,Generalized Inverted Index,官方推荐
- GiST:通用搜索树,Generalized Search Trees
- RUM:https://github.com/postgrespro/rum
基本Query:
- Simple Query:
@@
SELECT * FROM documents WHERE to_tsvector(\'english\', content) @@ to_tsquery(\'search_term\');
- Phrase Search:
& for AND, | for OR, and ! for NOT
SELECT * FROM documents WHERE to_tsvector(\'english\', content) @@ to_tsquery(\'word1 & word2\');
高级Query:
- Ranked Search:
ts_rank
SELECT *, ts_rank(to_tsvector(\'english\', content), to_tsquery(\'search_term\')) AS rankFROM documentsWHERE to_tsvector(\'english\', content) @@ to_tsquery(\'search_term\')ORDER BY rank DESC;
- Proximity Search:
SELECT * FROM documents WHERE to_tsvector(\'english\', content) @@ to_tsquery(\'word1 word2\');
- Weighted Search:
setweight
SELECT *, ts_rank_cd(setweight(to_tsvector(\'a\', title), \'A\') || setweight(to_tsvector(\'b\', content), \'B\'), to_tsquery(\'search_term\')) AS rankFROM documentsWHERE to_tsvector(\'english\', content) @@ to_tsquery(\'search_term\')ORDER BY rank DESC;
中文全文检索
安装插件:
- zhparser:https://github.com/amutu/zhparser,推荐,阿里云的RDS默认包含。
- jieba:https://github.com/jaiminpan/pg_jieba、
- PGroonga:https://github.com/pgroonga/pgroonga,star, https://blog.csdn.net/weixin_44957042/article/details/138917123
参考
- 全文检索:http://www.postgres.cn/docs/9.3/textsearch.html
- 用PostgreSQL 做实时高效 搜索引擎 - 全文检索、模糊查询、正则查询、相似查询、ADHOC查询
- https://help.aliyun.com/zh/analyticdb/analyticdb-for-postgresql/user-guide/
- https://www.cnblogs.com/zhenbianshu/p/7795247.html
- https://cloud.tencent.com/developer/article/1430039
对比
主要差异:
对比项解读:
- 向量检索精度:在召回率(Recall)方面,所有系统的精确搜索(如Milvus的FLAT、PostgreSQL无索引扫描)均可达到 100%。使用近似索引时,精度取决于参数:Milvus的HNSW/IVF可通过增大
nprobe
或ef
值获得高召回;ES的HNSW需要设置较高ef
才能接近真实最近邻。实践中,如果要求召回≥98%,Milvus和ES都能达到,而pgvector的近似索引在高维场景中通常需要较多参数调优。 - 检索速度(QPS/延迟):通用数据库(PostgreSQL、MongoDB、OpenSearch)在高召回向量搜索场景下吞吐量和延迟都明显落后于专用向量库。在相同召回条件下,其查询吞吐量比pgvector提供的PostgreSQL快近10倍。Milvus和其他专业库通常在大规模数据上能提供更高QPS。例如,Milvus官方示例在百万级数据上进行HNSW比较,展示出较高吞吐(云端部署时需注意资源配置)。ES查询速度介于两者之间:其优化良好的Lucene索引在中等规模下表现良好,但向量检索耗费内存和CPU,相比纯向量库略显逊色。综合而言,在大数据量和高吞吐场景下,Milvus通常表现最好,其次是ES,pgvector适合数据量中等、延迟要求不极端的场景。
- 全文检索:
- 内存与存储占用:向量检索一般需要大量内存。ES要求所有向量索引数据在节点的页缓存中才能高效查询,量化(Int8)可降低索引大小。Milvus的HNSW/FLAT索引需要在RAM中存储图结构或完整向量;使用IVF+PQ/SQ8等压缩索引可显著减少内存使用。PostgreSQL将向量直接存储在表中,HNSW索引占用额外内存较大;IVF索引还需要保存聚类单元的中心点数据。一般来说,专业向量库在内存管理上更灵活,但部署时需注意节点规格。
- 系统扩展与运维:ES原生支持集群分片和副本,运维工具成熟(如ES Operator、Elastic Cloud)。Milvus也提供完整的分布式架构,可水平扩展;其自动重平衡功能在节点增减时保证负载均匀。PostgreSQL本身单节点性能优秀,但需额外方案(读写分离、Citus等)才能实现横向扩展。综合运维复杂度:Elastic、Milvus都需要管理多服务节点,Milvus配置稍复杂;PG相对简单但可扩展性较差。
结论: 综合来看,Milvus 在大规模向量检索场景中性能最佳,支持丰富索引类型和自动扩展,适合对吞吐和低延迟要求高的应用;ES 拥有成熟的全文搜索能力,适合混合结构化、文本和向量的检索(内置 BM25、倒排索引);PostgreSQL + pgvector 则为传统关系库用户提供便利,适合数据量适中、方便集成的场景,但其向量查询性能明显弱于专用向量库(多项基准显示 QPS 低于 Milvus)。选择哪种方案取决于具体需求:如果需要同时做关键词和语义搜索,ES 可快速构建混合应用;如果追求最大化向量检索性能与扩展性,Milvus 是更优选;如果已有 PostgreSQL 生态且对吞吐要求不极端,则 pgvector 提供足够的功能。
附录
Tantivy
Rust语言编写,Lucene平替,开源高性能搜索引擎库,可被集成到各种数据库中,包括:
- Milvus
- PG
- MyScaleDB:针对向量搜索进行优化的ClickHouse开源分支
https://docs.rs/tantivy/latest/tantivy/
https://tantivy-search.github.io/bench/
https://github.com/dromara/MilvusPlus/blob/main/Tantivy文本匹配.md
https://www.yicaiai.com/news/article/670738554ddd79f11a6e2770
https://www.53ai.com/news/hangyeyingyong/2024053165894.html
关键功能
- BM25相关性评分:Elasticsearch、Lucene和Solr都将BM25用作默认相关性排名算法。BM25分数评估文本搜索的准确性和相关性,增强用户搜索体验。
- 可配置标记器:此功能支持各种语言标记器,满足用户多样化的标记化需求。
- 自然语言查询:用户可以使用AND、OR和IN等关键字灵活地组合文本查询,降低SQL语句编写的复杂性。
ParadeDB
GitHub。
ParadeDB is a full text search engine built for Postgres. Powered by an extension called pg_search, ParadeDB embeds Tantivy, a Rust-based Lucene alternative, inside Postgres.
基于pg_search+ Tantivy。
参考
- https://iniakunhuda.medium.com/postgresql-full-text-search-a-powerful-alternative-to-elasticsearch-for-small-to-medium-d9524e001fe0
- https://risingwave.com/blog/implementing-high-performance-full-text-search-in-postgres/
检索
包括:
- Semantic Search:语义搜索
- Keyword Search:关键词搜索
- Full Text Search:FTS,全文搜索
- Vector Search:向量搜索
- Exact Match Search:精确搜索
- Fuzzy Search:模糊搜索
LIKE
)tsvector
fuzzy
查询、Redis的模糊键匹配其他:
- Hybrid Search:混合搜索,结合关键词搜索和向量搜索,增强搜索结果的相关性;
- Geospatial Search:地理位置搜索,基于经纬度或地理范围,如:ES 的geo_distance、PostGIS;
- Temporal Search:时间范围搜索,按时间戳过滤;
- Multimodal Search:多模态搜索,跨模态检索(如用文本搜索图片,或用图片搜索文本),如CLIP等跨模态模型生成的向量。
Dense Vector v.s Sparse Vector
稠密向量和稀疏向量,向量表示的两种主要形式。
其他
https://db-engines.com/en/ranking/vector+dbms