向量检索与 RAG 应用实战指南


快速选型

函数用途返回值适用场景
ai_embedding(model, text)
ai_embedding(model, text)
文本转高维向量VECTOR(N)RAG 检索、语义搜索、向量化存储
vector(v1, v2, ...)
vector(v1, v2, ...)
创建向量VECTOR 类型构造查询向量、测试数据
cosine_distance(a, b)
cosine_distance(a, b)
余弦距离(0-2)FLOAT文本语义相似度、推荐系统
l2_distance(a, b)
l2_distance(a, b)
欧氏距离(≥0)FLOAT图像特征匹配、空间距离
dot_product(a, b)
dot_product(a, b)
向量点积FLOAT推荐系统评分计算
l2_norm(v)
l2_norm(v)
L2 范数(向量长度)FLOAT向量归一化预处理
l2_normalize(v)
l2_normalize(v)
L2 归一化VECTOR 类型将点积转为余弦相似度
fill_vector(n, val)
fill_vector(n, val)
创建填充向量VECTOR 类型零向量/单位向量基准
binary_quantize(v)
binary_quantize(v)
向量二值化VECTOR(tinyint, N)降维加速、汉明距离搜索

前置准备

本文所有示例基于以下测试数据:

-- 商品语义向量表 -- 实际生产中,使用 ai_embedding 函数将商品描述转为高维向量: -- UPDATE product_embeddings -- SET embedding = ai_embedding('endpoint:my_embedding_model', description); CREATE TABLE product_embeddings ( id BIGINT, name VARCHAR(100), description VARCHAR(500), category VARCHAR(50), embedding VECTOR(768), -- 创建向量索引(HNSW 算法),加速余弦距离检索 INDEX idx_embedding(embedding) USING VECTOR PROPERTIES ( 'scalar.type' = 'f32', 'distance.function' = 'cosine_distance' ) ); -- 模拟数据:实际向量由 Embedding 模型生成,此处用简化向量演示 -- 注意:真实场景中向量维度通常为 768、1024 或 1536 INSERT INTO product_embeddings (id, name, description, category, embedding) VALUES (1, 'Apple', 'Fresh red apple from organic farm, sweet and juicy.', 'Fruit', vector(0.9, 0.1, 0.0, 0.0) || fill_vector(764, 0.0)), (2, 'Banana', 'Ripe yellow banana, rich in potassium and energy.', 'Fruit', vector(0.1, 0.9, 0.0, 0.0) || fill_vector(764, 0.0)), (3, 'Carrot', 'Organic carrot, crunchy and full of vitamins.', 'Vegetable',vector(0.0, 0.0, 0.9, 0.1) || fill_vector(764, 0.0)), (4, 'Dog', 'Friendly golden retriever, great family pet.', 'Animal', vector(0.1, 0.0, 0.1, 0.8) || fill_vector(764, 0.0)), (5, 'Elephant', 'Majestic elephant, largest land animal.', 'Animal', vector(0.0, 0.1, 0.0, 0.9) || fill_vector(764, 0.0));


场景 0:使用 ai_embedding 生成向量

问题

如何将文本描述转换为高维向量,用于后续的相似度搜索。

SQL 实现

-- 使用 ai_embedding 将商品描述转为 768 维向量 SELECT id, name, description, ai_embedding('endpoint:my_embedding_model', description, JSON '{"dimensions": "768"}') AS embedding FROM products WHERE id <= 5;

批量生成向量

-- 为存量数据批量生成向量 UPDATE product_embeddings_768 SET embedding = ai_embedding('endpoint:my_embedding_model', description, JSON '{"dimensions": "768"}') WHERE embedding IS NULL;


场景 1:语义相似度搜索

问题

给定一个查询向量(如"水果"的 Embedding),找到最相似的商品。

SQL 实现

-- 给定查询文本,使用 ai_embedding 转为向量后检索 -- 实际生产中,查询向量也由 ai_embedding 生成: -- ai_embedding('endpoint:my_embedding_model', 'fresh sweet fruit') SELECT id, name, category, description, cosine_distance(embedding, ai_embedding('endpoint:my_embedding_model', 'fresh sweet fruit')) AS similarity FROM product_embeddings ORDER BY similarity ASC LIMIT 3;

输出:

idnamecategorydescriptionsimilarity
1AppleFruitFresh red apple...0.009
2BananaFruitRipe yellow banana...0.652
4DogAnimalFriendly golden retriever...0.881

场景 2:多距离函数对比

问题

不同距离度量适用于不同业务场景,需要对比效果。

SQL 实现

-- 对比不同距离度量的效果 -- 查询向量由 ai_embedding 实时生成 SELECT id, name, cosine_distance(embedding, ai_embedding('endpoint:my_embedding_model', 'fresh fruit')) AS cos_dist, l2_distance(embedding, ai_embedding('endpoint:my_embedding_model', 'fresh fruit')) AS l2_dist, dot_product(embedding, ai_embedding('endpoint:my_embedding_model', 'fresh fruit')) AS dot_prod FROM product_embeddings ORDER BY cos_dist ASC;

