PlanetScale 向量检索怎么配置:从建表到相似度查询
PlanetScale 本身不提供 pgvector 那样的向量类型或向量索引,向量检索需要自己用 JSON 列存向量,再在 SQL 里计算余弦距离排序。
适合数据量不大、想复用现有 MySQL 生态的场景;
数据量到几十万行以上时,全表扫描会明显变慢,需要提前评估。
先确认 PlanetScale 的向量能力边界
PlanetScale 兼容 MySQL 协议,支持 JSON 类型,但没有原生 VECTOR 列,也没有向量索引。
你能做的是:
- 用
JSON或TEXT列保存向量数组,例如[0.12, -0.03, 0.88]。 - 在应用层把查询向量转成同样格式。
- 用 SQL 计算余弦相似度并按结果排序。
这种方案不需要额外组件,但每次查询都会扫描候选行并计算,行数越多越慢。
如果检索规模较大,更合适的方向是换用支持向量索引的数据库,而不是在 PlanetScale 上硬扛。
建表与写入向量数据
假设要存储商品嵌入向量,先建一张表:
CREATE TABLE product_embeddings (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
product_id BIGINT UNSIGNED NOT NULL,
embedding JSON NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
KEY idx_product_id (product_id)
);
embedding 用 JSON 保存数组。
写入时保持维度一致,例如统一 768 维:
INSERT INTO product_embeddings (product_id, embedding)
VALUES (1001, '[0.12, -0.03, 0.88, 0.41]');
实际向量通常由嵌入模型生成,用 Python 写入的示例:
import json
import pymysql
conn = pymysql.connect(host='your-host', user='your-user', password='your-pass', database='your-db')
vec = [0.12, -0.03, 0.88, 0.41]
with conn.cursor() as cur:
cur.execute(
'INSERT INTO product_embeddings (product_id, embedding) VALUES (%s, %s)',
(1001, json.dumps(vec))
)
conn.commit()
写入前建议校验向量维度,避免同一张表里混入不同长度的数组。
用 SQL 计算余弦相似度
余弦相似度公式是点积除以模长乘积。
在 MySQL 中可以把 JSON 数组展开后计算,但更省事的办法是在应用层算,或者用存储函数封装。
下面给出一个可直接执行的查询思路,用 JSON_TABLE 把数组展开成行:
SELECT
e.product_id,
SUM(jt.v * q.v) / (
SQRT(SUM(jt.v * jt.v)) * SQRT(SUM(q.v * q.v))
) AS cosine_similarity
FROM product_embeddings e
JOIN JSON_TABLE(
e.embedding, '$[*]' COLUMNS (v DOUBLE PATH '$')
) jt
JOIN JSON_TABLE(
'[0.10, -0.02, 0.90, 0.40]', '$[*]' COLUMNS (v DOUBLE PATH '$')
) q
GROUP BY e.product_id
ORDER BY cosine_similarity DESC
LIMIT 10;
这条语句能跑通,但注意它会对全表每一行展开计算,只适合小数据量验证。
生产环境如果候选行较多,建议先在应用层做粗筛,例如按分类或时间范围缩小 WHERE 条件,再计算相似度。
避坑与性能注意事项
- 不要在 PlanetScale 上期待向量索引:目前没有原生向量索引,
ORDER BY相似度本质是全表计算,数据量上去后延迟会明显增加。 - JSON 列不要存成字符串数组:保持数值数组格式,避免查询时还要二次解析。
- 维度必须统一:写入前校验长度,混入不同维度会让相似度计算失去意义。
- 查询向量提前归一化:如果所有向量都做 L2 归一化,余弦相似度简化为点积,SQL 可以少算两个
SQRT。 - 大表先缩小范围:用
WHERE category_id = ?或时间范围过滤,再计算相似度,比直接全表排序更稳。
验证配置是否生效
写入几条测试数据后,执行上面的查询语句,确认:
- 返回结果按
cosine_similarity降序排列; - 相似度值在
-1到1之间; - 换一个明显不同的查询向量,排序结果发生变化。
如果查询报错 JSON_TABLE 不存在,说明 MySQL 版本过低;
PlanetScale 当前分支一般支持,但仍建议在开发分支先执行验证。
常见疑问
PlanetScale 能直接做向量检索吗?
不能开箱即用。
需要用 JSON 列存向量并手动计算相似度,没有专用向量索引。
数据量多大时不适合这种方案?
没有固定阈值,取决于行宽和查询频率。
经验上几千到几万行以内可以接受,再往上建议评估专用向量数据库,并用真实数据做压测。
能不能用全文索引替代?
全文索引面向文本关键词匹配,不计算语义相似度,和向量检索解决的不是同一个问题。
PlanetScale 向量检索配置的核心就是 JSON 存向量加 SQL 算距离,小规模验证够用,规模上来后要提前规划迁移或分层检索。