< 返回版块

motedb 发表于 2026-10-31 15:58

Tags:数据库,AI,IOT,嵌入式

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 同行的两个小教训

  1. 双实现必漂移:时间戳解析器、算术求值器都有 SqlRow / positional 两份副本,小数秒丢弃、类型分支缺失全是“修了一份忘了另一份”。能用一份实现就用一份。
  2. 占位字节也要过编码学:合并时墓碑行的占位符是“反正没人读”的字节,但在变长编码里任何字节序列都是合法数据。宽度正确 ≠ 语义正确。

链接

  • 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 反垃圾误伤暂缺(工单处理中,文档有说明)

评论区

写评论

还没有评论

1 共 0 条评论, 1 页