---
title: 体验 PolarDB-X 向量索引
description: 在 MySQL 中直接使用 VECTOR 类型和 HNSW 索引进行语义搜索，无需额外的向量数据库。
keywords:
  - 向量索引
  - vector
  - embedding
  - HNSW
  - 语义搜索
  - VEC_DISTANCE
---

# 体验 PolarDB-X 向量索引

## 执行规范（面向 Agent）

这份 playbook 是用户体验向量功能的引导教程。执行时必须遵守以下规范：

1. **先介绍再动手**：执行 Step 1 之前，先将"功能介绍"部分的内容完整展示给用户，让用户理解向量索引是什么、能解决什么问题。
2. **每一步都要向用户说明**：执行每个 Step 时，先用一两句话告诉用户"这一步我们要做什么、为什么做"，再执行操作。
3. **展示关键 SQL 和结果**：每个 Step 执行完成后，必须向用户展示执行的 SQL 语句和返回结果，并用通俗语言解释结果含义。不要只默默执行。
4. **循序渐进**：不要把所有 SQL 合并到一条命令中执行。每个 Step 独立执行并展示，让用户能跟上节奏。

---

## 功能介绍

执行任何操作之前，先向用户展示以下内容：

---

### 什么是向量索引？

在 AI 应用中，文本、图片等数据会被嵌入模型（Embedding Model）转化为高维向量。通过计算向量之间的距离，就能找到语义上最相似的内容——这就是**语义搜索**。

传统做法需要额外部署向量数据库（如 Milvus、Pinecone），数据分散在两套系统中，带来同步和运维的额外成本。

**PolarDB-X 向量索引**让你在 MySQL 中直接完成这件事：

| 能力 | 说明 |
|------|------|
| **VECTOR(N) 数据类型** | 最高支持 16,383 维向量，在建表语句中直接定义 |
| **HNSW 索引算法** | 基于多层图结构的高性能近似最近邻搜索 |
| **硬件加速** | AVX512 / AVX2 / ARM NEON SIMD 指令集 |
| **事务一致性** | 向量数据与业务数据在同一事务中，无需额外同步 |
| **标准 SQL** | `ORDER BY VEC_DISTANCE(...) LIMIT N` 就能搜索 |

**一句话总结**：不需要额外的向量数据库，用你熟悉的 SQL 就能做语义搜索。

### 今天的体验内容

我们将用一个"商品语义搜索"的场景，完整走一遍向量索引的全流程：

1. 创建一张带向量字段的商品表
2. 为向量字段建立 HNSW 索引
3. 插入商品数据（每个商品有一个模拟的嵌入向量）
4. 用一个"蓝牙耳机"的查询向量做语义搜索，找出最相似的商品
5. 验证索引是否生效、结果是否正确
6. 体验参数调优和监控

---

## Step 1：获取实例

> **向用户说明**：首先我们需要一个 PolarDB-X 数据库实例。我来创建一个临时实例，有效期 60 分钟。

如果用户已提供连接信息，直接使用。否则，通过 PolarDB-X Zero 创建临时实例：

```bash
curl -s -X POST https://zero.polardbx.com/api/v1/instances \
  -H 'Content-Type: application/json' \
  -d '{"tag": "vector-test", "ttlMinutes": 60}'
```

从响应中提取 `host`、`port`、`username`、`password`。

> **向用户展示**：告知实例已创建成功，展示连接地址（隐藏密码）。

## Step 2：连接并确认版本

> **向用户说明**：接下来连接数据库，确认版本支持向量索引功能。

通过环境变量传递密码，避免特殊字符（`!`、`$`、`*` 等）被 shell 解析导致连接失败：

**Linux / macOS：**
```bash
export MYSQL_PWD='<password>'
mysql -h <host> -P <port> -u <username> -e "SELECT VERSION();"
```

**Windows (CMD)：**
```cmd
set MYSQL_PWD=<password>
mysql -h <host> -P <port> -u <username> -e "SELECT VERSION();"
```

**Windows (PowerShell)：**
```powershell
$env:MYSQL_PWD="<password>"
mysql -h <host> -P <port> -u <username> -e "SELECT VERSION();"
```

