首批通过分布式安全可靠测评,为关键业务系统打造
创建向量索引
更新时间:2026-05-20 17:52:22
本文介绍了 OceanBase 如何创建、搜索、维护和删除向量索引。
OceanBase 向量索引的具体说明如下:
- 支持 HNSW 索引,索引列最大维度为 2000。HNSW 索引是一种内存索引,需要完整载入内存,支持 DML 和实时搜索。
- 支持 L2 和内积(IP)作为索引距离算法。
- 向量索引搜索支持调用部分距离函数,具体请参见 使用 SQL 函数。
准备工作
使用向量索引前,需要通过设置 ob_vector_memory_limit_percentage 开启向量功能。
ALTER SYSTEM SET ob_vector_memory_limit_percentage = 30;
索引搜索概述
向量索引搜索是一种近似最近邻搜索,并不保证 100% 的结果正确。相应的向量搜索准确率的指标是召回率,例如在查 10 个最近邻时,如果可以稳定返回 9 个正确的结果,那么召回率就是 90%。召回率说明如下:
召回率受构建参数和搜索参数的影响。
搜索参数在建索引时指定,之后不可修改,但可通过 session 变量
ob_hnsw_ef_search设置。如果设置了ob_hnsw_ef_search,会优先使用它的值。具体设置方式请参见ob_hnsw_ef_search。
搜索语法如下:
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子句会报错。
索引创建、搜索及删除示例
注意事项
OceanBase 向量索引的创建支持在建表时创建和后建两种方式。创建索引时需要注意:
向量索引创建后,不支持任何参数的修改。
创建向量索引必须带有 VECTOR 关键字。
后建索引的参数和说明与建表时创建索引一致。
如果数据量较大,建议先写完数据,再创建索引,以获得最佳搜索性能。
建表时创建索引
创建测试表。
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
索引参数说明:
| 参数 | 默认值 | 取值范围 | 是否必填 | 说明 | 备注 |
|---|---|---|---|---|---|
| distance | l2/inner_product | 是 | 指定向量距离算法类型。 | l2 表示欧氏距离,inner_product 表示内积距离。 | |
| type | hnsw | 是 | 指定索引类型。 | 目前仅支持 HNSW 索引。 | |
| lib | vsag | vsag | 否 | 指定向量索引库类型。 | 目前仅支持 VSAG 向量库。 |
| m | 16 | [5,64] | 否 | HNSW 构建参数,每个节点的最大邻居数。 | 值越大,索引构建越慢,搜索性能越好。 |
| ef_construction | 200 | [5,1000] | 否 | HNSW 构建参数,构建索引时的候选集大小。 | 值越大,索引构建越慢,索引质量越好。ef_construction 必须大于 m。 |
| ef_search | 64 | [1,1000] | 否 | HNSW 搜索参数,搜索时的候选集大小。 | 值越大,搜索越慢,召回率越高。 |
后建索引
创建测试表。
CREATE TABLE vec_table (id int, c2 vector(10));
创建索引。
CREATE VECTOR INDEX vec_idx1 ON vec_table(c2) WITH (distance=l2, type=hnsw);
查看测试表结构。
SHOW CREATE TABLE vec_table;
+-----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| vec_table | CREATE TABLE `vec_table` (
`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
查看索引。
SHOW INDEX FROM vec_table;
+-----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+------------+
| 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
删除索引
删除索引。
DROP INDEX vec_idx1 ON vec_table;
查看索引。
SHOW INDEX FROM vec_table;
返回结果如下:
Empty set
索引维护
增量数据过多的情况下,搜索性能会下降。为减小增量数据表的数据量,OceanBase 引入了 DBMS_VECTOR 对向量索引进行维护。
全量刷新
如果建立索引后更新或删除数据较多,建议使用全量刷新。
语法如下:
PROCEDURE rebuild_index(
IN idx_name VARCHAR(65535), ---- 索引名
IN table_name VARCHAR(65535), ---- 表名
IN idx_vector_col VARCHAR(65535) DEFAULT NULL, ---- 向量列名
IN delta_rate_threshold FLOAT DEFAULT 0.2, ---- 增量数据的比例
IN idx_organization VARCHAR(65535) DEFAULT NULL, ---- 索引类型
IN idx_distance_metrics VARCHAR(65535) DEFAULT 'EUCLIDEAN',---- 距离类型
IN idx_parameters LONGTEXT DEFAULT NULL, ---- 索引参数
IN idx_parallel_creation INT DEFAULT 1); ---- 并行构建索引的并行度,预留,仅语法支持
全量刷新每 24 小时会检查一次,如果新增数据超过原有数据的 20%,则自动执行全量刷新。全量刷新会在后台异步执行,首先创建新的索引,然后替换旧索引。在重建过程中,旧索引保持可用状态,但整体过程相对较慢。
索引维护示例
创建测试表。
CREATE TABLE vector_index_test(c1 INT, c2 VECTOR(3), PRIMARY KEY(c1), VECTOR INDEX idx1(c2) WITH (distance=l2, type=hnsw, lib=vsag));
写入测试数据。
INSERT INTO vector_index_test VALUES(1, '[0.203846,0.205289,0.880265]');
INSERT INTO vector_index_test VALUES(2, '[0.484526,0.669954,0.986755]');
INSERT INTO vector_index_test VALUES(3, '[0.327936,0.048756,0.084670]');
INSERT INTO vector_index_test VALUES(4, '[0.148869,0.878546,0.028024]');
INSERT INTO vector_index_test VALUES(5, '[0.334970,0.857377,0.886132]');
INSERT INTO vector_index_test VALUES(6, '[0.117582,0.302352,0.471198]');
INSERT INTO vector_index_test VALUES(7, '[0.551185,0.231134,0.075354]');
INSERT INTO vector_index_test VALUES(8, '[0.185221,0.315131,0.558301]');
INSERT INTO vector_index_test VALUES(9, '[0.928764,0.254038,0.272721]');
触发更新。
-- 触发全量更新。
call dbms_vector.rebuild_index('idx1','t1','c2');