云原生数据库PolarDB分布式版在 MySQL 生态中原生提供向量存储与检索能力。您可以用标准 SQL 定义向量字段、写入向量数据,并通过 ORDER BY VEC_DISTANCE(...) LIMIT N 完成高性能的近似最近邻(ANN)相似度检索,适用于语义搜索、推荐召回、图文多模态检索、RAG(检索增强生成)等 AI 场景。
功能简介
向量索引底层基于业界主流的 HNSW(Hierarchical Navigable Small World)算法,并复用 InnoDB 的事务、持久化、崩溃恢复与主备复制能力,让您像使用普通索引一样使用向量索引。
向量索引解决的核心问题是:在海量高维向量中,快速找到与目标向量最相似的 Top-N 条记录。
核心特性
PolarDB-X向量索引的主要特性如下:
|
特性 |
说明 |
|
最大维度 |
支持最高 16,383 维 |
|
数据类型 |
单精度浮点(float32) |
|
距离度量 |
EUCLIDEAN(欧氏距离)、COSINE(余弦距离) |
|
索引算法 |
HNSW 多层图结构 |
|
硬件加速 |
自动启用 AVX512 / AVX2 / ARM NEON 指令集加速距离计算 |
|
事务支持 |
支持已提交读(Read Committed,RC) /可重复读(Repeatable Read,RR) /串行化(SERIALIZABLE)隔离级别 |
|
复制与高可用 |
支持Binlog复制、XA事务,主备数据一致。企业版支持分布式事务。 |
适用范围
您的实例需满足以下版本要求:
-
产品系列:标准版或企业版。
-
引擎版本:MySQL 8.0。
-
存储节点版本:V2.6.0.8.4.21-20260605 及以上版本。
-
向量数据的写入、更新、删除与基表在同一事务内自动同步,无需手动维护索引,使用体验与普通索引一致。不同实例产品系列支持能力有所不同:
能力
标准版(集中式)
企业版(分布式)
向量存储与ANN检索
支持
支持
主备复制/高可用
支持
支持
事务
支持
支持
使用限制
-
存储引擎:仅支持在InnoDB引擎表上创建向量索引。
-
索引数量:同一张表当前仅支持创建一个向量索引。
-
分区表 :暂不支持在标准版分区表上创建向量索引,企业版分区表支持创建向量索引。
-
DDL算法:创建、修改、删除向量索引使用COPY算法(非INPLACE),对大表会有较长的执行时间与锁定期,建议在业务低峰期操作。
-
INVISIBLE索引:向量索引不支持设置为INVISIBLE。
-
向量数据约束:写入向量的维度必须与建表时
VECTOR(N)的 N 严格一致,且不允许包含NaN或Inf值。 -
NULL 向量:向量列允许为 NULL。值为 NULL 的行不会被纳入向量索引,检索时不会被返回。
-
空间膨胀:
UPDATE / DELETE采用“标记删除 + 新增”方式维护图结构,高频更新或删除场景下辅助表会逐渐膨胀、召回率下降,需定期执行OPTIMIZE TABLE重建。
开启向量索引功能
向量索引功能由系统变量 vidx_disabled 控制,默认值为 ON(即默认关闭)。出于资源隔离考虑,需先显式开启后才能创建和使用向量索引。
vidx_disabled 为反向开关:ON 表示关闭功能,OFF 表示开启功能。
方式一:(推荐)控制台修改
前往PolarDB分布式版控制台,在目标集群的页面的存储层页签中,将参数vidx_disabled修改为OFF。
方式二:命令行修改
-- ON = 关闭,OFF = 开启
SET GLOBAL vidx_disabled = OFF;
该变量修改后,已有连接不会立即生效,需重新建立连接后才能使用向量索引。
使用向量索引
创建向量字段与索引
向量字段使用 VECTOR(维度) 类型声明,例如:
标准版
CREATE TABLE articles (
id INT PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(200),
embedding VECTOR(128) -- 128 维向量字段
) ENGINE=InnoDB;
企业版
CREATE TABLE articles (
id INT PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(200),
embedding VECTOR(128) -- 128 维向量字段
) ENGINE=InnoDB
PARTITION BY KEY(id);
创建向量索引
-
方式一:建表时直接创建。
标准版
CREATE TABLE articles ( id INT PRIMARY KEY AUTO_INCREMENT, title VARCHAR(200), embedding VECTOR(128), VECTOR INDEX vi (embedding) M=6 DISTANCE=EUCLIDEAN ) ENGINE=InnoDB;企业版
CREATE TABLE articles ( id INT PRIMARY KEY AUTO_INCREMENT, title VARCHAR(200), embedding VECTOR(128), VECTOR INDEX vi (embedding) M=6 DISTANCE=EUCLIDEAN ) ENGINE=InnoDB PARTITION BY KEY(id); -
方式二:ALTER TABLE追加。
ALTER TABLE articles ADD VECTOR INDEX vi (embedding) M=16 DISTANCE=COSINE; -
方式三:CREATE VECTOR INDEX。
-- 使用默认参数 M=6, DISTANCE=EUCLIDEAN CREATE VECTOR INDEX vi ON articles (embedding);
索引参数说明
|
参数 |
含义 |
选型建议 |
|
M |
每个节点在图中的最大邻居连接数。M 越大,索引占用空间越大、写入越慢,但搜索精度越高。
|
|
|
DISTANCE |
距离度量函数。EUCLIDEAN 衡量绝对空间距离,COSINE 衡量方向相似度。取值范围:
|
|
查看向量索引
向量索引不会出现在SHOW INDEX FROM <表名>的结果中,请使用SHOW CREATE TABLE查看。
-- 查看索引定义(向量索引以 VECTOR KEY 形式展示)
SHOW CREATE TABLE articles;
返回示例:
CREATE TABLE `articles` (
`id` int NOT NULL AUTO_INCREMENT,
`title` varchar(200) DEFAULT NULL,
`embedding` vector(128) DEFAULT NULL,
PRIMARY KEY (`id`),
VECTOR INDEX `vi`(`embedding`) M=16 DISTANCE=COSINE
) ENGINE = InnoDB
删除向量索引
-- 删除向量索引
ALTER TABLE articles DROP INDEX vi;
写入与修改向量数据
您使用VEC_FROMTEXT()将字符串格式的向量转为内部存储格式。
-
单行插入
INSERT INTO articles (title, embedding) VALUES ('深度学习入门', VEC_FROMTEXT('[0.12, 0.34, 0.56, ...]')); -
批量插入
INSERT INTO articles (title, embedding) VALUES ('文章A', VEC_FROMTEXT('[0.1, 0.2, 0.3, 0.4, 0.5]')), ('文章B', VEC_FROMTEXT('[0.5, 0.4, 0.3, 0.2, 0.1]')); -
更新向量字段(索引自动同步更新)
UPDATE articles SET embedding = VEC_FROMTEXT('[0.9, 0.8, ...]') WHERE id = 1; -
删除行(索引自动同步清理)
DELETE FROM articles WHERE id = 1;
向量检索
-
标准检索模式为
ORDER BY VEC_DISTANCE(...) LIMIT N:-- 找出与目标向量最相似的 10 条记录 SELECT id, title, VEC_DISTANCE(embedding, VEC_FROMTEXT('[0.1, 0.2, 0.3, 0.4, 0.5]')) AS distance FROM articles ORDER BY distance LIMIT 10;返回示例:
+----+--------------+----------+------------------------+ | id | name | category | distance | +----+--------------+----------+------------------------+ | 2 | 降噪头戴耳机 | 数码 | 0.005887877200042468 | | 1 | 无线蓝牙耳机 | 数码 | 0.006059869516314431 | | 3 | 运动蓝牙耳机 | 运动 | 0.09631679001555782 | +----+--------------+----------+------------------------+优化器行为说明:
-
优化器检测到
ORDER BY VEC_DISTANCE(...) LIMIT N模式后,会基于代价自动选择向量索引。 -
查询必须带
LIMIT子句,否则不会使用向量索引。 -
若
LIMIT过大(超过表行数的 1/4),优化器会回退为全表扫描。若大表查询意外回退,可通过FORCE INDEX(向量索引名)强制使用向量索引。
-
-
使用
Hint强制指定索引:-- 强制使用向量索引 SELECT * FROM articles FORCE INDEX(vi) ORDER BY VEC_DISTANCE_EUCLIDEAN(embedding, VEC_FROMTEXT('[0.1, 0.2, 0.3, 0.4, 0.5]')) LIMIT 10; -- 强制全表扫描(精确计算,用于验证召回率) SELECT * FROM articles FORCE INDEX(PRIMARY) ORDER BY VEC_DISTANCE_EUCLIDEAN(embedding, VEC_FROMTEXT('[0.1, 0.2, 0.3, 0.4, 0.5]')) LIMIT 10; -
通过
EXPLAIN可确认是否使用了向量索引(命中时key列显示向量索引名):EXPLAIN SELECT * FROM articles ORDER BY VEC_DISTANCE(embedding, VEC_FROMTEXT('[0.1, 0.2, 0.3, 0.4, 0.5]')) LIMIT 10;说明PolarDB-X 使用分布式执行计划格式。命中向量索引时,
physicalPlan中的key字段会显示向量索引名(如vi_embedding)。当表数据量较小时(如不足数百行),优化器可能选择全表扫描(key:null)。
向量函数
|
函数 |
等价别名 |
说明 |
|
|
- |
将 |
|
|
- |
将向量转回可读字符串 |
|
|
- |
计算两向量距离。若 v1 为带索引列,自动采用该索引的距离类型 |
|
|
- |
显式计算欧氏距离(L2) |
|
|
- |
显式计算余弦距离(1 − 余弦相似度) |
日常查询推荐使用VEC_DISTANCE(),写法最简洁,且会自动匹配索引的距离类型。COSINE 距离返回的是1 − 余弦相似度,值越小表示越相似,与EUCLIDEAN方向一致,均使用ORDER BY distance升序。
系统变量与参数调优
|
变量名 |
作用域 |
说明 |
|
|
GLOBAL |
向量索引功能总开关,修改后需重连生效。
|
|
|
SESSION |
创建索引未指定DISTANCE时的默认距离类型。
说明
仅可通过控制台参数设置页面修改,不支持SQL |
|
|
SESSION |
创建索引未指定M(每个节点在图中的最大邻居连接数)时的默认值。
说明
仅可通过控制台参数设置页面修改,不支持SQL |
|
|
SESSION |
搜索时的候选集大小,越大精度越高但越慢,该值不会小于LIMIT。
|
|
|
GLOBAL |
单个向量索引的内存缓存上限。
说明
仅可通过控制台参数设置页面修改,不支持SQL |
ef_search 选型指南
|
ef_search值 |
预期召回率 |
适用场景 |
|
10 |
~85% |
低延迟优先,允许少量漏检 |
|
20(默认) |
~92% |
平衡精度与速度 |
|
50~100 |
~97% |
高精度场景 |
|
200+ |
~99%+ |
接近暴力检索 |
调优示例
-- 提高搜索精度(牺牲一些延迟)
SET SESSION vidx_hnsw_ef_search = 100;
-- 降低延迟(牺牲一些精度)
SET SESSION vidx_hnsw_ef_search = 10;
监控与运维
您通过以下命令查看向量索引运行状态:
SHOW GLOBAL STATUS LIKE 'Vidx%';
返回示例:
+----------------------------------+----------+
| Variable_name | Value |
+----------------------------------+----------+
| Vidx_cache_usage | 1048576 |
| Vidx_insert_count | 5 |
| Vidx_load_node_hits | 14 |
| Vidx_load_node_misses | 10 |
| Vidx_load_vec_hits | 6 |
| Vidx_load_vec_misses | 6 |
| Vidx_query_count | 1 |
| Vidx_update_count | 0 |
| ... | ... |
+----------------------------------+----------+
常用监控指标
|
状态变量 |
含义 |
|
|
向量查询总次数 |
|
|
向量插入 / 更新总次数 |
|
|
图节点缓存命中 / 未命中次数 |
|
|
向量数据缓存命中 / 未命中次数 |
|
|
当前缓存内存使用量(字节) |
运维建议
-
缓存命中率 =
(Vidx_load_node_hits + Vidx_load_vec_hits)/(Vidx_load_node_hits + Vidx_load_node_misses + Vidx_load_vec_hits + Vidx_load_vec_misses,若低于 90%,可适当调大vidx_hnsw_cache_size。 -
定期执行
OPTIMIZE TABLE可清理因更新/删除产生的冗余节点,控制空间增长。 -
高精度需求时优先调大
vidx_hnsw_ef_search,并保证其不小于查询的LIMIT。
端到端示例
以下示例演示一个“商品语义搜索”完整流程:
-
开启功能
SET GLOBAL vidx_disabled = OFF; -
创建表并定义5维向量字段
标准版
CREATE TABLE products ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(100) NOT NULL, category VARCHAR(50), embedding VECTOR(5) ) ENGINE=InnoDB;企业版
CREATE TABLE products ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(100) NOT NULL, category VARCHAR(50), embedding VECTOR(5) ) ENGINE=InnoDB PARTITION BY KEY(id); -
创建向量索引(余弦距离)
ALTER TABLE products ADD VECTOR INDEX vi_embedding (embedding) M=6 DISTANCE=COSINE; -
写入商品数据
INSERT INTO products (name, category, embedding) VALUES ('无线蓝牙耳机', '数码', VEC_FROMTEXT('[0.8, 0.1, 0.3, 0.5, 0.2]')), ('降噪头戴耳机', '数码', VEC_FROMTEXT('[0.7, 0.2, 0.4, 0.6, 0.1]')), ('运动蓝牙耳机', '运动', VEC_FROMTEXT('[0.6, 0.5, 0.3, 0.4, 0.3]')), ('智能手表', '数码', VEC_FROMTEXT('[0.3, 0.7, 0.2, 0.8, 0.1]')); -
检索与“蓝牙耳机”最相似的3个商品
SELECT id, name, category, VEC_DISTANCE(embedding, VEC_FROMTEXT('[0.75, 0.15, 0.35, 0.55, 0.15]')) AS distance FROM products ORDER BY distance LIMIT 3;返回示例:
+----+--------------+----------+------------------------+ | id | name | category | distance | +----+--------------+----------+------------------------+ | 2 | 降噪头戴耳机 | 数码 | 0.005887877200042468 | | 1 | 无线蓝牙耳机 | 数码 | 0.006059869516314431 | | 3 | 运动蓝牙耳机 | 运动 | 0.09631679001555782 | +----+--------------+----------+------------------------+
常见问题
-
如何确认实例是否支持并已开启向量索引?
确认实例存储节点版本不低于V2.6.0.8.4.21-20260605,并通过以下命令确认功能已开启,返回
OFF表示已开启。SHOW GLOBAL VARIABLES LIKE 'vidx_disabled';返回示例:
+-----------------+-------+ | Variable_name | Value | +-----------------+-------+ | vidx_disabled | OFF | +-----------------+-------+ -
为什么向量检索没有走索引?
请依次确认:
-
vidx_disabled = OFF且已重新建立连接。 -
SQL 包含
ORDER BY VEC_DISTANCE(...) LIMIT N。 -
LIMIT值未超过表行数的 1/4。
可通过
EXPLAIN验证,命中时key列会显示向量索引名。 -
-
检索召回率不达预期怎么办?
可调大会话变量
vidx_hnsw_ef_search(如 50~100),或在建索引时增大 M(如 16)。可使用FORCE INDEX(PRIMARY)做全表精确检索作为对比基准。 -
创建向量索引为什么比较慢?
向量索引使用 COPY 算法构建,需要为存量数据逐条建立 HNSW 图结构,大表耗时较长,建议在业务低峰期执行。
-
向量索引会增加多少存储和内存?
-
存储:索引大小约为基表向量列大小的 1.5 倍。
-
内存:由
vidx_hnsw_cache_size控制单个索引的缓存上限。 -
缓存:主要由行数、向量维度和 M 决定,可用以下经验公式估算(单位:字节):
vidx_hnsw_cache_size ≈ 行数 × (维度 × 2 + M × 16 + 60)-
维度 × 2:向量经量化压缩后的大小(每维 2 字节)。 -
M × 16:图节点邻居连接的开销。 -
60:节点对象等固定开销。
估算示例:
行数
维度
M
建议缓存
100 万
128
6
≈ 700 MB
100 万
768
16
≈ 1.8 GB
1000 万
128
6
≈ 7 GB
-
说明缓存超过上限后会触发整体重建、影响查询性能。建议在估算值基础上适当上调;若监控发现缓存命中率偏低,可再调大。
-
-
向量索引支持主备复制和高可用吗?
支持。向量数据的写入与基表在同一事务内同步,通过Binlog复制到备库,主备数据保持一致,同时支持XA事务。在企业版(分布式)下,向量索引还支持分布式事务,跨分片的向量数据写入与检索可在分布式事务中保证一致性。