MoteDB 是什么
一个纯 Rust 写的嵌入式多模态数据库,面向具身智能场景(机器人、AR、边缘设备):向量、全文、时序、空间四类索引 + 列存 + ACID 事务 + SQL,单进程嵌入式,无外部依赖。MIT 协议,cargo add motedb 即用。
- GitHub: https://github.com/motedb/motedb
- crates.io: https://crates.io/crates/motedb
- 文档: https://motedb.github.io
use motedb::Database;
let db = Database::create("robot.mote")?;
db.execute("CREATE TABLE frames (id INT PRIMARY KEY, ts TIMESTAMP, emb VECTOR(384), body TEXT)")?;
db.execute("CREATE VECTOR INDEX f_emb ON frames(emb)")?;
db.execute("CREATE TEXT INDEX f_body ON frames(body)")?;
// 向量 + 全文 + 时序一个引擎里查
let hits = db.query(
"SELECT id FROM frames WHERE MATCH(body) AGAINST('抓取 失败') \
ORDER BY emb <-> '[0.1, 0.2, ...]' LIMIT 10")?;
Python / Node / Go 绑定 + MCP server 都有(pip install motedb-python / npm install motedb)。
v0.16.0:一个“找 bug”版本
这次发布的核心不是加功能,而是发布前做了 28 轮系统性猎虫(每轮针对一个此前零覆盖的维度写探针),累计修复 42 个缺陷。对数据库来说,最值得展开讲的是“静默错误结果”类——不报错、返回错的答案,比 panic 危险一个量级。挑几个有意思的:
1. 向量列在 UPDATE + DELETE + 段合并后读成 65535 维全零向量(数据损坏级)
列段合并时,墓碑行的占位字节给 VECTOR 列写的是裸 [0xFF 0xFF]——而在逐行 [dim: u16][payload] 编码里 0xFFFF 是合法的非空维度,后面却没有 262KB 载荷。顺序走读的解码器从这行开始错位,同列之后所有行雪崩(80 行的表实测 17 行损坏)。修复是把占位改成 [0x0000](dim 0 = NULL)。
这个 bug 的藏身之处说明了一个道理:没有测试的维度就是 bug 的温床——它是给“KNN 结果 vs 暴力扫描逐 id 比对”的影子字典 oracle 测试揪出来的,现在该 oracle 常驻回归套件。
2. WHERE 未知列被静默吞掉
WHERE usr_id = 5(拼错列名)返回 0 行、无任何报错——逐行过滤路径出于性能把求值错误统一当“不匹配”。修复是语句入口做一次 schema 绑定校验。但注意权衡:不能把过滤路径改成传播错误,动态回退会死——所以 JOIN 和相关子查询豁免。
3. 中文全文检索恒空
FTS 索引和逐行 MATCH 都硬编码空白分词器——无空格的中文句成一个整 token,MATCH(body) AGAINST('训练') 匹配 深度学习模型训练 两条路径全空。现在默认 AutoTokenizer:含 CJK 走 jieba 精确分词,其余空白分词,索引与逐行路径共用。
4. 一批“同一语义两种写法不同结果”
ts BETWEEN '字面量' AND '字面量'恒空而>= AND <=正常(向量化谓词编译器漏了类型预解析);SELECT 0x1F返回 0(词法器不认十六进制,x1F被吃成隐式别名);- TIMESTAMP ± INTEGER 算术 TypeError 被 WHERE 吞掉。
发布工程质量
- 四层 API 全部在当前引擎上端到端验证:Rust(292 个测试二进制 / 4253 断言)、Node、Go、Python + MCP stdio 协议往返;
- 性能 A/B 无回归:与 9 个版本前背靠背对照,ORDER BY 快 ~28%、查询内存省 18%,点读/扫描/GROUP BY 持平;
- clippy 双 feature 集(默认 + no-jieba/no-rayon 最小集)零警告;
- 语义全部钉住并写进文档:除零 = PostgreSQL 语义、LIKE 大小写敏感、复合主键/DEFAULT/NOT NULL 行为、NULLS FIRST/LAST 全路径生效。
给 Rust 同行的两个小教训
- 双实现必漂移:时间戳解析器、算术求值器都有 SqlRow / positional 两份副本,小数秒丢弃、类型分支缺失全是“修了一份忘了另一份”。能用一份实现就用一份。
- 占位字节也要过编码学:合并时墓碑行的占位符是“反正没人读”的字节,但在变长编码里任何字节序列都是合法数据。宽度正确 ≠ 语义正确。
链接
- GitHub: https://github.com/motedb/motedb (欢迎 star / issue / PR)
- v0.16.0 Release Notes: https://github.com/motedb/motedb/releases/tag/v0.16.0
- 文档: https://motedb.github.io
- 已知限制也是公开的:WHERE 里的除零错误目前会被吞(roadmap)、列级 UNIQUE 约束未实现、Windows npm 二进制因 npm 反垃圾误伤暂缺(工单处理中,文档有说明)
评论区
写评论还没有评论