在 Percona Server for MySQL 9.7 中直接计算向量相似度

2026-09-21 29 预计阅读时间: 1 分钟
来源: percona.com AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:9 分钟

Percona Server for MySQL 9.7.2-2 加入了 DISTANCE(),让应用可以在 SQL 中直接计算向量距离,并使用 COSINEEUCLIDEANMANHATTANDOT 等度量完成排序或过滤。VECTOR_DISTANCE() 则提供了面向向量距离计算的对应接口。

这项能力解决的是向量检索中最基础的一步:给定查询向量,为候选记录打分。它还不是 HNSW、IVF 这类近似最近邻索引,但已经足以支持小规模检索、元数据预过滤后的重排,以及向量算法验证。

向量距离进入 SQL 意味着什么

传统做法通常是从数据库读取候选记录,在 Python、Java 或独立向量服务中计算相似度。现在,距离计算可以和普通 SQL 条件放在同一条查询中:

SELECT
    id,
    title,
    DISTANCE(embedding, @query_vector, 'COSINE') AS distance
FROM documents
WHERE language = 'zh'
ORDER BY distance ASC
LIMIT 10;

这带来几个直接变化:

  • 可以先用租户、语言、时间、权限等普通字段缩小候选集,再计算向量距离。
  • 距离值可以参与 ORDER BY、阈值过滤、CTE 和后续业务逻辑。
  • 应用不必把大量向量搬出数据库后再逐条评分。
  • SQL 查询更容易纳入已有的事务、权限和审计体系。

不过,距离函数只是计算原语。没有 ANN 索引时,数据库通常仍需对候选行逐一计算距离;单独添加 LIMIT 10 并不意味着只计算十次。

四种度量应该怎样选择

Percona Server 9.7.2-2 支持的度量覆盖了常见的嵌入检索场景:

度量 适合的场景 使用时需要注意
COSINE 文本嵌入、语义搜索、方向比长度更重要的向量 通常将较小的余弦距离视为更相似
EUCLIDEAN 向量的绝对位置和长度有意义 特征尺度会显著影响结果
MANHATTAN 希望使用各维绝对差之和 高维数据中应通过真实样本验证效果
DOT 模型训练目标基于内积,或向量已经归一化 不要未经验证就假设返回值与排序方向

度量并不是可以随意切换的 UI 选项。嵌入模型如何训练、输出是否归一化,以及线上阈值如何标定,都会影响最终选择。

尤其是 DOT,不同系统可能返回原始内积,也可能把它转换成便于按距离升序排列的值。升级或切换函数名时,可以先用方向明确的向量做一次探针查询:

SET @x = STRING_TO_VECTOR('[1,0,0]');
SET @same = STRING_TO_VECTOR('[1,0,0]');
SET @opposite = STRING_TO_VECTOR('[-1,0,0]');

SELECT
    DISTANCE(@x, @same, 'DOT') AS same_value,
    DISTANCE(@x, @opposite, 'DOT') AS opposite_value;

观察实际返回值后,再确定业务查询应该使用升序还是降序。对 COSINEEUCLIDEANMANHATTAN 这类距离,一般采用 ORDER BY distance ASC

一套可以直接改造的 SQL 示例

下面假设已经连接到 Percona Server for MySQL 9.7.2-2,并使用三维向量缩短示例。生产环境应将 VECTOR(3) 改为嵌入模型的真实维度,例如 384、768 或其他固定值。

先确认服务器版本:

mysql -u root -p -e 'SELECT VERSION();'

创建表并写入几条测试数据:

DROP DATABASE IF EXISTS vector_demo;
CREATE DATABASE vector_demo;
USE vector_demo;

CREATE TABLE documents (
    id BIGINT PRIMARY KEY,
    title VARCHAR(200) NOT NULL,
    language CHAR(2) NOT NULL,
    embedding VECTOR(3) NOT NULL,
    INDEX idx_language (language)
);

