基于湖库一体架构,统一管理结构化、半结构化与非结构化等多模态数据,一个系统承载事务处理、实时分析与 AI 工作负载。
创建向量索引
更新时间:2026-08-18 16:46:30
本文介绍了 OceanBase 如何创建、搜索、维护和删除向量索引。
索引类型
OceanBase 支持的向量索引类型及其具体说明如下:
| 索引类型 | 描述 | 适用场景 |
|---|---|---|
| HNSW | 索引列最大维度为 4096。HNSW 索引是内存索引,需要完整载入内存。 | |
| HNSW_SQ | HNSW_SQ 索引提供了和 HNSW 索引相近的构建速度,搜索性能,召回率,但总的内存使用降低到原本的 1/2~1/3。 | 对性能和召回率有较高要求的场景。 |
| HNSW_BQ | HNSW_BQ 索引的召回率略低于 HNSW 索引,但显著减少了内存占用。BQ 量化压缩算法(Rabitq)能将向量压缩至原大小的 1/32,随着向量维度增加,HNSW_BQ 索引的内存优化效果更明显。 | |
| IVF(实验特性) | 基于数据库表实现的 IVF 索引,可不占用常驻内存。 | 对性能要求不高,但数据量较大,成本敏感的场景。 |
| IVF_PQ(实验特性) | 基于数据库表实现的 IVF_PQ 索引,可不占用常驻内存。在 IVF 基础上应用了 PQ 量化技术,索引的召回率略低于 IVF 索引,性能高于 IVF 索引,同时 PQ 量化压缩算法普遍场景下能将向量压缩至原大小的 1/16 ~ 1/32。 | 对性能要求不高,但数据量较大,成本敏感的场景。 |
一些其他说明:
- 稠密向量索引支持 L2、内积(IP)、余弦距离作为索引距离算法。
- 支持带有过滤条件的向量查询。过滤条件可以是标量类型的条件,可以是空间关系,如 ST_Intersects 等。暂不支持多值索引/全文索引/全局索引作为预过滤器。
- 支持同表创建向量索引和全文索引。
- 向量索引对 Offline DDL 的支持情况请见Offline DDL。
- 向量索引搜索支持调用部分距离函数,具体请参见 使用 SQL 函数。
准备工作
使用 HNSW/HNSW_SQ/HNSW_BQ 向量索引前,需要通过设置 ob_vector_memory_limit_percentage 开启向量功能。IVF 索引不需要常驻内存,所以无需手动设置此参数来开启向量功能。
ALTER SYSTEM SET ob_vector_memory_limit_percentage = 30;
创建语法及说明
OceanBase 向量索引的创建支持在建表时创建和后建两种方式。创建时需要注意:
- 向量索引创建后,不支持任何参数的修改。
- 创建向量索引必须带有
VECTOR关键字。 - 后建索引的参数和说明与建表时创建索引一致。
- 如果数据量较大,建议先写完数据,再创建索引,以获得最佳搜索性能。
- HNSW_SQ/IVF/IVF_PQ 索引均建议在写入数据后再创建索引,并在写入较多增量数据后进行索引重建。每个索引具体的创建说明见下文具体示例。
建表时创建索引语法:
CREATE TABLE table_name (
column_name1 data_type1,
column_name2 data_type2,
...,
VECTOR INDEX index_name (column_name) WITH (param1=value1, param2=value2, ...)
);
后建索引语法:
-- 后建索引支持设置并行度,以提升索引构建性能,并行度最大设置不超过 CPU 核数 * 2
CREATE [/*+ paralell $value*/] VECTOR INDEX index_name ON table_name(column_name) WITH (param1=value1, param2=value2, ...);
param 参数说明:
| 参数 | 默认值 | 取值范围 | 是否必填 | 说明 | 备注 |
|---|---|---|---|---|---|
| distance | l2/inner_product/cosine | 是 | 指定向量距离算法类型。 | l2 表示欧氏距离,inner_product 表示内积距离,cosine 表示余弦距离。 | |
| type | 目前支持 hnsw / hnsw_sq/ hnsw_bq。 |
是 | 指定索引类型。 | ||
| lib | vsag | vsag | 否 | 指定向量索引库类型。 | 目前仅支持 VSAG 向量库。 |
| m | 16 | [5,128] | 否 | 每个节点的最大邻居数。 | 值越大,索引构建越慢,搜索性能越好。 |
| ef_construction | 200 | [5,1000] | 否 | 构建索引时的候选集大小。 | 值越大,索引构建越慢,索引质量越好。ef_construction 必须大于 m。 |
| ef_search | 64 | [1,1000] | 否 | 搜索时的候选集大小。 | 值越大,搜索越慢,召回率越高。 |
| extra_info_max_size | 0 | [0,16384] | 否 | 设置每个主键信息的最大大小(单位:字节)。将表的主键存储在索引中,以加快搜索速度。 | 0:不存储主键信息。1:强制存储主键信息,忽略大小限制。此时表的主键类型(详见下文)必须为支持的类型。大于 1:设置主键信息的最大大小(单位:字节)。此时,需要满足以下条件:
|
extra_info_max_size 支持的主键类型包括:
主键信息的大小计算方法:
SET @table_name = 'test'; -- 替换为要查询的 table_name
SELECT
CASE
WHEN COUNT(*) <> COUNT(result_value) THEN 'not support'
ELSE COALESCE(SUM(result_value), 'not support')
END AS extra_info_size
FROM (
SELECT
CASE
WHEN vdt.data_type_class IN (1, 2, 3, 4, 6, 8, 9, 14, 27, 28) THEN 8 -- 为数值类型 extra_info_size += 8
WHEN oc.data_type = 22 THEN oc.data_length -- 为 varchar 类型 extra_info_size += data_length
ELSE NULL -- 其他类型不支持
END AS result_value
FROM
oceanbase.__all_column oc
JOIN
oceanbase.__all_virtual_data_type vdt
ON
oc.data_type = vdt.data_type
WHERE
oc.rowkey_position != 0
AND oc.table_id = (SELECT table_id FROM oceanbase.__all_table WHERE table_name = @table_name)
) AS result_table;
-- 计算结果为 8 byte
建表时创建索引语法:
CREATE TABLE table_name (
column_name1 data_type1,
column_name2 data_type2,
...,
VECTOR INDEX index_name (column_name) WITH (param1=value1, param2=value2, ...)
);
后建索引语法:
-- 后建索引支持设置并行度,以提升索引构建性能,并行度最大设置不超过 CPU 核数 * 2
CREATE [/*+ paralell $value*/] VECTOR INDEX index_name ON table_name(column_name) WITH (param1=value1, param2=value2, ...);
param 参数说明:
| 参数 | 默认值 | 取值范围 | 是否必填 | 说明 | 备注 |
|---|---|---|---|---|---|
| distance | l2/inner_product/cosine | 是 | 指定向量距离算法类型。 | l2 表示欧氏距离,inner_product 表示内积距离,cosine 表示余弦距离。 | |
| type | ivf_flat/ivf_pq | 是 | 指定 IVF 索引类型。 | ||
| lib | ob | ob | 否 | 指定向量索引库类型。 | |
| nlist | 128 | [1,65536] | 否 | 聚类中心的个数。 | |
| sample_per_nlist | 256 | [1,int64_max] | 是 | 每个聚类中心的取样的数据量,后建索引中使用。 |
搜索语法及说明
向量索引搜索是一种近似最近邻搜索,并不保证 100% 的结果正确。相应的向量搜索准确率的指标是召回率,例如在查 10 个最近邻时,如果可以稳定返回 9 个正确的结果,那么召回率就是 90%。召回率说明如下:
- 召回率受构建参数和搜索参数的影响。
- 索引搜索参数在建索引时指定,之后不可修改。但可通过 session 变量设置:HNSW/HNSW_SQ 索引通过
ob_hnsw_ef_search设置,IVF 索引通过ob_ivf_nprobes设置。如果设置了 session 变量,会优先使用它的值。具体设置方式请参见 ob_hnsw_ef_search 和 ob_ivf_nprobes。
稠密向量索引搜索语法具体如下:
SELECT ... FROM $table_name ORDER BY $distance_function($column_name, $vector_expr) [APPROXIMATE|APPROX] LIMIT $num (OFFSET $num);
搜索使用说明如下:
搜索语法要求:
- 必须指定
APPROXIMATE/APPROX关键字才会使用向量索引。 - 必须包含
ORDER BY和LIMIT子句。 ORDER BY只支持单个向量条件。LIMIT + OFFSET的取值范围为(0, 16384]。
- 必须指定
距离函数使用规则:
- 指定
APPROXIMATE/APPROX,调用当前版本支持的距离函数,且与向量索引算法匹配,搜索会使用向量索引。 - 指定
APPROXIMATE/APPROX,距离函数与向量索引算法不匹配,搜索不会使用向量索引,但也不会报错。 - 指定
APPROXIMATE/APPROX,如果距离函数为当前版本不支持的距离函数,搜索不会使用向量索引,且会报错。 - 未指定
APPROXIMATE/APPROX,调用当前版本支持的距离函数,搜索不会使用向量索引,但也不会报错。
- 指定
其他说明:
WHERE条件会作为向量索引搜索后的过滤条件。- 不指定
LIMIT子句会报错。
索引创建、搜索及删除示例
建表时创建索引
稠密向量索引示例
HNSW 索引示例
注意
创建 HNSW 索引时,索引名长度暂不支持超过 25 个字符,否则可能因为索引辅助表名长度超过 index_name 限制导致异常。未来版本会支持更长的索引名。
创建测试表。
CREATE TABLE t1(c1 INT, c0 INT, c2 VECTOR(10), c3 VECTOR(10), PRIMARY KEY(c1), VECTOR INDEX idx1(c2) WITH (distance=l2, type=hnsw, lib=vsag), VECTOR INDEX idx2(c3) WITH (distance=l2, type=hnsw, lib=vsag));
写入测试数据。
INSERT INTO t1 VALUES(1, 1,'[0.203846,0.205289,0.880265,0.824340,0.615737,0.496899,0.983632,0.865571,0.248373,0.542833]', '[0.203846,0.205289,0.880265,0.824340,0.615737,0.496899,0.983632,0.865571,0.248373,0.542833]');
INSERT INTO t1 VALUES(2, 2, '[0.735541,0.670776,0.903237,0.447223,0.232028,0.659316,0.765661,0.226980,0.579658,0.933939]', '[0.213846,0.205289,0.880265,0.824340,0.615737,0.496899,0.983632,0.865571,0.248373,0.542833]');
INSERT INTO t1 VALUES(3, 3, '[0.327936,0.048756,0.084670,0.389642,0.970982,0.370915,0.181664,0.940780,0.013905,0.628127]', '[0.223846,0.205289,0.880265,0.824340,0.615737,0.496899,0.983632,0.865571,0.248373,0.542833]');
使用近似最近邻搜索。
SELECT * FROM t1 ORDER BY l2_distance(c2, [0.712338,0.603321,0.133444,0.428146,0.876387,0.763293,0.408760,0.765300,0.560072,0.900498]) APPROXIMATE LIMIT 1;
返回结果如下:
+----+------+-------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------+
| c1 | c0 | c2 | c3 |
+----+------+-------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------+
| 3 | 3 | [0.327936,0.048756,0.08467,0.389642,0.970982,0.370915,0.181664,0.94078,0.013905,0.628127] | [0.223846,0.205289,0.880265,0.82434,0.615737,0.496899,0.983632,0.865571,0.248373,0.542833] |
+----+------+-------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------+
1 row in set
HNSW_SQ 索引示例
CREATE TABLE t2 (c1 INT AUTO_INCREMENT, c2 VECTOR(3), PRIMARY KEY(c1), VECTOR INDEX idx1(c2) WITH (distance=l2, type=hnsw_sq, lib=vsag));
HNSW_BQ 索引示例
CREATE TABLE t3 (c1 INT AUTO_INCREMENT, c2 VECTOR(3), PRIMARY KEY(c1), VECTOR INDEX idx3(c2) WITH (distance=l2, type=hnsw_bq, lib=vsag));
HNSW_BQ 索引 distance 参数仅支持 l2。
IVF 索引示例
注意
创建 IVF 索引时,索引名长度暂不支持超过 33 个字符,否则可能因为索引辅助表名长度超过 index_name 限制导致异常。未来版本会支持更长的索引名。
CREATE TABLE ivf_vecindex_suite_table_test (c1 INT, c2 VECTOR(3), PRIMARY KEY(c1), VECTOR INDEX idx2(c2) WITH (distance=l2, type=ivf_flat));
后建索引
注意
目前仅支持后建稠密向量索引。
HNSW 索引示例
创建测试表。
CREATE TABLE vec_table_hnsw (id INT, c2 VECTOR(10));
创建 HNSW 索引。
CREATE VECTOR INDEX vec_idx1 ON vec_table_hnsw(c2) WITH (distance=l2, type=hnsw);
查看创建的表。
SHOW CREATE TABLE vec_table_hnsw;
返回结果如下:
+-----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| vec_table_hnsw | CREATE TABLE `vec_table_hnsw` (
`id` int(11) DEFAULT NULL,
`c2` VECTOR(10) DEFAULT NULL,
VECTOR KEY `vec_idx1` (`c2`) WITH (DISTANCE=L2, TYPE=HNSW, LIB=VSAG, M=16, EF_CONSTRUCTION=200, EF_SEARCH=64) BLOCK_SIZE 16384
) DEFAULT CHARSET = utf8mb4 ROW_FORMAT = DYNAMIC COMPRESSION = 'zstd_1.3.8' REPLICA_NUM = 2 BLOCK_SIZE = 16384 USE_BLOOM_FILTER = FALSE TABLET_SIZE = 134217728 PCTFREE = 0 |
+-----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set
OceanBase(root@oceanbase)>SHOW INDEX FROM vec_table_hnsw;
+-----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+-----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+------------+
| vec_table | 1 | vec_idx1 | 1 | c2 | A | NULL | NULL | NULL | YES | VECTOR | available | | YES | NULL |
+-----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+------------+
1 row in set
HNSW_SQ 索引示例
创建测试表。
CREATE TABLE vec_table_hnsw_sq (c1 INT AUTO_INCREMENT, c2 VECTOR(3), PRIMARY KEY(c1));
创建 HNSW_SQ 索引。
CREATE VECTOR INDEX vec_idx2 ON vec_table_hnsw_sq(c2) WITH (distance=l2, type=hnsw_sq, lib=vsag, m=16, ef_construction = 200);
HNSW_BQ 索引示例
CREATE VECTOR INDEX vec_idx3 ON vec_table_hnsw_bq(c2) WITH (distance=l2, type=hnsw_bq, lib=vsag, m=16, ef_construction = 200);
HNSW_BQ 索引 distance 参数仅支持 l2。
IVF 索引示例
创建测试表。
CREATE TABLE vec_table_ivf (c1 INT, c2 VECTOR(3), PRIMARY KEY(c1));
创建 IVF 索引。
CREATE VECTOR INDEX vec_idx3 ON vec_table_ivf(c2) WITH (distance=l2, type=ivf_flat);
删除索引
删除向量索引的语法具体如下:
DROP INDEX vec_idx1 ON vec_table;
查看删除的索引。
SHOW INDEX FROM vec_table;
返回结果如下:
Empty set
维护
增量数据过多的情况下,搜索性能会下降。为减小增量数据表的数据量,OceanBase 引入了 DBMS_VECTOR 对向量索引进行维护。
全量刷新(重建)
如果建立索引后更新或删除数据较多,建议使用 REBUILD_INDEX 过程进行全量刷新。说明和示例请参见 REBUILD_INDEX。
默认情况下,全量刷新每 24 小时检查一次;若新增数据超过原有数据的 20%,则自动执行全量刷新。全量刷新会在后台异步执行,首先创建新的索引,然后替换旧索引。在重建过程中,旧索引保持可用状态,但整体过程相对较慢。
注意事项如下:
- 执行 离线 DDL 操作(例如
ALTER TABLE修改表结构或主键)时,将导致索引表的重建。由于重建索引无法指定并行度,系统会默认使用单线程,因此在数据量较大时,重建过程会比较缓慢,从而影响整个 离线 DDL 的执行效率。 - 重建索引时如果需要修改索引参数,必须在参数列表中同时指定
type和distance,且type和distance必须和原索引类型一致,例如原来索引类型是hnsw,距离算法是l2,则重建时必须同时指定type=hnsw和distance=l2。 - 重建索引时支持:
- 修改
m,ef_search,ef_construction值。 - 在线重建
ef_search参数。 hnsw<->hnsw_sq的索引类型重建。ivf_flat<->ivf_flat,ivf_pq<->ivf_pq的索引类型重建。- 支持重建时设置并行度。示例见 REBUILD_INDEX。
- 修改
- 重建索引时不支持:
- 修改
type和distance类型。 hnsw<->ivf的索引重建。hnsw<->hnsw_bq的索引重建。ivf_flat,ivf_pq之间的交叉重建。
- 修改
配置重建参数
如果遇到合并窗口过多或者业务高峰期,可能会因为资源调度冲突导致重建失败,这时可以通过 DBMS_VECTOR.SET_ATTRIBUTE PL 系统包为索引配置重建的触发周期,避开合并窗口或业务高峰。
通过 SET_ATTRIBUTE 可为单个向量索引设置自动重建的并行度、触发阈值与触发周期:
-- 设置 rebuild 并行度
CALL DBMS_VECTOR.SET_ATTRIBUTE('idx1', 't1', 'parallel', '20');
-- 设置 rebuild 触发阈值(增量数据达到基线 50% 时触发)
CALL DBMS_VECTOR.SET_ATTRIBUTE('idx1', 't1', 'rebuild_trigger_percentage', '0.5');
-- 设置 rebuild 触发周期:每 600 秒检查一次
CALL DBMS_VECTOR.SET_ATTRIBUTE('idx1', 't1', 'rebuild_repeat_interval', 'FREQ=SECONDLY; INTERVAL=600');
-- 设置 rebuild 触发周期:每天 19:45:00 检查
CALL DBMS_VECTOR.SET_ATTRIBUTE('idx1', 't1', 'rebuild_repeat_interval', 'FREQ=DAILY; byhour=19;byminute=45;bysecond=0');
使用时的注意事项如下:
- 不同索引的
rebuild_repeat_interval应错开,避免同一时段集中重建。
参数说明、约束和示例请参见 SET_ATTRIBUTE。