pgvector 索引的混合查询

对于pgvector0.6.0的向量相关查询,稍不注意,优化器就会不使用向量索引,例如:

这个查询,先查询出 id 在 10 和 100 之间的记录,然后对这些记录,按照与向量 ‘[3, 1, 2]’ 的距离排序。

从执行计划看,是先用 id 上的索引(主键),选出 id 在 10 到 100 之间的记录,然后对这些记录计算向量距离并排序,查找最近向量的方法是排序,是一种暴力计算的方法。

可以看到,这里并没有使用pgvector所特有的向量索引。

当 where 的条件查询出的记录多到一定程度时(估计selectivity不同了),优化器便会选择另一个执行计划,如下图,会先按照向量索引查询出最近的若干向量,然后再对这些最邻近向量所在行,按其它字段进行条件过滤,这种情况使用了向量索引。

同样的查询类型,查询的范围不同,优化器会根据cost给出不同的执行计划。

在上面的查询中,返回的最邻近向量数只有一个,没有达到5个的需求,在不改变执行计划的前提下,可以增大where的查询范围,即按照向量索引查询后,过滤条件放宽一些,或许可以得到更多结果,然后再用limit选取头几条。

上面的查询模式,增大limit的值也会带来执行计划的改变,例如:

这就需要,每次对SQL做修改时,查看执行计划,有时数据库的优化,和业务内容强相关。

### pgvector 结合 BM25 实现检索的技术解析 pgvector 是一个 PostgreSQL 扩展,用于支持向量存储和相似性搜索。BM25(Best Matching 25)是一种基于概率的排名函数,广泛应用于信息检索领域[^1]。将 pgvector 和 BM25 结合使用,可以通过以下方式实现高效的文本检索: #### 1. 数据准备与索引构建 在使用 pgvector 和 BM25 之前,需要对数据进行预处理,并构建相应的索引。以下是关键步骤: - **向量化文本**:将文本数据转换为向量表示。可以使用预训练的语言模型(如 Sentence-BERT 或 OpenAI 的嵌入模型)生成高质量的文本向量。 - **创建 pgvector 表**:在 PostgreSQL 中创建一个包含向量列的表。 - **BM25 索引**:对于 BM25 检索,通常需要一个倒排索引来加速查询。可以使用 PostgreSQL 的GIN或GiST索引支持 BM25 排序。 ```sql CREATE EXTENSION vector; CREATE TABLE documents ( id SERIAL PRIMARY KEY, content TEXT, embedding VECTOR(1536) -- 假设向量维度为 1536 ); CREATE INDEX ON documents USING GIN (embedding); -- 向量索引 ``` #### 2. BM25 排序逻辑 BM25 的核心在于其评分公式,该公式考虑了词频、逆文档频率以及文档长度等因素。虽然 PostgreSQL 本身不直接支持 BM25,但可以通过扩展或自定义函数来实现。例如,VectorChord-bm25 提供了原生的 BM25 支持,可以直接集成到 PostgreSQL 中。 ```sql -- 示例:使用 BM25 对查询结果排序 SELECT id, content, bm25_score(query, content) AS score FROM documents WHERE content @@ query ORDER BY score DESC; ``` #### 3. pgvector 与 BM25 的结合 pgvector 主要用于向量相似性搜索,而 BM25 则侧重于基于文本匹配的排名。为了结合两者,可以采取以下策略: - **混合检索**:先通过 pgvector 进行向量相似性检索,筛选出候选集;然后对候选集应用 BM25 排序,以进一步优化结果。 - **联合索引**:在同一个查询中同时利用 pgvector 和 BM25 的优势。例如,可以先通过向量距离过滤出前 N 个结果,再对这些结果计算 BM25 分数。 ```sql -- 示例:结合 pgvector 和 BM25 WITH candidates AS ( SELECT id, content, 1 - (embedding <=> query_embedding) AS similarity FROM documents ORDER BY similarity DESC LIMIT 100 ) SELECT c.id, c.content, bm25_score(query, c.content) AS bm25_score FROM candidates c ORDER BY bm25_score DESC; ``` #### 4. 技术选型与实施建议 根据引用内容[^3],如果组织没有技术栈限制,可以选择专门的向量数据库(如 Milvus 或 Qdrant)。但如果已有 PostgreSQL 技术栈,则推荐使用 pgvector 集成 BM25 方法。此外,还可以参考多模态检索的技术对比分析[^4],选择最适合具体场景的方案。 --- ### 示例代码 以下是一个完整的示例,展示如何结合 pgvector 和 BM25 实现检索: ```python import psycopg2 from sentence_transformers import SentenceTransformer # 加载语言模型 model = SentenceTransformer('all-MiniLM-L6-v2') # 连接 PostgreSQL 数据库 conn = psycopg2.connect("dbname=test user=postgres password=secret") cur = conn.cursor() # 插入示例数据 def insert_document(content): embedding = model.encode(content).tolist() cur.execute("INSERT INTO documents (content, embedding) VALUES (%s, %s)", (content, embedding)) conn.commit() # 查询最相关的文档 def search_documents(query, top_k=5): query_embedding = model.encode(query).tolist() cur.execute(""" WITH candidates AS ( SELECT id, content, 1 - (embedding <=> %s) AS similarity FROM documents ORDER BY similarity DESC LIMIT 100 ) SELECT c.id, c.content, bm25_score(%s, c.content) AS bm25_score FROM candidates c ORDER BY bm25_score DESC LIMIT %s; """, (query_embedding, query, top_k)) return cur.fetchall() # 示例调用 insert_document("This is a sample document.") results = search_documents("sample text", top_k=3) for result in results: print(result) ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值