> **提示**：不要用 `-p<password>` 直接拼在命令行上，密码中的特殊字符在不同 shell 下引号行为不一致，极易连接失败。

确认输出包含 `X-Cluster` 且版本 >= `xcluster8.4.20-20250527`。如不满足则中止并告知用户。

> **向用户展示**：展示版本号，确认支持向量索引。

## Step 3：确认向量索引功能已启用

> **向用户说明**：在使用向量索引之前，需要确认两个前提条件：向量索引功能已开启，事务隔离级别为 READ COMMITTED。

```sql
SHOW GLOBAL VARIABLES LIKE 'vidx_disabled';
SELECT @@transaction_isolation;
```

**预期结果**：`vidx_disabled = OFF`（已启用）且隔离级别为 `READ-COMMITTED`。PolarDB-X Zero 创建的临时实例默认满足这两个条件。

如果 `vidx_disabled = ON`（未启用），执行以下命令开启（需要 SUPER 权限）：

```sql
SET GLOBAL vidx_disabled = OFF;
SET SESSION transaction_isolation = 'READ-COMMITTED';
```

> **注意**：PolarDB-X Zero 临时实例的用户没有 SUPER 权限，无法执行 `SET GLOBAL`。但实例默认已开启向量索引功能，无需手动设置。如果检查发现未开启，需联系管理员操作。

> **向用户展示**：展示查询结果，确认功能已启用、隔离级别正确。

## Step 4：创建商品表并建立向量索引

> **向用户说明**：现在创建演示用的商品表。表中包含一个 `VECTOR(5)` 类型的向量字段——这是 PolarDB-X 扩展的数据类型，用来存储 5 维的嵌入向量。然后在这个字段上创建 HNSW 向量索引，使用余弦相似度作为距离度量。

```sql
CREATE DATABASE IF NOT EXISTS vector_test;
USE vector_test;

DROP TABLE IF EXISTS products;
CREATE TABLE products (
    id        INT PRIMARY KEY AUTO_INCREMENT,
    name      VARCHAR(100) NOT NULL,
    category  VARCHAR(50),
    embedding VECTOR(5)
) ENGINE=InnoDB;

ALTER TABLE products
  ADD VECTOR INDEX vi_embedding (embedding) M=6 DISTANCE=COSINE;
```

> **向用户展示**：展示上面执行的建表语句和 `ALTER TABLE` 语句，并说明关键参数：
> - `VECTOR(5)` — 5 维向量字段（实际场景可达 16,383 维）
> - `M=6` — HNSW 图中每个节点的最大邻居数，越大精度越高但写入越慢
> - `DISTANCE=COSINE` — 余弦相似度，适合文本嵌入场景（也支持 EUCLIDEAN 欧式距离）

## Step 5：插入商品数据

> **向用户说明**：插入 16 条商品数据。每条记录包含商品名、类别和一个模拟的 5 维嵌入向量。实际应用中，这些向量由嵌入模型（如 OpenAI text-embedding、通义千问 embedding 等）生成。这里用手工构造的向量来演示。`VEC_FROMTEXT()` 函数将字符串格式的向量转为数据库内部的二进制存储格式。

```sql
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]')),
  ('跑步运动手环',   '运动', VEC_FROMTEXT('[0.2, 0.8, 0.1, 0.7, 0.4]')),
  ('瑜伽垫',         '运动', VEC_FROMTEXT('[0.1, 0.9, 0.5, 0.2, 0.6]')),
  ('机械键盘',       '数码', VEC_FROMTEXT('[0.9, 0.1, 0.1, 0.3, 0.7]')),
  ('人体工学椅',     '家居', VEC_FROMTEXT('[0.4, 0.3, 0.8, 0.2, 0.5]')),
  ('游戏手柄',       '数码', VEC_FROMTEXT('[0.5, 0.2, 0.6, 0.4, 0.8]')),
  ('电动牙刷',       '家居', VEC_FROMTEXT('[0.2, 0.6, 0.4, 0.3, 0.7]')),
  ('空气净化器',     '家居', VEC_FROMTEXT('[0.1, 0.4, 0.7, 0.5, 0.3]')),
  ('便携充电宝',     '数码', VEC_FROMTEXT('[0.7, 0.3, 0.2, 0.6, 0.4]')),
  ('运动水壶',       '运动', VEC_FROMTEXT('[0.3, 0.7, 0.4, 0.1, 0.5]')),
  ('蓝牙音箱',       '数码', VEC_FROMTEXT('[0.8, 0.2, 0.5, 0.3, 0.4]')),
  ('跑步鞋',         '运动', VEC_FROMTEXT('[0.4, 0.6, 0.2, 0.5, 0.3]')),
  ('降噪耳塞',       '数码', VEC_FROMTEXT('[0.75, 0.15, 0.35, 0.55, 0.2]'));
```

