跳到主要内容

创建语义索引

本文档介绍了如何在 seekdb 中创建语义索引(Hybrid Vector Index)。

概述

语义索引利用 seekdb 内置的嵌入(Embedding)能力,极大地简化了向量索引的使用流程。它实现了向量概念对用户的透明化:你可以直接写入需要存储的原始数据(如文本),seekdb 会在内部自动将其转换为向量并建立索引。在搜索时,你同样只需提供原始搜索内容,seekdb 也会自动进行嵌入并搜索向量索引,从而显著提升了使用的便捷性。

考虑到嵌入模型的性能开销,语义索引提供了同步和异步两种嵌入方式供用户选择:

  • 同步模式:数据写入后立即进行嵌入和索引,确保数据实时可见。
  • 异步模式:由后台任务分批进行数据的嵌入和索引,这能显著提升写入性能。你可以根据对数据实时可见性的要求,灵活设置后台任务的触发周期。

此外,本特性还提供了对语义索引进行暴力搜索的能力,用以辅助判断搜索结果的正确性。暴力搜索指的是采用全表扫描的方式进行搜索,得到距离最近的前 n 行的精确结果。

功能支持

提示

本功能在当前版本中仅支持 HNSW/HNSW_BQ 索引。

本特性支持语义索引的创建、更新、删除与搜索的全流程,同时适配了 DBMS_VECTOR 系统包内的 REFRESH_INDEXREBUILD_INDEX。其中,更新、删除与搜索的使用语法和常规向量索引完全一致,异步模式下 REFRESH_INDEX 会额外触发数据的嵌入。创建、搜索的使用详见下文。

支持的功能点如下:

模块功能点介绍
DDL建表时创建语义索引可以在创建表的时候,在 VARCHAR 列上创建语义索引
DDL后建语义索引支持在已存在表的 VARCHAR 列上创建语义索引
搜索semantic_distance 函数通过该函数传入原始数据进行向量搜索
搜索semantic_vector_distance 函数通过该函数传入向量进行搜索,有两种使用方式:
  • 当 SQL 语句中带有 APPROXIMATE/APPROX 子句时,会使用向量索引进行搜索。
  • 当不带有 APPROXIMATE/APPROX 子句时,会采用全表扫描的方式进行暴力搜索。
DBMS_VECTORREFRESH_INDEX使用方法与常规向量索引相同,执行索引增量刷新以及异步模式的嵌入
DBMS_VECTORREBUILD_INDEX使用方法与常规向量索引相同,执行索引全量重建

一些使用注意事项如下:

  • 同步模式下,写入性能可能受到嵌入性能的影响;异步模式下,数据可见性会有延迟。
  • 对于重复搜索的场景,建议使用 AI 函数服务(AI Function Service)预先获取查询向量,避免每次搜索都进行嵌入。

前提条件

在使用语义索引之前,必须先注册嵌入模型和端点。以下是注册示例:

CALL DBMS_AI_SERVICE.DROP_AI_MODEL ('ob_embed');
CALL DBMS_AI_SERVICE.DROP_AI_MODEL_ENDPOINT ('ob_embed_endpoint');

CALL DBMS_AI_SERVICE.CREATE_AI_MODEL(
'ob_embed', '{
"type": "dense_embedding",
"model_name": "BAAI/bge-m3"
}');

CALL DBMS_AI_SERVICE.CREATE_AI_MODEL_ENDPOINT (
'ob_embed_endpoint', '{
"ai_model_name": "ob_embed",
"url": "https://api.siliconflow.cn/v1/embeddings",
"access_key": "sk-xxxxxxxxxxxxxxxxxxxxxxxxxxx",
"provider": "siliconflow"
}');
信息

请将 access_key 替换为您的实际 API Key。BAAI/bge-m3 模型的向量维度为 1024,因此在创建语义索引时需要使用 dim=1024

创建语法及说明

语义索引支持建表时创建后建两种方式。创建时需要注意:

  • 创建索引必须指定在 VARCHAR 类型的列上。
  • modelsync_mode 参数不支持在常规向量索引上配置。
  • 后建索引的参数和说明与建表时创建索引一致。

建表时创建

支持使用 CREATE TABLE 语句创建语义索引,通过索引参数,同步或者异步发起后台任务。同步模式会在插入数据时自动将 VARCHAR 数据转换成向量数据,异步模式则会定期或者手动完成数据转换。

语法