输出:

idnamecos_distl2_distdot_prod
1Apple0.0090.1410.74
2Banana0.6520.9900.26
3Carrot0.9571.2730.00
4Dog0.8811.0860.10
5Elephant0.9491.2250.02

场景 3:向量归一化与基准向量

问题

创建零向量作为基准,或计算向量归一化后的相似度。

SQL 实现

-- 创建零向量并计算距离 SELECT id, name, l2_distance(embedding, fill_vector(768, 0.0)) AS dist_to_zero, l2_norm(embedding) AS vector_length FROM product_embeddings ORDER BY dist_to_zero ASC LIMIT 3;

输出:

idnamedist_to_zerovector_length
4Dog0.8120.812
1Apple0.9060.906
2Banana0.9060.906

场景 4:二值化向量与汉明距离

问题

将浮点向量二值化为 0/1 向量,用于快速近似搜索。

SQL 实现

-- 二值化后计算汉明距离(避免直接输出向量列) SELECT a.id AS id_a, a.name AS name_a, b.id AS id_b, b.name AS name_b, hamming_distance( binary_quantize(a.embedding), binary_quantize(b.embedding) ) AS hamming_dist FROM product_embeddings a JOIN product_embeddings b ON a.id < b.id ORDER BY hamming_dist ASC LIMIT 5;

输出:

id_aname_aid_bname_bhamming_dist
3Carrot4Dog1.0
1Apple2Banana2.0
...............

场景 5:Jaccard 相似度(集合重叠)

问题

计算两个二值向量(表示集合)的 Jaccard 距离,用于衡量集合重叠度。

SQL 实现

-- Jaccard 距离需要 tinyint 类型的向量 -- 距离 = 0 表示完全相同,距离 = 1 表示完全不同 SELECT jaccard_distance(vector(1Y, 1Y, 0Y, 0Y), vector(1Y, 0Y, 1Y, 0Y)) AS jaccard_dist, -- Jaccard 相似度 = 1 - 距离 1 - jaccard_distance(vector(1Y, 1Y, 0Y, 0Y), vector(1Y, 0Y, 1Y, 0Y)) AS jaccard_sim

输出:

jaccard_distjaccard_sim
0.6670.333

场景 7:向量索引加速检索

问题

当数据量达到百万级以上时,暴力计算所有向量距离会导致查询极慢。向量索引是大规模向量检索的必要条件,可以将查询时间从分钟级降至毫秒级。

为什么需要向量索引?

场景无索引(暴力检索)有索引(HNSW)
查询方式全表扫描,计算所有向量距离近似最近邻搜索(ANN),只计算部分向量
时间复杂度O(N),随数据量线性增长O(log N),随数据量对数增长
小规模数据(< 1万条)性能差异不明显性能差异不明显
大规模数据(> 10万条)查询时间显著增加查询时间基本稳定

SQL 实现

方式 1:建表时声明向量索引(推荐)

CREATE TABLE product_embeddings ( id BIGINT, name VARCHAR(100), embedding VECTOR(768), INDEX idx_embedding(embedding) USING VECTOR PROPERTIES ( 'scalar.type' = 'f32', 'distance.function' = 'cosine_distance' ) );

方式 2:存量表后建向量索引

-- 先有表和数据,后建索引 CREATE VECTOR INDEX idx_embedding ON TABLE product_embeddings(embedding) PROPERTIES ( 'scalar.type' = 'f32', 'distance.function' = 'cosine_distance' ); -- 存量数据需手动触发构建 BUILD INDEX idx_embedding ON product_embeddings;

验证索引是否生效

-- 查看表上的索引 SHOW INDEX IN product_embeddings;

输出:

index_nameindex_type
idx_embeddingvector

向量索引 + 文本过滤

-- 问题: 向量索引 + WHERE 其他字段过滤会退化到暴力检索 -- 方案 1: 子查询先向量检索,再外层过滤 SELECT id, name, dist FROM ( SELECT id, name, cosine_distance(embedding, query_vec) as dist FROM product_embeddings WHERE cosine_distance(embedding, query_vec) < 0.5 ORDER BY dist LIMIT 100 ) WHERE name LIKE '%Apple%'; -- 方案 2: 向量索引 + 倒排索引配合使用 SET cz.sql.index.prewhere.enabled=true; SELECT id, name, cosine_distance(embedding, query_vec) as dist FROM product_embeddings WHERE match_regexp(name, '.*Apple.*', map('analyzer', 'keyword')) AND cosine_distance(embedding, query_vec) < 0.5 ORDER BY dist LIMIT 100;


场景 8:综合实战 — RAG 知识库检索

问题

构建一个简单的 RAG(检索增强生成)知识库检索流程:

  1. 将用户查询转为向量
  2. 检索 Top K 最相关的文档
  3. 按类别过滤结果

SQL 实现

