引言
SQLite 经常被当成“开发环境临时数据库”。其实它是一套完整的关系数据库:支持事务、索引、SQL、全文检索和 JSON,数据库本身就是一个文件,不需要单独启动服务。
如果应用是桌面软件、命令行工具、手机应用、单机服务、测试工具或边缘设备,SQLite 往往比“先部署一个数据库服务”更简单。它和 PostgreSQL for Everything 以及 SQLite for Everything 的共同启发是:先把系统数量降下来,再根据真实瓶颈扩展。
原文的语气是故意夸张的:SQLite 不会真的替代整个基础设施货架,但它能把全文检索、文档存储、缓存、向量索引、文件格式和一部分队列需求收进一个进程和一个文件里。
稳定可靠
SQLite 的代码、文件格式和兼容性经过了非常长时间的验证。它没有服务器进程,故障面更小;数据库文件可以在不同机器和平台之间移动,适合长期保存和离线使用。
SQLite 是公共领域软件,官方也以 2050 年为长期支持规划目标。项目还使用多套测试系统持续验证核心代码。对桌面应用、设备和本地工具来说,这些“无聊”的特性往往比新功能更重要。
易于运行、安装和扩展
SQLite 最容易运行,因为通常没有什么需要运行:应用链接库文件,打开数据库文件即可。它已经被大量操作系统、语言运行时和桌面软件内置,Python 甚至直接提供 sqlite3 标准库模块。
它的“扩展”方式也很直接:应用从内存数据库开始,需要持久化时换成文件,需要更多读并发时启用 WAL。真正达到单写者的吞吐上限后,再把数据放到 PostgreSQL 或 MySQL,而不是先为一个小工具部署完整服务栈。
简化 IT 架构
SQLite 的魅力不只是一个 RDBMS 文件。它还可以是应用文件格式、全文检索索引、文档存储、缓存、向量索引和小型任务队列。
SQLite 可以替代 Solr 和 Elastic:FTS5 全文检索
SQLite 的 FTS5 是数据库内的全文检索虚拟表:
CREATE VIRTUAL TABLE notes_search USING fts5(title, body);
INSERT INTO notes_search(rowid, title, body)
SELECT id, title, body FROM notes;
SELECT rowid, title
FROM notes_search
WHERE notes_search MATCH 'SQLite';
这里使用独立索引表,生产代码需要在同一个事务里同步新增、修改和删除的记录,也可以用触发器自动同步。对于本地文档、离线帮助、个人知识库和小型内容管理工具,这已经很实用。要做中文搜索时,应该先确认 tokenizer 和分词方案;“有全文索引”不等于“搜索体验自动达到搜索引擎水平”。
SQLite 可以替代 MongoDB:JSON 文档
SQLite 也提供 JSON 函数。JSON 在 SQLite 中仍然是 TEXT 或 BLOB,不是一个可以像 PostgreSQL jsonb 那样直接声明的独立列类型:
CREATE TABLE events (
id INTEGER PRIMARY KEY,
payload TEXT NOT NULL CHECK (json_valid(payload))
);
INSERT INTO events(payload)
VALUES ('{"type":"login","user_id":42}');
SELECT json_extract(payload, '$.user_id') AS user_id
FROM events
WHERE json_extract(payload, '$.type') = 'login';
固定且高频过滤的 JSON 字段,可以用生成列和普通索引优化:
CREATE INDEX events_event_type_idx
ON events (json_extract(payload, '$.type'));
SQLite 可以替代 Kafka 和 RabbitMQ:单机任务队列
SQLite 的队列模式可以很简单:在 BEGIN IMMEDIATE 事务中拿到最早的待处理任务,更新状态,再用 RETURNING 返回给 worker:
CREATE TABLE jobs (
id INTEGER PRIMARY KEY,
payload TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'pending',
started_at TEXT
);
BEGIN IMMEDIATE;
UPDATE jobs
SET status = 'running', started_at = CURRENT_TIMESTAMP
WHERE id = (
SELECT id FROM jobs
WHERE status = 'pending'
ORDER BY id
LIMIT 1
)
RETURNING *;
COMMIT;
同一条任务不会被两个 worker 同时领取。WAL 下,查看队列深度的读请求也不会挡住写入;但所有消费者最终会在 SQLite 的单写者上串行,写入达到每秒数万级时就该换队列系统。
SQLite 可以替代 ClickHouse:本地时序数据
设备、桌面应用和边缘采集器的时序数据可以按时间建索引,并按月或按设备分文件归档。数据和查询都在本机时,这种方案比为了几个指标部署 ClickHouse 更容易交付。跨机器持续写入和大规模聚合则不属于 SQLite 的舒适区。
SQLite 可以替代向量数据库:sqlite-vec
AI 工作流的小型向量索引可以通过 sqlite-vec 等扩展和业务数据一起保存。它适合本地 RAG、离线搜索和嵌入式应用;向量数量、召回并发或索引构建时间达到瓶颈后,再使用专用向量数据库。
SQLite 可以替代 Redis:内存或非持久缓存
SQLite 可以直接使用 :memory: 数据库,也可以使用 WAL 和合适的同步设置做本地缓存。原文给出了一个很有意思的数量级对比:热页缓存中的 SQLite 点查询大约是微秒级,而通过 localhost 访问 Redis 还要付出网络往返,通常是百微秒级。实际数字取决于硬件、驱动和查询,应该自己基准测试。
SQLite 可以替代文件系统:小型原始数据
SQLite 官方的 35% Faster Than The Filesystem 测试显示,小型 BLOB 放在 SQLite 中读写可能比单独文件更快,而且 10 KB 左右的文件使用的磁盘空间约少 20%。这不是所有硬件和文件大小都成立的定律;但对缩略图、附件、应用资源等小对象,数据库文件值得作为候选方案。
SQLite 可以替代图数据库:递归 CTE
树形数据可以用递归 CTE 查询,不必为目录、标签和依赖关系单独部署图数据库。需要复杂图遍历、图算法或高并发多方向关系查询时,再考虑专用图数据库。
SQLite 可以替代微服务
SQLite 在进程内运行,查询就是函数调用,不需要 localhost 网络请求。一个本地工具可以直接通过 SQL 生成结果,不必为了“前端调用后端、后端调用数据库”搭建一层只有转发逻辑的微服务。
当然,SQLite 不能替代真正的远程服务、认证边界和跨机器协调。这里的重点只是:本来就没有网络边界的应用,不要人为制造一层网络边界。
SQLite 不能替代 PlayStation 5
至于用 SQL 写游戏,这属于原文的玩笑。它证明了递归 CTE 和虚拟表很有表现力,但不建议拿 SQLite 运行下一代 3D 游戏。
结论
SQLite 适合“数据属于这个应用,应用和数据在同一台机器”的场景。它可以是正式产品的数据层,而不只是 demo 依赖。
最小方案通常就是:一个文件、事务、必要的索引、WAL、可验证的备份。只有在访问边界、写入并发或数据规模真的超过它之后,才把数据迁移到服务型数据库。