CREATE TABLE table_name (
column_name1 data_type1,
column_name2 VARCHAR, -- 文本列
...,
VECTOR INDEX index_name (column_name2) WITH (param1=value1, param2=value2, ...)
);

参数说明

参数默认值取值范围是否必填说明备注
distancel2/inner_product/cosine指定向量距离算法类型。l2 表示欧氏距离,inner_product 表示内积距离,cosine 表示余弦距离。
type目前支持 hnsw / hnsw_bq指定索引算法类型。
libvsagvsag指定向量索引库类型。目前仅支持 VSAG 向量库。
model已注册的模型名称指定用于 embedding 的大语言模型名称。必须在创建索引使用 AI 函数服务注册该模型。

说明

常规向量索引不支持设置此参数。

dim正整数,最大 4096指定 embedding 后的向量维度。必须与模型提供的维度对应。
sync_modeasyncimmediate/manual/async指定数据和索引同步的模式。immediate 表示同步模式,manual 表示手动模式,async 表示异步模式。

说明

常规向量索引不支持设置此参数。

sync_interval10s时间间隔,如 10s1h1d设置异步模式下后台任务的触发周期。数值部分需为正数,单位支持秒(s)、小时(h)、天(d)等。

其他向量索引参数(如 mef_constructionef_search 等)的使用与常规向量索引相同,具体请参见相关文档。

后建索引

支持在已经存在表的 VARCHAR 列上创建语义索引,后建索引时会通过提供的索引参数发起同步或者异步的后台任务。同步模式下所有现存 VARCHAR 数据会转换成向量数据,异步模式则会定期或者手动完成数据转换。

语法

CREATE VECTOR INDEX index_name 
ON table_name(varchar_column_name)
WITH (param1=value1, param2=value2, ...);

参数说明

参数说明与建表时创建索引一致,详见上文。

创建、更新与删除示例

语义索引的 DML 操作(INSERTUPDATEDELETE)与常规向量索引完全一致。插入或更新 VARCHAR 类型的数据时,系统会根据 sync_mode 参数设置自动或异步进行嵌入。

建表时创建

创建测试表 items 时创建 vector_idx 索引:

-- 假设 ob_embed 模型的创建在此前已完成(请参考"前提条件"部分注册模型)
CREATE TABLE items (
id BIGINT PRIMARY KEY,
doc VARCHAR(100),
VECTOR INDEX vector_idx(doc)
WITH (distance=l2, lib=vsag, type=hnsw, model=ob_embed, dim=1024, sync_mode=async, sync_interval=10s)
);

向测试表 items 插入一条数据,系统会自动进行嵌入:

INSERT INTO items(id, doc) VALUES(1, 'Rose');

后建

创建测试表 items 后,使用 CREATE VECTOR INDEX 语句创建 vector_idx 索引:

CREATE TABLE items (
id BIGINT PRIMARY KEY,
doc VARCHAR(100)
);

-- 假设 ob_embed 模型的创建在此前已完成(请参考"前提条件"部分注册模型)
CREATE VECTOR INDEX vector_idx
ON items (doc)
WITH (distance=l2, lib=vsag, type=hnsw, model=ob_embed, dim=1024, sync_mode=async, sync_interval=10s);

向测试表 items 插入一条数据,系统会自动进行嵌入:

INSERT INTO items(id, doc) VALUES(1, 'Rose');

更新

更新 VARCHAR 类型的数据时,系统会重新进行嵌入:

  • 同步模式:更新后立即重新进行嵌入。
  • 异步模式:更新后由后台任务在下次触发周期时重新进行嵌入。

使用示例:

UPDATE items SET doc = 'Lily' WHERE id = 1;

删除

删除操作与常规向量索引一致,直接删除数据即可。

使用示例:

DELETE FROM items WHERE id = 1;

搜索

语义索引支持两种搜索方式:

  • 使用原始文本搜索
  • 使用向量搜索

APPROXIMATE/APPROX 子句的详细用法请参见文末创建向量索引相关文档。

使用原始文本搜索

使用 semantic_distance 表达式,传入原始文本进行向量搜索。

语法

SELECT ... FROM table_name 
ORDER BY semantic_distance(column_name, 'query_text') [APPROXIMATE|APPROX]
LIMIT n;

其中:

  • column_name:语义索引创建时指定的文本列。
  • query_text:搜索的原始文本。
  • n:返回的结果行数。

使用示例

-- 假设 ob_emb 模型的创建在此前已完成
CREATE TABLE items (
id INT PRIMARY KEY,
doc varchar(100),
VECTOR INDEX vector_idx(doc)
WITH (distance=l2, lib=vsag, type=hnsw, model=ob_embed, dim=1024, sync_mode=immediate)
);