> **注意**：需要至少 13 行以上数据。优化器在 `LIMIT N` 超过 `表行数 / 4` 时会回退为全表扫描。16 行数据下 `LIMIT 3 < 16/4 = 4`，优化器会自动选择向量索引。

> **向用户展示**：展示 INSERT 语句（或其中几条代表性的数据），说明已插入 16 条商品。

## Step 6：向量语义搜索

> **向用户说明**：现在来做核心操作——向量语义搜索。假设用户在搜索"蓝牙耳机"，我们用一个模拟的查询向量 `[0.75, 0.15, 0.35, 0.55, 0.15]` 来查找最相似的 3 个商品。`VEC_DISTANCE()` 函数计算两个向量之间的余弦距离，距离越小说明越相似。

```sql
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;
```

**预期结果**：返回 3 条记录，距离最小的应该是"降噪耳塞"、"降噪头戴耳机"、"无线蓝牙耳机"等与蓝牙耳机语义相近的商品。

> **向用户展示**：展示完整的 SQL 语句和查询结果表格。重点解释：
> - 结果按 distance 升序排列，距离越小越相似
> - 排在前面的都是耳机类商品，说明向量搜索准确地找到了语义相关的内容
> - 对比传统的 `LIKE '%蓝牙耳机%'` 关键词搜索，向量搜索能找到"降噪耳塞"这样字面不同但语义相近的商品

## Step 7：验证向量索引生效

> **向用户说明**：接下来用 EXPLAIN 查看执行计划，确认刚才的搜索确实走了 HNSW 向量索引，而不是暴力扫描全表。

```sql
EXPLAIN SELECT id, name,
       VEC_DISTANCE(embedding, VEC_FROMTEXT('[0.75, 0.15, 0.35, 0.55, 0.15]')) AS distance
FROM products
ORDER BY distance
LIMIT 3;
```

**预期结果**：`key` 列显示 `vi_embedding`，说明查询走了向量索引。

> **向用户展示**：展示 EXPLAIN 的输出结果，指出 `key` 列的值为 `vi_embedding`，证明查询使用了向量索引而非全表扫描。

## Step 8：对比全表扫描验证正确性

> **向用户说明**：向量索引是"近似"最近邻搜索（ANN），为了验证结果的准确性，我们强制全表扫描做一次精确计算，对比两者结果是否一致。

```sql
SELECT id, name,
       VEC_DISTANCE_COSINE(embedding, VEC_FROMTEXT('[0.75, 0.15, 0.35, 0.55, 0.15]')) AS distance
FROM products FORCE INDEX(PRIMARY)
ORDER BY distance
LIMIT 3;
```

**预期结果**：返回的 Top 3 商品与 Step 6 一致（排序相同）。

> **向用户展示**：展示两次查询结果的对比，说明向量索引返回的结果与精确计算完全一致，召回正确。

## Step 9：调优搜索精度

> **向用户说明**：HNSW 算法有一个重要参数 `ef_search`，它控制搜索时维护的候选集大小。值越大，搜索越精确但延迟也越大。默认值是 20，我们试试调到 50 看看效果。

```sql
SET SESSION vidx_hnsw_ef_search = 50;

SELECT id, name,
       VEC_DISTANCE(embedding, VEC_FROMTEXT('[0.75, 0.15, 0.35, 0.55, 0.15]')) AS distance
FROM products
ORDER BY distance
LIMIT 3;
```