-- RAG 检索流程: -- 1. 用户查询 → ai_embedding 转为向量 -- 2. 向量检索 → Top K 相关文档 -- 3. 将检索结果 + 原始查询 → LLM 生成回答 SELECT id, name, category, description, cosine_distance(embedding, ai_embedding('endpoint:my_embedding_model', 'large land animal')) AS relevance FROM product_embeddings WHERE category = 'Animal' -- 可选:按类别过滤 ORDER BY relevance ASC LIMIT 2;

输出:

idnamecategoryrelevance
4DogAnimal0.000
5ElephantAnimal0.134

常见问题

1. 向量类型无法直接输出

-- 错误: 直接查询向量列会报错 SELECT embedding FROM product_embeddings; -- 报错: data type vector(float,4) is not currently supported by textfile writer -- 正确: 配合距离函数使用,或只输出标量结果 SELECT id, name, cosine_distance(embedding, vector(0.5, 0.5, 0.5, 0.5)) AS dist FROM product_embeddings; -- 正确: 二值化后计算距离 SELECT l2_distance(binary_quantize(embedding), binary_quantize(vector(0.5, 0.5, 0.5, 0.5))) AS bin_dist FROM product_embeddings;

2.
ai_embedding
ai_embedding
生成向量的维度一致性

-- 错误: 查询向量与存储向量维度不一致 cosine_distance(embedding, ai_embedding('endpoint:my_model', 'query')) -- embedding 是 768 维,ai_embedding 默认可能是 1536 维 -- 正确: 指定 dimensions 参数保持一致 ai_embedding('endpoint:my_model', 'query', JSON '{"dimensions": "768"}')

3.
vector()
vector()
函数参数格式

-- 错误: 传入字符串数组 vector('[0.9, 0.1, 0.0, 0.0]') -- 正确: 传入独立数值参数 vector(0.9, 0.1, 0.0, 0.0)

3. 余弦距离 vs 余弦相似度

-- cosine_distance 返回距离值(0-2),不是相似度 -- 相似度 = 1 - 距离 SELECT name, 1 - cosine_distance(embedding, query_vec) AS cosine_similarity FROM product_embeddings; -- 验证: 相同向量距离=0, 正交向量距离=1, 相反向量距离=2 SELECT cosine_distance(vector(1.0, 0.0), vector(1.0, 0.0)) AS same, -- 0 cosine_distance(vector(1.0, 0.0), vector(0.0, 1.0)) AS ortho, -- 1 cosine_distance(vector(1.0, 0.0), vector(-1.0, 0.0)) AS opp; -- 2

4. 向量维度必须一致

-- 错误: 维度不匹配会报错 cosine_distance(vector(1.0, 2.0), vector(1.0, 2.0, 3.0)) -- 正确: 确保查询向量与存储向量维度相同 cosine_distance(embedding, vector(0.8, 0.2, 0.0, 0.0)) -- 4 维对 4 维

5.
fill_vector
fill_vector
参数顺序

-- 错误: 参数顺序反了 fill_vector(vector(0.0, 0.0), 4, 0.5) -- 正确: fill_vector(dimension, fill_value) fill_vector(4, 0.0) -- 创建 4 维零向量

6. 向量运算函数

-- vector_add_scalar: 向量每个元素加标量(第二个参数需为整数) SELECT l2_distance( vector_add_scalar(vector(1.0, 2.0, 3.0), 2), vector(3.0, 4.0, 5.0) ) AS dist; -- 结果: 0,说明计算正确 -- l2_normalize: 归一化后 L2 范数≈1 SELECT l2_norm(l2_normalize(vector(1.0, 2.0, 3.0, 4.0))) AS norm; -- 结果: 0.99999994


性能优化建议

场景优化策略
大规模向量检索建立向量索引(HNSW),避免全表扫描
二值化加速
binary_quantize
binary_quantize
降维,汉明距离计算更快
预过滤先用
WHERE
WHERE
过滤类别/时间范围,再计算向量距离
批量查询
JOIN
JOIN
替代多次单条查询
向量索引调优调整
cz.vector.index.search.ef
cz.vector.index.search.ef
参数,平衡性能与准确率

-- 推荐: 先过滤再计算距离 SELECT id, name, cosine_distance(embedding, query_vec) AS dist FROM product_embeddings WHERE category = 'Fruit' -- 先缩小范围 ORDER BY dist ASC LIMIT 3; -- 不推荐: 全表计算距离后再过滤 SELECT id, name, cosine_distance(embedding, query_vec) AS dist FROM product_embeddings ORDER BY dist ASC LIMIT 100; -- 然后再在应用层过滤 category -- 推荐: 使用向量索引加速 SET cz.vector.index.search.ef=64; -- 调整探索因子 SELECT id, name, cosine_distance(embedding, query_vec) AS dist FROM product_embeddings WHERE cosine_distance(embedding, query_vec) < 0.5 -- 距离阈值触发索引 ORDER BY dist ASC LIMIT 10;


相关文档

联系我们
预约咨询
微信咨询
电话咨询