SQLite 万能论:它凭什么把搜索、队列、缓存和向量库都收进一个文件
作者借回应《PostgreSQL for Everything》的机会,提出更极端的组合:SQLite 不是玩具,而是把 RDBMS、全文检索、文档存储、队列、时序数据、向量库和缓存合并成一个文件与一次函数调用。文章给出多个可直接照搬的做法:用 BEGIN IMMEDIATE 配合 RETURNING 把表当持久化队列;用 JSON 生成列索引无模式字段;用 sqlite-vec 让混合检索退化成同一个事务里的 JOIN;用 WAL 加 synchronous=OFF 把缓存延迟压到约 1 微秒,低于本地 Redis 的约 100 微秒。它也列出了诚实的边界:SQLite 只有单写者,几十万行/秒的写入和每秒百万点级的时序场景应另选专业系统。适合想减少基础设施组件、重新评估依赖边界的后端与基础设施工程师。
Dr. Raphael Bauer penned an excellent article (PostgreSQL for Everything) on the value of using PostgreSQL to power your enterprise. I’ve taken the liberty of correcting a couple of errors, mainly he should of chosen SQLite 😊 (this is mostly a joke, I ❤️ PostgreSQL, its great tech.)
Contrary to popular belief, the answer to everything is NOT 42. It’s SQLite. (Fine. It might also be sqlite3.)
Raphael Bauer 博士写了一篇很棒的文章(PostgreSQL for Everything),讲的是用 PostgreSQL 驱动企业级应用的价值。我冒昧帮他改几个错:他主要应该选 SQLite 😊(这大半是玩笑,我 ❤️ PostgreSQL,它是很棒的技术。)
与流行观点相反,万物的答案不是 42,而是 SQLite。(好吧,也可能就是 sqlite3。)
SQLite will outlive most of what you are running right now.
Back then the accepted wisdom was that SQLite was a toy. A file. Something you shipped inside a phone app so you didn’t have to write a config parser. Real applications got a real database with a real port number and a real daemon and a real 3am page.
In my humble opinion, the power of SQLite comes from three sources:
It is rock-solid and stable.
It is easy to run, install and scale. Mostly because there is nothing to run.
It massively simplifies your IT setup by being not only an RDBMS, but also a full-text search engine, a document store, a cache, a vector index, and a file format.
Let’s have a closer look.
SQLite 会比你现在运行的大多数东西都活得更久。
过去的主流看法是:SQLite 是个玩具。一个文件。你把它塞进手机 App,只是为了不写配置文件解析器。真正的应用要用真正的数据库——要有真正的端口号、真正的守护进程、真正的凌晨三点被叫醒。
以我浅见,SQLite 的力量来自三个方面:
它坚如磐石、稳定可靠。
它易于运行、安装和扩展。主要是因为根本没什么需要运行的东西。
它极大地简化了你的 IT 架构,因为它不只是关系型数据库,还是全文搜索引擎、文档存储、缓存、向量索引和文件格式。
我们逐条细看。
SQLite is boring old technology. First release: 2000. It is also, by a margin that isn’t close, the most widely deployed database engine on the planet. It’s in your phone. It’s in your browser. It’s in your car. It’s in the plane you flew here on. There are more running copies of SQLite than there are running copies of everything else combined, and it isn’t a contest.
Ironing out bugs in database systems takes time. SQLite had that time, and then kept going. The test suite has 100% branch coverage under MC/DC, the same standard used for avionics software. There is roughly 500 times more test code than library code. The project has a stated support commitment through the year 2050, which is a longer planning horizon than your company’s mission statement.
It’s also in the public domain. Not open source. Public domain. No license, no CLA, no attribution clause, no vendor with a Series C and a change of heart.
True, SQLite is old. But it keeps quietly shipping modern features: window functions, RETURNING, strict tables, generated columns, jsonb. Every release is a small, well-tested, backwards-compatible improvement, which is the least exciting and most valuable thing a database can be.
SQLite 是无聊的老技术。2000 年发布首个版本。它也是地球上部署最广泛的数据库引擎,而且领先优势大到没有悬念。它在你的手机里,在浏览器里,在车里,在你飞来这里的飞机上。正在运行的 SQLite 副本数量,比其余所有东西加在一起还要多,这根本不是一场竞争。
数据库系统里的 bug 需要时间才能磨平。SQLite 有那个时间,而且还在继续。它的测试套件在 MC/DC 标准下达到 100% 分支覆盖率,这也是航空电子软件采用的标准。测试代码大约是库代码的 500 倍。项目公开承诺支持到 2050 年,这个规划视野比你们公司的使命宣言还要长。
它还属于公有领域(public domain)。不是开源,是公有领域。没有许可证、没有 CLA、没有署名条款、没有拿了 C 轮融资然后变心的厂商。
没错,SQLite 很老。但它一直在悄悄发布现代特性:window functions、RETURNING、strict tables、generated columns、jsonb。每个版本都是一次小而完善、经过充分测试、向后兼容的改进——这是数据库能拥有的最不刺激、也最有价值的东西。
Installing SQLite locally is easy in the sense that you have already done it. It is bundled with every major Linux distribution, ships inside Python, Ruby, PHP, Go, Rust, .NET, Android and iOS, and is sitting on your Mac right now whether you asked for it or not.
Running tests against a database identical to production is not a Test containers problem here. It is :memory:. Your test suite spins up a fresh database in microseconds, per test, in parallel, with no Docker daemon and no port collisions. The thing you test against is the thing you ship, because it’s the same library compiled into the same binary.
If you want to run SQLite on a server: you already are. It came with the OS.
在本地安装 SQLite 很容易,因为你现在已经装好了。每个主流 Linux 发行版都捆绑了它,Python、Ruby、PHP、Go、Rust、.NET、Android 和 iOS 里都内置了它,而且你的 Mac 上现在就有,不管你愿不愿意。
针对与生产环境一致的数据库跑测试,在这里不是 Test containers 的问题,而是 :memory:。你的测试套件每个测试都能在几微秒内启动一个全新数据库,并行运行,没有 Docker 守护进程,没有端口冲突。你测试的东西就是你上线的东西,因为它是编译进同一个二进制里的同一个库。
如果你想在服务器上运行 SQLite:你早就在跑了。它是随操作系统来的。
Scaling is the part where people expect the article to get quiet, so let’s not:
Vertical: a modern NVMe drive and a machine with 128GB of RAM will serve a shocking amount of traffic when your database round trip is a function call instead of a network hop. No connection pool. No TLS handshake. No pgbouncer. Nanoseconds instead of milliseconds.
Replication and backup: Litestream streams your WAL to S3 continuously. LiteFS gives you distributed reads. Both are small, single-binary, and boring.
Hosted: Turso, Cloudflare D1, rqlite, and friends will happily sell you SQLite with a control panel if you miss having a control panel.
That makes SQLite one of the most widely supported pieces of software in existence. For you this means less maintenance and more time building features for clients.
扩展是大家以为这篇文章会开始低调的部分,所以我们偏不:
垂直扩展:现代 NVMe 硬盘加一台 128GB 内存的机器,当你的数据库往返只是一次函数调用而不是网络跳转时,它能扛住惊人的流量。没有连接池,没有 TLS 握手,没有 pgbouncer。纳秒取代毫秒。
复制与备份:Litestream 把你的 WAL 持续流式备份到 S3。LiteFS 提供分布式读。两者都是体积小、单一二进制、而且无聊。
托管:Turso、Cloudflare D1、rqlite 和同类产品会很高兴地卖给你一个带控制面板的 SQLite,如果你怀念控制面板的话。
这让 SQLite 成为现存支持面最广的软件之一。对你来说,这意味着更少的维护和更多给客户做功能的时间。
Running SQLite in the cloud is zero clicks, because it’s a file next to your application. But it gets better. SQLite can replace a whole shelf of systems you’d otherwise be running.
在云端运行 SQLite 是零点击,因为它就是你应用旁边的一个文件。但还能更好:SQLite 可以取代你本来要跑的一整排系统。
SQLite ships with FTS5, a full-text search engine built into the library you already have linked. Tokenizers, prefix queries, phrase queries, NEAR, boolean operators, custom ranking with BM25, and snippet/highlight functions for rendering results.
Two things worth appreciating here. First, there is no sync problem, because there is no second system. Your search index is updated in the same transaction as your data, by definition, forever. Every “why is the search index stale” incident you have ever had was caused by architecture you didn’t need.
Second, it’s fast in a way that surprises people. Simon Willison’s Datasette runs faceted full-text search over multi-gigabyte SQLite files and returns in milliseconds, on a small VM, for free.
Is FTS5 going to do multilingual analysis chains and distributed sharding across 40 nodes? No. Do you have 40 nodes? Also no.
More on the topic: SQLite FTS5 documentation
SQLite 自带 FTS5,这个全文搜索引擎已经内置在你已经链接的库里。支持分词器、前缀查询、短语查询、NEAR、布尔操作符、基于 BM25 的自定义排序,以及用于渲染结果的 snippet/highlight 函数。
有两点值得体会。第一,没有同步问题,因为根本不存在第二个系统。你的搜索索引和你的数据在同一个事务里更新,从定义上永远如此。你经历过的每一次“为什么搜索索引是旧的”事故,都是你本不需要的架构造成的。
第二,它快到让人意外。Simon Willison 的 Datasette 可以在一个小型虚拟机上免费对多 GB 的 SQLite 文件做分面全文搜索,返回结果只要几毫秒。
FTS5 能支持多语言分析链和 40 个节点的分布式分片吗?不能。你有 40 个节点吗?也没有。
更多内容:SQLite FTS5 文档
SQLite has excellent support for storing and querying JSON. The JSON functions are built in, -> and ->> operators work the way you’d hope, and since 3.45 there’s jsonb, a binary representation that skips the reparse on every access.
The part people miss: you can index into JSON. Create a generated column from a JSON path, index the generated column, and you have a fast lookup on a field that doesn’t exist in your schema. Schemaless writes, indexed reads, one file.
So the pitch is: document storage, ACID transactions, no separate server, no replica set, no sharding config, no mongod, and the thing on disk is a single file you can copy. Is there a need for MongoDB anymore? There was a good article about a large publication switching off Mongo. Notably, nobody has ever written the reverse article.
SQLite 对 JSON 的存储和查询支持非常出色。JSON 函数是内置的,-> 和 ->> 操作符用起来符合预期,从 3.45 起还有 jsonb,这是一种二进制表示,跳过了每次访问时的重新解析。
大家容易忽略的是:你可以对 JSON 建索引。从 JSON 路径创建一个 generated column,再给这个列建索引,你就获得了一个基于 schema 中本不存在字段的快速查找。无模式的写入,有索引的读取,还是一个文件。
所以卖点是:文档存储、ACID 事务、没有独立服务器、没有副本集、没有分片配置、没有 mongod,磁盘上是一个你可以直接复制的文件。还需要 MongoDB 吗?有篇好文章讲一家大型刊物弃用 Mongo。值得注意的是,从来没人写过反向的文章。
Events, queues and persistent logs matter more every year. Kafka, RabbitMQ and SQS all provide that. Maintaining them is annoying, bespoke, and requires a skillset you have to hire for.
Good news: a table works fine.
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 takes the write lock up front, RETURNING hands you the claimed row, and the transaction guarantees exactly one worker gets it. In WAL mode readers never block, so your dashboard querying queue depth doesn’t fight your workers.
事件、队列和持久化日志的重要性逐年上升。Kafka、RabbitMQ 和 SQS 都提供这些能力,但维护它们很烦,是定制活,而且需要你专门去招的技能。
好消息是:一张表就够了。
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 把认领到的行交给你,事务保证只有一个 worker 能拿到它。在 WAL 模式下读不会被阻塞,所以你查看队列深度的仪表盘不会和 worker 打架。
Here is the honest caveat, because you deserve one: SQLite has a single writer. There is no SKIP LOCKED because there is nothing to skip. Concurrent consumers serialize on the write lock, and if your enqueue rate is genuinely in the tens of thousands per second, you will feel it.
But notice what happened. In the PostgreSQL version of this argument, the queue is a table in your database. In this version, the queue is a table in your database that is also in your application process. The message never leaves the machine. There is no broker, no consumer group rebalance, no “why did the partition assignment change during deploy.”
My tip: start with SQLite as your queue. When it stops performing, you will have real numbers instead of a vibe, and you can go buy Kafka with confidence. You’ll be surprised how long that takes.
这里有个诚实的提醒,因为你值得一个:SQLite 只有一个写者。没有 SKIP LOCKED,因为没什么可跳过的。并发消费者会在写锁上排队,如果你的入队速率真的达到每秒几万条,你会感觉到瓶颈。
但注意发生了什么。在 PostgreSQL 的论证版本里,队列是数据库里的一张表。在这个版本里,队列是数据库里的一张表,而且这个数据库同时也在你的应用进程里。消息从不离开这台机器。没有 broker,没有消费者组重平衡,没有“为什么部署时分区分配变了”。
我的建议:先用 SQLite 当队列。当它撑不住的时候,你手里会有真实数据而不是感觉,到时你可以放心去买 Kafka。你会惊讶这一步能撑多久。
Time series data is special. Lots of points arriving fast, then aggregation, statistics, rollups.
There is no TimescaleDB here, so let’s be straight about it. What SQLite gives you instead:
Partitioning by file. One database per day, week or tenant. Archiving is mv. Deleting old data is rm, which runs in constant time and doesn’t vacuum. Querying across them is ATTACH plus a UNION ALL view. This is crude and it is also extremely effective.
Rollup tables written by trigger or by the same code path that does the insert. You were going to build continuous aggregates anyway.
Batched writes. One transaction, ten thousand inserts, one fsync. SQLite will do several hundred thousand rows per second this way on ordinary hardware, because there’s no network protocol in the path.
Column-oriented when you need it. For the analytical half, point DuckDB at your SQLite file directly. It reads it natively. You get vectorized OLAP over the same file your app writes to, no ETL.
The specialized systems are genuinely amazing and if you are ingesting a million points a second you should go use one. Most people saying “time series” mean a few million rows a day, which is a Tuesday for a file on an SSD.
时序数据很特别:大量数据点快速到达,然后要做聚合、统计、rollup。
这里没有 TimescaleDB,所以直说。SQLite 给你的是:
按文件分区。每天、每周或每个租户一个数据库。归档就是 mv。删除旧数据就是 rm,常数时间而且不需要 vacuum。跨库查询就是 ATTACH 加 UNION ALL 视图。这很粗糙,也非常有效。
Rollup 表用触发器或插入的同一段代码路径来写。反正你本来也要建连续聚合。
批量写入。一个事务,一万次插入,一次 fsync。SQLite 用这种方式在普通硬件上每秒可以写几十万行,因为路径上没有网络协议。
需要列存的时候。分析那一半,直接把 DuckDB 指向你的 SQLite 文件。它能原生读取。你在应用写入的同一个文件上做向量化 OLAP,不需要 ETL。
专用系统确实了不起,如果你每秒摄入一百万点,你该去用。但多数人说“时序数据”时,意思是一天几百万行,这对 SSD 上的一个文件来说不过是小菜一碟。
sqlite-vec is a single-file, dependency-free extension that turns SQLite into a vector database. It’s written in C, runs anywhere SQLite runs, including the browser via WASM, and stores vectors in ordinary tables.
This is the part where SQLite has an unfair advantage. Your embeddings, your source documents, your metadata and your full-text index are in the same file, so hybrid search is a join, not a distributed query across three services with three different consistency models. Filter by tenant and date and keyword and vector similarity, in one statement, transactionally.
Also, and this matters more than it sounds: your entire RAG index is a file. You can email it. You can put it in a Docker image. You can ship it to a laptop that’s offline. Try that with your managed vector cluster.
sqlite-vec 是一个单文件、零依赖的扩展,把 SQLite 变成向量数据库。它用 C 编写,能跑在 SQLite 能跑的任何地方,包括通过 WASM 跑在浏览器里,向量就存在普通表里。
这是 SQLite 拥有不公平优势的地方。你的 embedding、源文档、元数据和全文索引都在同一个文件里,所以混合搜索是一个 join,而不是跨三个一致性模型不同的服务的分布式查询。按租户、日期、关键词和向量相似度过滤,放在一条语句里,事务性地完成。
另外,这一点比听起来更重要:你整个 RAG 索引就是一个文件。你可以用邮件发出去,可以塞进 Docker 镜像,可以送到一台离线笔记本上。你试试对你的托管向量集群做同样的事。
Caching is important. Most applications reach for Redis to hold sessions and hot data. A cache is by definition allowed to lose data and be regenerated from source.
So why run a second server for that? SQLite gives you several options depending on how much durability you want to trade away:
PRAGMA journal_mode = WAL; PRAGMA synchronous = OFF; -- it's a cache, live a little
Or skip the disk entirely with :memory:, or PRAGMA temp_store = MEMORY, or an in-memory database shared across your connections via file:cache?mode=memory&cache=shared.
Expiry is a column and a DELETE ... WHERE expires_at < unixepoch() on a timer, which is what Redis is doing for you anyway, just further away and with its own eviction policy you had to go read about.
And here’s the kicker: a Redis GET over localhost is on the order of 100 microseconds. A SQLite point lookup against a warm page cache is on the order of 1 microsecond. You did not remove a dependency to be slower. You removed a dependency and got faster, because the fastest network call is the one that’s a function call.
Redis is excellent software. It is also a separate process, a separate failure mode, a separate memory budget, a separate thing to secure, and a separate line item.
缓存很重要。大多数应用用 Redis 存 session 和热点数据。缓存按定义允许丢数据,可以从源头重新生成。
那为什么要为这个再跑一台服务器?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 在 localhost 上的 GET 大约 100 微秒。SQLite 命中暖页缓存的一次点查大约 1 微秒。你不是去掉一个依赖后变慢,你是去掉依赖后变快了,因为最快的网络调用就是一次函数调用。
Redis 是卓越的软件。但它也是一个独立进程、一种独立故障模式、一份独立内存预算、一个需要单独保护的东西、以及预算里的独立一行。
You would think reading a small blob from a file is faster than reading it from a database. It is not, and this is not an opinion, it’s a benchmark the SQLite project published and titled with admirable directness: 35% Faster Than The Filesystem.
For blobs under roughly 100KB, SQLite reads and writes faster than individual files on disk, and uses about 20% less space on top of it. The reason is that the file system charges you an open() and a close() and a directory traversal per item, while SQLite charges you one already-open file handle and a B-tree seek.
You also get, for free: atomic multi-blob updates, no partial writes on crash, no filename escaping bugs, no “what happens when a directory has 4 million entries,” no rsync taking six hours because of inode count, and a backup story that is one file.
Store the payload in a BLOB column, serialize with something compact if you’re feeling fancy, deserialize on the client. The SQLite team themselves suggest that SQLite is a better fopen(), and they meant it as a design goal, not a joke.
你可能会认为从文件读小 blob 比从数据库读更快。其实不是,而且这不是观点,是 SQLite 项目发布的一个基准测试,标题直白得令人敬佩:35% Faster Than The Filesystem。
对于大约 100KB 以下的 blob,SQLite 的读写比磁盘上的独立文件更快,而且空间还少用约 20%。原因是文件系统每个条目都要向你收一次 open()、close() 和目录遍历,而 SQLite 只收一个已经打开的文件句柄和一次 B-tree 查找。
你还免费得到:原子化的多 blob 更新、崩溃时不会出现部分写入、没有文件名转义 bug、没有“目录里有 400 万个条目会怎样”、没有 rsync 因为 inode 数量跑六个小时,以及一份备份就是一个文件。
把负载放在 BLOB 列里,讲究的话用某种紧凑格式序列化,客户端再反序列化。SQLite 团队自己都说,SQLite 是一个更好的 fopen(),而且他们这是设计目标,不是玩笑。
Hierarchical data in SQL via recursive queries is doable but historically painful to read, maintain and debug.
SQLite has full recursive CTE support, and its documentation on the subject is genuinely one of the better pieces of technical writing in the field. Closure tables, materialized paths and adjacency lists all work well. There’s no LTREE, so materialized paths are a TEXT column plus a GLOB index, which is less elegant and roughly as fast.
For real graph work, simple-graph implements a property graph on top of plain SQLite tables in a few hundred lines of SQL. Nodes, edges, traversal.
The general principle applies here more than anywhere: your graph is probably ten thousand nodes. Ten thousand nodes fits in L3 cache. You do not need Neo4j. You need an index and a coffee.
用 SQL 递归查询表达层级数据是可行的,但历史上读起来、维护和调试都很痛苦。
SQLite 完整支持递归 CTE,而且它在这方面的文档确实堪称该领域最好的技术写作之一。闭包表、物化路径和邻接表都工作得很好。没有 LTREE,所以物化路径就是 TEXT 列加 GLOB 索引,不够优雅但速度差不多。
真正的图工作负载上,simple-graph 用几百行 SQL 在普通 SQLite 表之上实现了一个属性图。节点、边、遍历。
通用原则在这里比任何地方都适用:你的图大概只有一万个节点。一万个节点能放进 L3 缓存。你不需要 Neo4j,你需要一个索引和一杯咖啡。
Most “microservices” today are: a model, a query, and JSON out.
SQLite turns any query into JSON with json_object() and json_group_array(). That’s your serialization layer, gone.
But SQLite goes further than the original argument does, because SQLite runs inside your process. The microservice isn’t replaced by a stored procedure, it’s replaced by a function call. There is no service to deploy, no health check, no retry logic, no circuit breaker, no distributed trace to correlate, and no p99 dominated by network jitter.
Datasette is the proof of concept taken to its conclusion: point it at a SQLite file and you get a JSON API, a web UI, faceted search and a plugin ecosystem, with no code. Litestream handles the durability. That’s a production data service in two binaries and a file.
There are pros and cons and I am not going to pretend the cons are zero. But the number of services in this industry that exist purely to put a network hop in front of a query is not small.
现在大多数“微服务”就是:一个模型、一个查询、JSON 输出。
SQLite 用 json_object() 和 json_group_array() 把任意查询变成 JSON。你的序列化层,没了。
但 SQLite 比原来的论证走得更远,因为 SQLite 跑在你的进程里。微服务不是被存储过程替代,而是被函数调用替代。没有需要部署的服务,没有健康检查,没有重试逻辑,没有熔断器,没有需要关联的分布式追踪,也没有被网络抖动支配的 p99。
Datasette 就是把这个概念验证走到极致:指向一个 SQLite 文件,你就能得到一个 JSON API、一个 Web UI、分面搜索和插件生态,不用写代码。Litestream 搞定持久性。这就是一个用两个二进制加一个文件组成的生产级数据服务。
有优点也有缺点,我不会假装缺点为零。但这个行业里纯粹为了给查询前面加一次网络跳转而存在的服务,数量不少。
The SQLite documentation itself includes a Mandelbrot set renderer written as a recursive common table expression. In the manual. As an example of the query syntax. Casually.
People have also implemented Conway’s Game of Life, sudoku solvers, and maze generators in pure SQLite CTEs. There’s a chess engine. Someone got Doom’s fire effect running in a query.
Crazy. Probably not to be taken too seriously. But you have to respect a database whose official docs contain fractals.
SQLite 官方文档里就有一个用递归 CTE 写的 Mandelbrot 集渲染器。在手册里。作为查询语法的示例。就这么随意。
还有人用纯 SQLite CTE 实现了 Conway 生命游戏、数独求解器和迷宫生成器。还有个国际象棋引擎。有人让 Doom 的火焰效果跑在一条查询里。
疯狂。大概不该太当真。但一个官方文档里包含分形的数据库,你必须得服气。
The list above is not exhaustive. SQLite is a remarkably flexible piece of software, it loads extensions, and there is very likely one for whatever you’re about to go install a server for.
Here’s the thing the original argument gets right and SQLite gets righter: simplicity is what lets you move fast. Every system in your stack is a thing to deploy, monitor, secure, upgrade, back up, pay for, and explain to the new hire. PostgreSQL cuts that list down. SQLite cuts it to zero, because the database isn’t a system, it’s a file and a function call.
Yes, there is a ceiling. One writer, one machine. When you hit it you’ll know, and you’ll go get PostgreSQL, and that will be a good day because it means people are using your thing.
Until then, when the next requirement shows up, ask: can’t SQLite just do this? And do we really need that shiny new technology X?
SQLite might not be the answer to everything. But it is the answer to a lot more than you might think, and it is already installed.
上面的清单并不详尽。SQLite 是一个非常灵活的软件,它能加载扩展,而且很可能你要去装服务器的任何需求,都已经有一个扩展了。
原文章说得对、而 SQLite 说得更对的一点是:简单才能让你快速前进。你架构里的每个系统都是一件要部署、监控、加固、升级、备份、付费、还要向新同事解释的东西。PostgreSQL 把这串清单缩短了。SQLite 直接砍到零,因为数据库不是一个系统,它就是一个文件和一次函数调用。
是的,有天花板。一个写者,一台机器。等你撞到它的时候你会知道,然后你会去用 PostgreSQL,那会是美好的一天,因为那意味着有人在用你的东西。
在那之前,当下一个需求出现时,问一句:SQLite 能不能直接做?我们真的需要那个闪亮的新技术 X 吗?
SQLite 可能不是万物的答案。但它能回答的问题,比你想象的多得多,而且它已经装好了。