SQLite为什么总受质疑?它明明可以替代一切……
原创 JoeCode 2026-09-21 07:15 广东
但它能够胜任的场景,远比大多数人想象得要多,而且它往往已经预装在你的环境之中。
引言
SQLite的寿命比你现在运行的大多数系统都要长。
在我看来,SQLite的强大源于三点:
稳定可靠;
易于运行、安装和扩展(因为根本不需要运行任何东西);
它不止是一个关系型数据库,同时还是全文检索引擎、文档存储、缓存层、向量索引,甚至是一种应用文件格式,极大简化了整个技术栈。
一、稳定可靠
SQLite是一项平淡无奇的老技术,于2000年首次发布。但同时,它也是全球部署最广泛的数据库引擎,而且优势非常明显。你的手机、浏览器、汽车里有它,甚至你坐的飞机上也有它。SQLite的运行实例数量比其他所有数据库加起来还要多,这毫无悬念。
数据库系统要修复各种漏洞需要足够长的时间。SQLite不仅有足够的时间,而且还在持续改进当中。其测试套件在MC/DC标准(航空电子软件也采用该标准)下实现了100%的分支覆盖率,测试代码量大约是库代码量的500倍。官方承诺维护支持到2050年,这个时间跨度可能比你们公司的愿景规划还要长。
另外,SQLite属于公共领域,不是开源软件。没有许可证、贡献者协议、署名条款,背后也没有一个靠C轮融资撑起来、随时可能变卦的厂商。
没错,SQLite的确很老旧了,但它一直在默默地把各种现代功能加入进来:窗口函数、RETURNING、严格表、生成列、jsonb等等。每次发布都是小幅改进、充分测试,向后兼容。这对于数据库来说是最不起眼的,但也是最有价值的。
二、易于运行、安装和扩展
从某种意义上说,在本地安装SQLite很简单。它与所有主流Linux发行版捆绑在一起,也内置于Python、Ruby、PHP、Go、Rust、.NET、Android 和iOS等编程语言中。无论你是否需要,它现在就安装在你的设备上。
如果想在服务器上运行SQLite,其实它已经在跑了,因为这是操作系统自带的。
扩展这部分也有优势:
1)垂直拓展:SQLite一次往返只是一次函数调用,而非一次网络跳转,那么一台配备现代NVMe固态硬盘、128GB内存的机器,能够承载的流量会高得惊人。无需连接池,没有TLS握手,也不需要pgbouncer;耗时从毫秒级降至纳秒级。
2)复制和备份: Litestream持续将WAL日志流式备份到S3,LiteFS提供分布式读取能力。两者都是小巧的单二进制文件,非常简洁。
3)托管服务商:如果你实在需要控制面板的话,Turso、Cloudflare D1、rqlite等也提供带控制面板的SQLite。
这些特性使得SQLite成为目前部署最广泛的软件之一。对你而言,这意味着维护工作量更少,可以把更多时间用来为客户开发业务功能。
三、简化IT架构部署
SQLite在云端部署几乎零配置,因为它就是和应用程序放在一起的普通文件。它的优势还不止于此:SQLite可以替代一整套原本需要独立运维的系统组件。
四、替代Solr和Elastic:全文搜索
SQLite内置FTS5全文搜索引擎,该引擎直接集成在你已经链接使用的库文件当中。它支持分词器、前缀查询、短语查询、NEAR邻近检索、布尔运算符、基于BM25的自定义排序,以及用于结果展示的片段截取与高亮函数。
这里有两点值得关注:
第一,SQLite不存在数据同步问题,因为不需要额外部署一套独立系统。它的搜索索引与业务数据天然在同一个事务内完成更新,这一特性始终成立。你遇到过的每一次 “为什么搜索索引数据过期” 故障,根源都来自那些本就非必需的复杂架构。
第二,FTS5的查询速度往往会超出预期。Simon Willison开发的Datasette,就可以在一台低配虚拟机上,对数GB大小的SQLite文件执行分面全文检索,查询响应仅毫秒级别,而且完全零额外成本。
那FTS5能否支持多语言完整分析链路、跨40个节点的分布式分片?并不能。但现实中,你真的会用到40个节点吗?大概率也不会。
更多内容参见SQLite FTS5官方文档:https://sqlite.org/fts5.html
五、替代MongoDB:出色的JSON支持
SQLite对JSON的存储与查询提供了完善支持。JSON相关函数均为内置实现,-> 和 ->> 操作符行为符合开发人员的使用预期。从3.45版本开始,SQLite还提供了jsonb二进制存储格式,访问数据时无需反复重新解析 JSON 文本。
很多人忽略的一点:SQLite支持对JSON内部字段建立索引。你可以基于JSON路径创建生成列,再为该生成列建立索引,即便这个字段没有定义在表结构中,也能实现高速查询。一份文件,即可做到无结构写入、带索引读取。
所以它的优势是:兼具文档存储能力、ACID 事务特性;无需独立服务进程、不用配置副本集、无需分片配置、不需要mongod服务,磁盘上就是一个可以直接拷贝的文件。那么,MongoDB还有存在的必要吗?
六、替代Kafka和RabbitMQ:把SQLite用作消息队列
事件、队列和持久日志的重要性逐年提升。Kafka、RabbitMQ、SQS都可以实现这类能力,但维护这套系统十分繁琐,需要做大量定制化工作,还得招聘掌握对应技术栈的专人来运维。
好消息是:SQLite的一张数据表就足以胜任消息队列的工作。
BEGIN IMMEDIATE;UPDATE jobs SET status = 'running', worker = ?WHERE id = (SELECT id FROM jobs WHERE status = 'pending'ORDER BY id LIMIT 1)RETURNING *;COMMIT;
BEGIN IMMEDIATE提前获取写锁,RETURNING子句直接返回抢到的那一行数据,依靠事务机制,可以保证只有一个工作进程能获取这条任务。开启WAL模式后,读操作完全不会被阻塞,因此监控面板查询队列长度时,不会和业务工作进程产生争抢。
说一句实在的限制:SQLite只能单线程写入。它没有SKIP LOCKED语法,因为根本不存在可供跳过的锁。多个消费端会在写锁上串行执行;如果你的入队速率真的达到每秒数万条,性能瓶颈就会显现。
但要注意二者的本质差异。同样这套队列思路,如果用PostgreSQL实现,队列只是数据库里的一张普通表;而用SQLite实现时,这张队列表直接运行在应用进程内部。消息始终不会流出本机,不存在独立的消息代理服务,没有消费者组重平衡问题,也不会遇到 “为什么发布期间分区分配发生变动” 这类故障。
我的建议是:先用SQLite充当消息队列。当它性能确实跟不上的时候,你手上已经有真实业务指标作为依据,而不是凭感觉判断,这时再稳妥地迁移到Kafka。
七、替代Clickhouse:处理高吞吐时序数据
时序数据比较特殊:大量数据点高速写入,后续再做聚合、统计与预聚合计算。
SQLite所能提供的能力如下:
1)按文件做数据分区:按天、按周或者按租户,各自生成独立的数据库文件。归档数据直接用mv命令;清理历史旧数据直接执行rm删除文件,操作是常数时间,不需要执行vacuum整理。跨多文件查询时,通过ATTACH挂载多个库,再配合UNION ALL视图即可完成。这套方案看着简陋,实际效果却极其出色。
2)汇总表:可以通过触发器,或是复用写入原始数据的同一套业务逻辑,生成预聚合汇总表。反正就算用其他时序数据库,你终究还是要自己实现持续聚合的逻辑。
3)批量写入:一个事务中执行上万条插入语句,最终只触发一次fsync。普通硬件下,采用这种方式,SQLite每秒可以写入数十万行数据,整个链路不存在网络协议开销。
4)需要列式处理时:分析场景可以直接用DuckDB读取SQLite文件。DuckDB原生支持该文件格式。应用写入的同一份数据文件,无需ETL,就可以直接获得向量化OLAP分析能力。
那些专用时序数据库的能力确实十分强大。如果你每秒要摄入百万级数据点,那确实应当选用这类专业系统。但大多数口中提到 “时序数据” 的业务,实际每日也就几百万行数据;对于SSD上的一个文件来说,这不过是稀松平常的负载。
八、SQLite作为AI工作流的向量数据库
sqlite-vec是一个单文件、零依赖的扩展组件,能将SQLite变为向量数据库。它用C语言编写,凡是 SQLite 能够运行的环境它都可以工作,包括通过WASM在浏览器中运行,向量直接存储在普通数据表内。
这正是SQLite的优势所在:向量嵌入、原始文档、元数据以及全文索引全部保存在同一个文件当中。因此混合检索只是一次表连接操作,而非跨三套服务、三种完全不同一致性模型的分布式查询。你可以在单条SQL语句内,完成按租户、时间、关键词、向量相似度的组合过滤,并且全部在事务保障下执行。
另外,这一点更重要:整个RAG索引就是一个文件。你可以直接邮件发送它,可以打包进Docker镜像,也可以部署到离线的笔记本设备上。你不妨试试,托管式向量集群根本做不到这件事。
九、替代Redis:非持久化高性能缓存
缓存很重要。大多数应用都会选用Redis来存储会话信息和热点数据。按定义,缓存允许数据丢失,并可以从源头重新生成。
那为什么还要为此额外部署一套独立服务呢?SQLite提供了多种方案,你可以根据愿意牺牲多少持久化能力来做选择:
PRAGMA journal_mode = WAL;PRAGMA synchronous = OFF; -- it's a cache, live a little
你可以直接完全绕过磁盘存储,选用:memory:,或是设置指令PRAGMA temp_store=MEMORY;也可以使用file:cache?mode=memory&cache=shared,实现多连接之间共享同一份内存数据库实例。
过期淘汰逻辑只需增加一列过期时间字段,配合定时器执行DELETE ... WHERE expires_at < unixepoch()。Redis底层本质也是在做同样的事情,只不过它跑在远端,还需要你专门去研读它自带的淘汰策略。
最关键的一点:本地回环地址上执行一次Redis的GET读取操作,耗时大约在百微秒级别。而页面缓存已经预热的前提下,SQLite的单点查询耗时仅约1微秒。你移除这个依赖,性能非但不会下降,反而还会变得更快。毕竟,最快的网络调用,就是直接本地函数调用。
Redis本身是非常优秀的软件。但它是独立进程,意味着引入了一套独立的故障模式、单独的内存开销、额外的安全防护工作,同时也多了一项需要维护的组件。
十、替代文件系统:存储原始数据
很多人会觉得,从普通文件读取一小块二进制数据,理应比从数据库读取更快。事实并非如此。这不是个人观点,而是SQLite项目发布的基准测试结果,其标题直截了当:比文件系统快35%。
对于大约100KB以内的二进制大对象,SQLite的读写性能优于磁盘上零散独立文件,同时磁盘占用还能再减少约20%。究其原因:每读写一个独立文件,文件系统都要执行一次open()、close(),还要做目录遍历;而SQLite只需要复用一个已经打开的文件句柄,再做一次B‑树寻址即可。
同时你还免费获得:多二进制对象的原子更新、崩溃不会产生半写损坏数据、不存在文件名转义漏洞、不会遇到单个目录存放四百万条文件的性能灾难,也不会出现inode数量过多导致rsync备份耗时数小时的问题,备份操作也简单到只需要复制这一个数据库文件。
把数据存进BLOB字段,追求极致的话可以选用紧凑格式做序列化,在客户端完成反序列化。官方曾表示,SQLite目标就是做一个更好用的fopen(),这是正经的设计目标,并非一句玩笑。
十一、替代图数据库
在SQL中使用递归查询处理分层数据是可行的,但传统写法阅读、维护与调试都十分折磨。
SQLite支持递归公用表表达式(递归 CTE),官方相关文档也是该领域质量上乘的技术资料。闭包表、物化路径、邻接表这几种模型都可以良好运行。SQLite没有提供LTREE类型,因此物化路径需要用TEXT字段搭配GLOB索引实现。写法不够优雅,但性能大体相当。
如果要做真正的图业务,simple-graph扩展用几百行SQL就能在普通SQLite表实现属性图模型,支持节点、边与图遍历。
这里体现的通用原则比其他场景更加突出:你的图数据规模大概率只有一万个节点。一万个节点完全可以放进CPU的L3缓存。你并不需要Neo4j,你真正需要的只是建好索引,再泡一杯咖啡。
十二、替代微服务
当下绝大多数微服务无非就是:一个数据模型、一条查询、输出 JSON。
SQLite通过json_object() 和 json_group_array()就能将任何查询结果转为JSON,序列化这一层就此不复存在。
但SQLite的价值还不止于此,因为它运行在你的应用进程内部。微服务并不是被存储过程替代,而是被一次本地函数调用所取代。你无需部署独立服务,不用配置健康检查,不需要重试逻辑、熔断组件,也不必处理分布式链路追踪;P99延迟也不再被网络抖动所主导。
Datasette是这个思路的终极验证:指向一个SQLite文件,无需编写任何业务代码,就能直接获得JSON API、Web管理界面、分面检索以及插件生态。Litestream负责保障数据持久可靠。仅仅两个二进制程序加一个数据文件,就构成一套可投入生产的数据服务。
当然这套方案有利也有弊,但行业里确实存在不少服务,它们存在的意义仅仅是给数据库查询套上一层网络调用。
十三、替代PlayStation 5
SQLite官方文档里,就包含了一套用递归公用表表达式(CTE)实现的曼德博集合渲染器。它堂堂正正写在手册当中,仅仅是作为查询语法的示例,显得十分随性。
还有开发者完全依靠SQLite CTE,实现了康威生命游戏、数独求解器、迷宫生成器,甚至国际象棋引擎。有人还直接用一条SQL查询跑出了Doom的火焰特效。
听上去很疯狂,这类玩法大可不必当真。但一份官方文档里都能跑出分形图案的数据库,不得不让人佩服。
结论
以上列举并不详尽。SQLite是一款极具灵活性的软件,支持加载扩展。但凡你准备部署一套独立服务来解决的问题,大概率都能找到对应的扩展。
当然,SQLite 存在能力上限:仅支持单线程,只能运行在单台机器。当业务触及这个天花板时,再迁移到PostgreSQL就好。那会是值得庆贺的时刻,代表你的产品已经拥有足够多的用户。
在此之前,每当出现新的业务需求,不妨先问自己两个问题:SQLite难道不能直接搞定这件事吗?我们真的需要那些光鲜亮眼的新技术吗?
SQLite并非万能解药。但它能够胜任的场景,远比大多数人想象得要多,而且它往往已经预装在你的环境之中。
作者丨JoeCode 编译丨dbaplus社群
dbaplus社群欢迎广大技术人员投稿,投稿邮箱:editor@dbaplus.cn