INSERT INTO items(id, doc) VALUES(1, 'Rose');
INSERT INTO items(id, doc) VALUES(2, 'Sunflower');
INSERT INTO items(id, doc) VALUES(3, 'Rose');
INSERT INTO items(id, doc) VALUES(4, 'Sunflower');
INSERT INTO items(id, doc) VALUES(5, 'Rose');

-- 使用原始文本进行搜索
SELECT id, doc FROM items
ORDER BY semantic_distance(doc, 'Sunflower')
APPROXIMATE LIMIT 3;

返回结果如下:

+----+-----------+
| id | doc |
+----+-----------+
| 2 | Sunflower |
| 4 | Sunflower |
| 5 | Rose |
+----+-----------+
3 rows in set

使用向量搜索(带 APPROXIMATE 子句)

使用 semantic_vector_distance 表达式,传入向量进行搜索,当搜索语句中带有 APPROXIMATE/APPROX 子句时,会使用向量索引进行搜索。

语法

SELECT ... FROM table_name 
ORDER BY semantic_vector_distance(column_name, 'query_vector') [APPROXIMATE|APPROX]
LIMIT n;

其中:

  • column_name:语义索引创建时指定的文本列。
  • query_vector:查询向量。
  • n:返回的结果行数。

使用示例

-- 假设 ob_emb 模型的创建在此前已完成(请参考"前提条件"部分注册模型)
CREATE TABLE items (
id INT PRIMARY KEY,
doc varchar(100),
VECTOR INDEX vector_idx(doc)
WITH (distance=l2, lib=vsag, type=hnsw, model=ob_embed, dim=1024, sync_mode=immediate)
);

INSERT INTO items(id, doc) VALUES(1, 'Rose');
INSERT INTO items(id, doc) VALUES(2, 'Lily');
INSERT INTO items(id, doc) VALUES(3, 'Sunflower');
INSERT INTO items(id, doc) VALUES(4, 'Rose');

-- 先获取查询向量
SET @query_vector = AI_EMBED('ob_embed', 'Sunflower');

-- 使用向量进行索引搜索
SELECT id, doc FROM items
ORDER BY semantic_vector_distance(doc, @query_vector)
APPROXIMATE LIMIT 3;

返回结果如下:

+----+-----------+
| id | doc |
+----+-----------+
| 3 | Sunflower |
| 1 | Rose |
| 4 | Rose |
+----+-----------+
3 rows in set

使用向量搜索(不带 APPROXIMATE 子句)

使用 semantic_vector_distance 表达式,传入向量进行搜索,当不带有 APPROXIMATE/APPROX 子句时,会采用全表扫描的方式进行暴力搜索,得到距离最近的前 n 行的精确结果。搜索执行时,会从表模式(Schema)中获取 distance 的类型,然后进行整表扫描,每行都会进行向量距离的计算,从而保证获取精确结果。

语法

SELECT ... FROM table_name 
ORDER BY semantic_vector_distance(column_name, 'query_vector')
LIMIT n;

其中:

  • column_name:语义索引创建时指定的文本列。
  • query_vector:查询向量。
  • n:返回的结果行数。

使用示例

-- 使用向量进行暴力搜索(精确结果)
SELECT id, doc FROM items
ORDER BY semantic_vector_distance(doc, @query_vector)
LIMIT 3;

返回结果如下:

+----+-----------+
| id | doc |
+----+-----------+
| 3 | Sunflower |
| 4 | Rose |
| 1 | Rose |
+----+-----------+
3 rows in set

索引维护

语义索引支持使用 DBMS_VECTOR 系统包进行索引维护,包括增量刷新和全量重建。

增量刷新

如果建立索引后写入数据较多,建议使用 REFRESH_INDEX 过程进行增量刷新。说明和示例请参见相关文档。

语义索引的特殊说明:

  • 使用方法与常规向量索引相同,详见相关文档。
  • 在异步模式下,REFRESH_INDEX 会额外触发数据的嵌入,确保增量数据被正确转换为向量并添加到索引中。

全量刷新(重建)

如果建立索引后更新或删除数据较多,建议使用 REBUILD_INDEX 过程进行全量刷新。说明和示例请参见相关文档。

语义索引的特殊说明:

  • 使用方法与常规向量索引相同,详见相关文档。
  • 执行任务合并增量和快照。

相关文档