近日,OceanBase 开源社区及部分企业用户反馈,在最新发布的 4.3.x 版本中,向量查询与结构化条件混合执行场景存在严重性能退化。具体表现为:当 SQL 语句同时包含 ANN_SEARCH(近似最近邻搜索,Approximate Nearest Neighbor Search)与 WHERE 子句时,查询引擎会绕过向量索引的预过滤机制,转而执行全表扫描,导致查询响应时间呈数量级增长。这一发现迅速在数据库技术圈引发热议,开发者质疑该版本在向量索引优化上的重大回退。

问题复现:向量索引“形同虚设”

OceanBase 4.3.x 于今年 6 月正式发布,主打增强的向量检索能力,支持 HNSW(Hierarchical Navigable Small World)等主流索引结构,旨在为 AI、推荐系统等场景提供高性能混合查询。按照官方文档描述,向量索引应具备“预过滤”能力:即先通过 WHERE 子句缩小扫描范围(例如筛选出“status=active”的行),再在结果集内执行 ANN 搜索,从而大幅减少向量计算量。

然而,实际测试表明情况截然相反。一位用户在 GitHub issue 中附上执行计划截图:当 SQL 为 SELECT * FROM table WHERE status = 'active' ORDER BY ANN_SEARCH(embedding, ?) LIMIT 10 时,查询计划显示“TableScan: full table scan”,而非预期的“IndexScan: vector_index + filter”。在 100 万行数据的测试集上,带 WHERE 子句的查询耗时超过 2.3 秒,而移除 WHERE 子句后使用纯向量索引仅需 15 毫秒,性能差异达到 150 倍。

技术分析:优化器策略失误还是架构缺陷?

针对该问题,社区核心贡献者初步定位为查询优化器(Optimizer)对向量索引的支持不完善。在传统关系型数据库中,优化器通过统计信息和代价模型决定是否使用索引;但对于 ANN_SEARCH + WHERE 混合查询,优化器需判断两种过滤条件的执行顺序——是先按向量相似度排序再过滤,还是先过滤再排序。前者(后过滤)通常效率低下,因为要计算所有行的向量距离;后者(预过滤)理论上更优,但要求 WHERE 子句的选择率足够高,否则预过滤后可能找不到足够的结果。

OceanBase 4.3.x 的优化器默认选择了“全表扫描+后过滤”路径,根本原因可能是代价模型未能正确评估向量索引的访问成本。当存在 WHERE 子句时,优化器认为使用向量索引需要先在索引上执行 ANN 排序,再回表过滤,回表成本被高估;而全表扫描虽然代价高,但被误判为更优。另一种可能是,当前版本向量索引与行存/列存引擎的交互接口存在限制,导致预过滤无法实现——即向量索引无法接受来自存储层下推的 filter 条件。

影响与临时解决方案

这一 Bug 直接打击 OceanBase 在 AI 应用场景的竞争力。特别是结合大模型的企业级 RAG(检索增强生成)场景,通常需要“metadata 过滤 + 向量检索”的混合查询,例如“查找最近 7 天、类别为‘科技’的文档中语义最相似的 TOP 10”。若无法使用预过滤,系统性能将无法支撑实时在线服务。

截至发稿,OceanBase 官方尚未发布热修复补丁。社区中已有用户给出临时方案: 1. 拆分查询:先执行 WHERE 子句获取候选集 ID,再使用 IN 子句结合向量搜索(但 IN 列表过长时性能依然不佳)。 2. 降低 WHERE 子句选择率:利用强制提示(Hint)让优化器选择索引,例如 SELECT /*+ INDEX(table vector_index) */ ...,但该方法在某些版本中不生效。 3. 升级至 4.3.2 以上:据部分用户测试,4.3.2 分支已部分修复此问题,但仍有边缘 case 未解决。

数据库向量化的“中年危机”

OceanBase 并非首个在此类问题翻车的数据库。MongoDB、PostgreSQL(pgvector)早期版本也曾因优化器无法正确处理向量索引与结构化过滤的优先级而备受诟病。业界共识是,基于向量索引的混合查询优化是数据库向量化进程中的“皇冠明珠”,需要从存储层到优化器的全链路协同设计。

OceanBase 4.3.x 号称“原生分布式向量数据库”,本应在这一领域领先,但此次事件暴露了其查询优化器在对接 AHNSW 索引时的粗糙。若不能快速修复,可能会使用户对 OceanBase 的向量能力信任度下降,转投 Milvus、Qdrant 等专用向量数据库。

我们希望 OceanBase 团队能公开问题根因,并给出修复时间表。毕竟,在 AI 时代,每一毫秒的延迟都可能决定用户体验的成败。