Appearance
memory_search 向量查询使用全表扫描,有 190 倍加速空间(sqlite-vec KNN 未生效)
问题
memory_search 工具调用时(in-gateway 路径)响应极慢,随着记忆条目增加,搜索时间线性增长。
根本原因:searchVector 使用了非索引的全表扫描模式——在 SELECT 中直接调用 vec_distance_cosine(...) 并配合 ORDER BY ... LIMIT,而非使用 sqlite-vec 提供的 KNN 虚表索引(MATCH 语法)。
社区测试数据:切换为 KNN 查询后实测约 190 倍速度提升。
影响版本:OpenClaw 2026.4.15
解决方案
方案一:等待官方修复
该 bug 已提交性能优化报告,关注后续版本 release notes。
方案二:理解规避方式
限制 memory 条目总量可以缓解问题。较小的知识库受影响程度更低(全表扫描在小数据集上仍然快):
yaml
agents:
defaults:
memory:
maxChunks: 500 # 减少条目数以降低全表扫描耗时方案三:本地 patch(高级用户)
将 searchVector 中的查询从全表扫描改为 KNN 索引查询,但有重要注意事项:
js
// ⚠️ 错误的简单修复(返回零结果)
// SELECT v.distance FROM chunks_vec v WHERE v.embedding MATCH ? AND k = ?
// 问题:chunks_vec 默认使用 L2 距离,v.distance 可能 > 1.0
// score = 1 - dist 为负数,被 minScore 过滤掉
// ✅ 正确修复:同时处理距离度量类型
// 选项 A:重建 chunks_vec 时指定余弦距离
// CREATE VIRTUAL TABLE chunks_vec USING vec0(
// embedding float[N] distance_metric=cosine
// )
// 选项 B:保持 L2 距离,但调整 minScore 的计算方式(不推荐,破坏语义)
// 选项 C:使用 KNN 但在应用层对 L2 距离做归一化处理关键陷阱:直接套用 KNN 语法但不处理距离度量类型,会导致搜索返回零结果。这是社区在测试时踩过的坑,完整修复需要同时修改向量表创建和查询两个地方。
常见问题
Q: 如何判断是否命中此性能问题?
A: 观察 memory_search 的响应时间随记忆条目数量变化。若从几十条变到几千条后搜索时间成比例增加(而非接近常数),则是全表扫描特征。
Q: 降低 maxChunks 会丢失记忆吗?
A: 会导致旧记忆被淘汰。如果是线上生产 agent,先备份 memory.db 再调整配置。