INSERT INTO documents (id, title, language, embedding) VALUES
    (1, 'MySQL query optimization', 'en', STRING_TO_VECTOR('[0.95,0.10,0.05]')),
    (2, 'Vector search in SQL',     'en', STRING_TO_VECTOR('[0.90,0.20,0.10]')),
    (3, 'Database backup guide',    'en', STRING_TO_VECTOR('[0.15,0.85,0.20]')),
    (4, 'SQL 中的向量检索',         'zh', STRING_TO_VECTOR('[0.88,0.22,0.12]'));

执行余弦距离排序:

SET @query_vector = STRING_TO_VECTOR('[0.92,0.18,0.08]');

SELECT
    id,
    title,
    DISTANCE(embedding, @query_vector, 'COSINE') AS distance
FROM documents
ORDER BY distance ASC
LIMIT 3;

如果项目使用 VECTOR_DISTANCE() 命名,可以用相同数据验证其行为:

SELECT
    id,
    title,
    VECTOR_DISTANCE(embedding, @query_vector, 'COSINE') AS distance
FROM documents
ORDER BY distance ASC
LIMIT 3;

需要阈值过滤时,使用 CTE 可以避免在同一查询层直接引用计算别名:

WITH scored AS (
    SELECT
        id,
        title,
        DISTANCE(embedding, @query_vector, 'COSINE') AS distance
    FROM documents
    WHERE language = 'en'
)
SELECT id, title, distance
FROM scored
WHERE distance < 0.10
ORDER BY distance ASC
LIMIT 10;

这里的 0.10 只是演示值,不能直接照搬到生产环境。合理阈值应根据真实查询、正负样本和召回率要求进行标定。

没有 ANN 索引时,怎样把查询做得更稳

现阶段最实用的策略不是把整个大表交给距离函数,而是尽量减少需要评分的候选行。

例如先按租户、文档类型和时间过滤:

WITH candidates AS (
    SELECT id, title, embedding
    FROM documents
    WHERE language = 'en'
      AND id > 100000
    LIMIT 5000
),
scored AS (
    SELECT
        id,
        title,
        DISTANCE(embedding, @query_vector, 'COSINE') AS distance
    FROM candidates
)
SELECT id, title, distance
FROM scored
ORDER BY distance ASC
LIMIT 20;

这是一种可以实践的候选集重排模式,但要注意:没有稳定排序条件的 LIMIT 5000 可能产生不可预测的候选集。生产查询通常应配合时间、主键范围、全文检索结果或其他明确的召回规则。

还可以使用 EXPLAIN 检查普通过滤条件是否命中索引:

EXPLAIN
SELECT
    id,
    DISTANCE(embedding, @query_vector, 'COSINE') AS distance
FROM documents
WHERE language = 'en'
ORDER BY distance ASC
LIMIT 10;

普通 B-tree 索引可以帮助缩小 language 等结构化条件的范围,但不能代替面向向量距离的 ANN 索引。

上线前的检查清单

将这项能力接入业务前,建议确认以下事项:

  • 固定向量维度,并拒绝维度不一致的数据。
  • 记录嵌入模型名称、版本和归一化方式,避免新旧向量混用。
  • 用明确样本验证每种度量的返回值和排序方向,尤其是 DOT
  • 通过离线数据标定距离阈值,不要复制示例中的常量。
  • 先使用租户、权限、语言和时间等字段过滤候选集。
  • 对真实数据量执行 EXPLAIN 和延迟测试,观察全表或大范围扫描成本。
  • 将向量生成放在应用或模型服务中;数据库中的 DISTANCE() 负责评分,而不是生成嵌入。
  • 为未来的 HNSW、IVF 等 ANN 能力保留模型版本和索引重建方案。

DISTANCE() 的价值在于让向量评分成为普通 SQL 的组成部分。对于小数据集、精确评估、混合过滤以及 ANN 召回后的重排,它已经是一个实用组件;面对百万级甚至更大的无过滤搜索,则应等待或引入专门的 ANN 索引方案,而不是把一次全量距离排序误当成可扩展的向量搜索。


相关推荐