找回密码
 立即注册
首页 业界区 科技 向量索引的混合查询方法,你选对了吗? ...

向量索引的混合查询方法,你选对了吗?

后彼 7 天前
作者:舸灏,OceanBase 高级技术专家
单一的向量近似最近邻查询,往往并不能满足实际业务的需求。用户通常都需要在向量检索中联合标量条件进行过滤,例如数据产生时间,知识库id等。还有一类需求是将全文或者多路向量索引查询的结果进行融合排序。本文解读OceanBase向量索引混合查询的原理和使用,以及产品规划。
一、标量与向量索引的混合查询

在正式介绍标量和向量索引的混合查询前,我们先举一个场景示例。例如:查询评分4.5以上,深圳南山区,评价最好的,价格实惠的店铺。这个查询既包含标量条件评分4.5以上,又包含地理区域限制,还需要按照语义“评价最好的,价格实惠”进行向量的近似最近邻查询。
数据库表结构的定义关系为:

  • id :店铺 ID
  • score :评分
  • position:店铺所在地理位置坐标
  • comment_vector:用户评价对应的向量在向量列上创建向量索引、Geometry 列上创建空间索引。
  1. create table t1(
  2. id int primary key,          
  3. score double,          
  4. position GEOMETRY NOT NULL SRID 0,          
  5. comment_vector vector(3),           
  6. spatial index idxg (position),         
  7. vector index idxv(comment_vector ) 
  8. with (distance=l2, type=hnsw, lib=vsag)
  9. );
复制代码
对应的查询 SQL如下:
1.png

在进行这类混合查询时,带上标量条件的方法和普通 SQL 没有任何区别,即直接将查询条件放到 where 后即可。但使用向量索引是有语法要求的,需要 order by,然后使用向量索引对应的 distance 表达式,并在其后加上 approximate关键词。如果不加上 approximate 关键词,则会进行全表扫描进行精确查询,而不会使用向量索引。
在上文 SQL 中我们加上了Hint(即 /*+index(t1 idxg) */)指定了向量检索时使用空间索引,此处就引出了第一种带标量过滤的查询方式,即 Pre-filtering(前过滤)。
在实际使用时,如果没有特殊要求,不需要指定hint,OceanBase会依据统计信息自动选择最合适的标量索引和查询方式。
查询方式1:Pre-filtering(前过滤)

Pre-filtering 是指先进行标量过滤的一种查询方式。
例如在上文的例子中,我们通过hint指定在进行向量检索前,先查询空间索引,获得所有满足st_intersects条件的数据。每一个向量都对应一个唯一ID作为其标识,这些唯一ID会被用来构造 bitmap。bitmap则会作为向量检索的上下文。在向量检索的过程中,每找到一个候选向量,就会校验其ID是否在 bitmap 中,如果不在,则说明其不满足标量过滤条件,需要继续查找下一个候选向量,直到找到limit K个结果。
2.png

Pre-filtering 的优点是,在 Filter rate 高时,会通过标量索引过滤掉大部分数据,减少后续的向量计算开销。然而,当标量过滤性不太好时候,Pre-filtering就不是最合适的过滤方式了。例如100万数据,过滤条件只能筛掉其中的50%,那么扫描索引表以及构造 bitmap 的代价仍然是非常大的。当然在一些特定场景,比如过滤条件是简单的range,会有一些优化。另外,如果过滤条件非常复杂,又没有标量索引可用的情况下,在做Pre-filtering进行标量过滤,就相当于对主表进行全表扫描,对每行数据还要执行过滤条件表达式计算,会导致性能不佳。
查询方式2:In-filtering with extra info(中过滤)

为了解决bitmap构造代价大的问题,OceanBase引入了In-filtering,即在向量索引过程中校验标量条件。这种方法需要将过滤字段加入到向量索引中,即作为每个向量的额外信息(extra info)。
3.png

In-filtering with extra info的优点是,不用先构造 bitmap,所以没有额外的 I/O开销,适用于 Filter rate 中高的场景。但这种方式会占用额外内存,使用成本较高,也要求过滤条件相对简单。
查询方式3:Iterative-Ann(迭代式)

为了应对前面两种方案不适用的情况,OceanBase 还实现了一种迭代式过滤的查询方法:Iterative-Ann,这种方法会使用多次迭代来完成查询,每一次迭代会返回向量距离最近的一批数据,然后再进行标量条件的校验,过滤掉不满足条件的数据。之后依据缺少的数据量,估算下一次迭代需要返回的向量近似最近邻结果的数量,调整参数再进行一轮查询。知道返回limit K条结果。 为此我们改造了传统的后过滤实现,在向量索引的查询中记录上下文,在前次迭代后,如果发现满足过滤个条件的数据量不足,就可以通过上下文继续查找,把下一批的数据迭代出来。
这种查询方式适用于 Filter rate 中低,过滤条件复杂的场景,在这类场景下,Iterative-Ann的计算量反而最少,性能会更好,也不会出现传统后过滤方法少数据的问题。
4.png

Iterative-Ann不适合 Filter rate 高的场景。在选择性非常好的情况下,比如100万数据中可能只有100条数据是满足过滤条件的,此时使用Iterative-Ann,由于向量索引只关注向量距离的相似性,可能需要迭代很多轮,甚至计算完大部分向量后才能找到满足的过滤条件。
如何选择合适的查询方法?

上述三种查询方法分别适合不同的使用场景,那么应该如何选择合适的过滤方法呢?
在 OceanBase 早期版本中,只能通过加 Hint进行方法选择。OceanBase V4.3.5_bp2 实现了比较完备的基于代价估计的路径选择。下图是 Oceanbase V4.3.5_bp2 和 Milvus 2.5.11 的 Vectordbbench 性能测试对比。测试在 Cohere 768D 100万数据集、top 100、recall 98%时,通过自动选择计划,在不同过滤条件下的性能。
5.png

6.png

7.png

上图中纵坐标分别是 QPS 或 RECALL (召回率),横坐标是过滤率,0表示过滤率为0%(无过滤条件)、99则表示过滤掉99%的数据。可以看到,不管是性能还是召回率,OceanBase 表现更优。
同样,对比其他向量数据库,OceanBase 的表现也毫不逊色。下图是我们在 AWS 基于 16C64G 的服务器,使用开源向量数据库评分工具Vectordbbench对几个主流的开源向量数据库进行性能测试的结果。测试数据集分别为:768维、100万的数据集;1536维、50万的数据集。
8.png

图中的横轴代表召回率,纵轴代表 QPS,可以看到,在同等召回率下,OceanBase 的表现仍然出色,已经达到了开源向量数据库的领先水平。

OceanBase 具备计划缓存的能力,可以减少SQL硬解析的开销,复用之前生成的执行计划,但如果过滤条件的参数发生比较大的改变,会导致命中的计划不一定合适。如下图所示,假设c1列有索引,在 c1
您需要登录后才可以回帖 登录 | 立即注册