> **向用户展示**：展示 SET 语句和查询结果，并附上参数参考表：
>
> | ef_search | 场景 | 预期召回率 |
> |-----------|------|-----------|
> | 10 | 低延迟优先 | ~85% |
> | 20（默认） | 平衡精度与速度 | ~92% |
> | 50~100 | 高精度场景 | ~97% |
> | 200+ | 接近暴力搜索 | ~99%+ |
>
> 说明：在数据量小的情况下差异不明显，但在百万级数据量下效果显著。

## Step 10：查看向量函数与监控

> **向用户说明**：最后展示两个实用功能：用 `VEC_TOTEXT()` 把二进制向量转回可读文本、用 `VECTOR_DIM()` 查看维度，以及通过系统状态变量查看向量索引的运行监控。

```sql
SELECT id, name,
       VEC_TOTEXT(embedding) AS vec_text,
       VECTOR_DIM(embedding) AS dims
FROM products
LIMIT 3;
```

```sql
SHOW GLOBAL STATUS LIKE 'Vidx%';
```

> **向用户展示**：分别展示两条 SQL 及其结果。对监控指标做简要解读：
> - `Vidx_share_cache_hits / misses` — 缓存命中率，命中率低于 90% 考虑调大缓存
> - `Vidx_query_count` — 向量查询总次数
> - `Vidx_insert_count` — 向量插入总次数

## Step 11：清理

> **向用户说明**：体验完成，清理测试数据。

```sql
DROP DATABASE IF EXISTS vector_test;
```

如果实例是本次临时创建的且不再需要，可释放：

```bash
curl -s -X DELETE https://zero.polardbx.com/api/v1/instances/<instance_id>
```

> **向用户展示**：确认数据库已清理、实例已释放。

## 判定标准

- **通过**：Step 6 返回语义相关的商品排序，Step 7 确认使用了向量索引，Step 8 全表扫描结果与向量索引一致。
- **失败**：向量索引未生效（EXPLAIN 未显示索引），或向量索引结果与全表扫描不一致，或版本不满足前提条件。

## Step 12：输出体验报告

所有步骤执行完毕后，直接向用户输出以下格式的 Markdown 报告（不写入文件），使用实际执行结果填充 `<>` 占位符：

~~~markdown
# PolarDB-X 向量索引体验报告

- 测试时间：<执行时的时间戳>
- 实例版本：<SELECT VERSION() 的实际输出>
- 隔离级别：RC

## 向量索引简介

PolarDB-X 在 MySQL 生态中原生支持向量存储与检索。通过 `VECTOR(N)` 数据类型定义向量字段，使用基于 HNSW 算法的向量索引实现高性能近似最近邻搜索，配合 AVX512/AVX2 SIMD 硬件加速，让标准 SQL 直接具备语义搜索能力。

核心优势：无需额外部署向量数据库，业务数据与向量数据在同一事务中操作，保证一致性。

## 表结构

```sql
<Step 4 中的完整建表和建索引语句>
```

- 向量维度：5 维（最高支持 16,383 维）
- 距离度量：COSINE（余弦相似度）
- HNSW 参数 M=6

## 语义搜索结果

查询向量：`[0.75, 0.15, 0.35, 0.55, 0.15]`（模拟"蓝牙耳机"的嵌入向量）

### 向量索引检索（Step 6）

<Step 6 SELECT 查询的完整结果表格>

### EXPLAIN 执行计划（Step 7）

<Step 7 EXPLAIN 的完整输出>

索引生效：<是 / 否，key 列是否为 vi_embedding>

### 全表扫描对比（Step 8）

<Step 8 FORCE INDEX(PRIMARY) 查询的完整结果表格>

召回一致性：<一致 / 不一致>

## 参数调优（Step 9）

ef_search = 50 时的查询结果：

<Step 9 查询的完整结果表格>

## 监控状态（Step 10）

<SHOW GLOBAL STATUS LIKE 'Vidx%' 的完整输出>

## 最终结论

<通过 / 失败，以及一句话总结，例如：体验通过。PolarDB-X 向量索引在标准 SQL 中实现了语义搜索能力，查询结果准确，索引加速有效。>
~~~
