有人用 LLM 把 SQLite 用 Rust 重写了一遍。代码能编译,测试能过,README 写得很专业。
然后跑了个最简单的性能测试:查询 100 行数据。
SQLite 用了 0.09 毫秒。LLM 生成的版本用了 1815 毫秒。
慢了 20,171 倍。
这不是打错小数点。这是一个能编译、能通过测试、看起来完全正常的数据库,在最基础的操作上直接崩了。
代码看起来没问题
这个 Rust 重写项目有 57.6 万行代码,625 个文件。有 parser、planner、B-tree、WAL,模块名字都对,架构看起来也对。
但有两个致命 bug:
Bug 1:查询规划器不认主键
SQLite 里,当你声明 id INTEGER PRIMARY KEY 时,查询 WHERE id = 5 会直接走 B-tree 搜索,时间复杂度 O(log n)。
LLM 生成的版本?它只认三个魔法字符串:rowid、_rowid_、oid。你用 id 当主键?对不起,全表扫描,O(n²)。
100 行数据,100 次查询 = 10,000 次行比较。SQLite 只需要 700 次 B-tree 操作。
Bug 2:每次插入都 fsync
每个 INSERT 语句外面都包了一层 autocommit,每次都调 fsync()。100 条插入 = 100 次磁盘同步。
SQLite 用的是 fdatasync(),只同步数据不同步元数据,快 1.6-2.7 倍。而且 SQLite 会复用编译好的语句,LLM 版本每次都重新编译。
结果:批量插入慢了 78 倍。
更离谱的是那些安全的选择
除了这两个明显的 bug,还有一堆看起来合理的设计决策:
- 每次缓存命中都
.clone()整个 AST,然后重新编译成字节码 - 每次读取都分配 4KB 的
Vec,即使是缓存命中 - 每次 autocommit 后都重新加载整个数据库 schema
- 每条语句都创建新的事务、程序、引擎对象
每个决策单独看都有道理:我们 clone 是因为 Rust 的所有权很复杂、我们用 sync_all() 因为这是安全默认值。
但加在一起?慢了 2900 倍。
这不是个例
同一个开发者还做了另一个项目:清理 Rust 编译产物的守护进程。
问题:Rust 的 target/ 目录太大,占满磁盘。
解决方案:8.2 万行 Rust 代码,192 个依赖,带终端 dashboard、贝叶斯评分引擎、EWMA 预测器、PID 控制器...
实际需要的解决方案:
*/5 * * * * find ~/*/target -type d -name "incremental" -mtime +7 -exec rm -rf {} +一行 cron,0 依赖。或者直接用 Rust 官方工具 cargo-sweep。
LLM 的问题不是语法错误
LLM 生成的代码能编译,能通过测试,README 写得很专业。问题是:
它生成的是你描述的东西,不是你需要的东西。
你说实现一个查询规划器,它就给你一个查询规划器——只不过每个查询都走全表扫描。
你说智能管理磁盘空间,它就给你 8.2 万行的智能系统——只不过问题本来只需要一行 cron。
代码在语法和语义上都是正确的。它就是不解决问题。
谁最危险?
反驳的声音会说:技术好的人能发现这些 bug。
对,这正是问题所在。
LLM 对最不具备验证能力的人最危险。如果你能在查询规划器里发现 is_ipk 检查缺失,LLM 确实能帮你提速。如果你发现不了,你根本不知道代码是错的。
它能编译,测试能过,LLM 还会告诉你看起来很棒。
SQLite 为什么快?
不是因为它用 C 写的。是因为 26 年的性能分析找到了每一个瓶颈。
- 零拷贝页缓存:直接返回内存指针,不复制
- 预编译语句复用:编译一次,执行多次
- Schema cookie 检查:读一个整数,不重新解析整个 schema
fdatasync而不是fsync:只同步数据is_ipk检查:一行代码,让主键查询走 B-tree
这些细节不在文档里。它们在 26 年的 commit 历史里,因为真实用户遇到了真实的性能问题。
LLM 训练在文档和 Stack Overflow 上。它不知道这些细节。
你的代码是你的吗?
如果你用 LLM 写代码(2026 年大部分人都在用),问题不是代码能不能编译。
问题是:你能不能自己找到这个 bug?
提示找到所有 bug 并修复不会有用。这不是语法错误,是语义错误:错误的算法,错误的系统调用。
如果你提示生成了代码,但解释不了为什么它选择全表扫描而不是 B-tree 搜索,那这代码不是你的。
代码只有在你理解到能把它搞坏的程度时,才真正属于你。
结论
LLM 很有用。当使用者知道正确长什么样时,它能大幅提速。
但如果你不知道,你就不是在编程——你只是在生成 token,然后祈祷。
光靠感觉不够。定义什么是正确的,然后测量。