软件选型 · 2026-07 整理

本地轻量数据库选型

SQLite 顶不住时的替代路线:瓶颈定位方法、嵌入式库与衍生复制层横评、两个典型负载的选型结论。

最近手头几个本地轻量服务(SQLite 打底)在并发小写入的场景下都开始喘。但这玩意是本地轻量服务,不能塞一堆重依赖,PG/MySQL 那一套直接 pass。借着给两个具体场景做选型的机会,我把市面上还能用的本地轻量方案摸了一遍,把结论和判断过程记下来,也算给你做决策时省点查资料的时间。

两个场景长这样:

  • 一个局域网 CMDB,监控 1 万多个 IoT 嵌入式服务的端口心跳,大约每 30 秒一跳,存 7 天用来展示。
  • 局域网里几十路摄像头,一直在录 30 秒一段的短视频,攒了 30~90 天的量要处理。

先说结论,后面再展开为什么。

先说结论

  1. 瓶颈大概率不是 SQLite 本身,是写法。 1 万设备 × 30 秒 = 平均才 333 次写入/秒,对批量写入的 SQLite 来说根本不算压力。绝大多数卡死都是因为每条心跳独立提交 + synchronous=FULL(每次提交都 fsync 到磁盘)+ 没开 WAL,再加上并发写互相抢锁。先开 WAL、单写协程攒批,往往零成本就能解决,不用动架构。
  2. 「单二进制」和「重依赖」是两回事。 VictoriaMetrics、QuestDB、MinIO、NATS 都只是一个静态可执行文件,往机器上丢一个 20~60MB 的 binary 就能跑,没有 initdb、没有服务账号、没有后台守护进程。这跟装 PostgreSQL/MySQL 完全不是一回事。所以第一步先想清楚:你能不能接受「多跑一个进程」。
  3. 场景一是时序负载,最对路的是时序库。 CMDB 心跳本质是时间序列 + 高频小写入 + 时间范围查询,VictoriaMetrics 单节点(vmsingle)最合适,前面接 NATS JetStream 做缓冲能彻底把生产者和存储解耦。
  4. 场景二是 Blob 问题,不是数据库问题。 30 秒一段的视频,几十路攒 90 天可能是 5~15 TB,这东西绝不能进库。用 MinIO(S3 对象存储)或者干脆哈希目录存文件系统,数据库只存元数据(路径、摄像头、时长、处理状态)。这种元数据写入速率极低,SQLite 管这个绰绰有余。

一句话:场景一 SQLite WAL 调优兜底、上量上 VictoriaMetrics(可选 NATS 缓冲);场景二 MinIO 存视频 + SQLite 存元数据。 全程不碰 PG/MySQL,轻量约束守住。

先别急着换库,看看瓶颈到底在哪

动手加任何组件之前,先确认瓶颈的性质。我见过太多「SQLite 并发瓶颈」其实都是下面这些能改的写法,不是 SQLite 的硬上限:

反模式实际发生了什么怎么改
每条心跳独立 autocommit每次提交都触发一次 fsync,磁盘 IOPS 成了天花板,几十 TPS 就卡死攒批:单写线程 + 队列,每 1000 条一个事务
journal_mode=DELETE + synchronous=FULL回滚日志 + 每事务刷盘,写写互斥,并发时疯狂 SQLITE_BUSY改 WAL + synchronous=NORMAL
多线程共用一个连接SQLite 连接不是线程安全的,串行化 + 锁竞争每线程/协程独立连接,或单写者模型
没设 busy_timeout一冲突就报错而不是重试,要么丢数据要么重试风暴PRAGMA busy_timeout=5000
万级设备全在 :00/:30 打点瞬时万级写入尖峰,单连接扛不住设备端加随机 jitter(±几秒)+ 服务端批量缓冲

说个我自己踩过的坑:SQLite 在 WAL 模式 + 批量事务下,单写者持续 5 万~10 万次插入/秒是能跑到的。你的场景平均才 333 次/秒,即便最坏情况下「万级尖峰」也只需在秒级内消化掉——这完全落在 SQLite 的能力圈里。所以我个人的建议是,换库前务必先做这一轮调优,大概率零成本解决。

调优清单就这几个 PRAGMA,连接建立后执行一次:

两个场景的负载画像(先算清楚账)

选型之前得先知道自己在扛多大的量,不然容易被厂商宣传带跑。

场景一:局域网 IoT 心跳监控(CMDB)

指标值
被监控的 IoT 服务数10,000+
平均心跳写入速率~333/s
7 天滚动窗口内行数~2.0 亿
列式压缩后存储2~4 GB(原始约 16GB)

算法:1 万服务 ×(每 30s 一次)= 333 次/秒;单日 1 万 × 2880(每天 30s 间隔数)= 2880 万行;7 天 ≈ 2.0 亿行。每行(设备ID + 时间戳 + 端口 + 状态 + 延迟)约 80 字节 → 原始约 16GB,时序库列存压缩后一般压到 2~4GB。

查询特征大致三类:① 每个服务「最新一次心跳」状态(last-value);② 时间范围趋势图(需要降采样);③ 7 天自动过期(retention)。

场景二:局域网摄像头短视频

指标值
单段视频时长30s
单摄像头 / 天 段数2,880
20 路 × 30 天 的片段数~5.2M
视频体量5~15 TB(看路数和天数)

这俩场景本质不一样,别混为一谈。场景一是「高频小写入 + 时间查询」,走时序库或批量 SQLite;场景二是「海量大文件 + 低频元数据」,走对象存储 + 轻量元数据库。把 30 秒视频塞进任何 SQL/NoSQL 的「值」里,结果都是数据库膨胀、备份灾难、查询变慢。视频进对象存储,数据库只管元数据,这是铁律。

产品全景

按「需不需要独立进程」分成两条主线。先泼盆冷水:几乎所有「嵌入式」方案本质仍是单写者,真要多个进程同时高频写,必须走单二进制服务或者更重的分布式层(而分布式层写也是串行的,只为高可用)。

A. 先优化 SQLite(零迁移)

  • SQLite(WAL 调优) —— 单写者 + WAL 并发读;单文件 .db,零依赖;场景一调优后够用,场景二元数据首选。先做这步,我估计 80% 的情况不用换库。

B. 嵌入式库(进程内)

  • LMDB —— MVCC:读永不阻塞写、写永不阻塞读;单写者,mmap 直读,读性能极强(OpenLDAP 同款)。适合读多写少、last-value 点查。Key-Value,没 SQL。
  • RocksDB —— LSM-Tree,为写入优化,单写者但写吞吐极高(Kafka/TiKV 底层同款思路)。适合进程内写洪流,但 C++ 依赖偏重、没 SQL。
  • bbolt(Go)/ sled(Rust) —— 单写 + 多读;如果你的服务本身是 Go / Rust 栈,直接引库最顺手。
  • DuckDB —— 单进程内可读写并发(无冲突的写,尤其 append,可以并行);多进程写入不支持。列式引擎,分析查询、降采样、报表极佳,不适合做高频并发写入的主存储。

C. SQLite 衍生 / 复制层

  • libSQL —— SQLite 的 fork,继承了单写者模型(官方明确:并发写入是 Turso 另一套 Rust 重写的数据库才解决)。新增了嵌入式副本、HTTP Server 远程访问。它不解决写并发瓶颈,只有当你需要「SQLite + 边缘副本 / 远程访问」时才值得换。别被「SQLite fork」这五个字骗去治并发。
  • rqlite / dqlite —— 通过 Raft 做复制与高可用;写入仍要经过 leader 串行化——提升的是可用性 / 读扩展,不是写吞吐。需要多机 HA/容灾时才上。
  • Litestream —— 后台进程把 SQLite 变更增量复制到文件 / S3,是容灾备份,不是并发方案。

D. 单二进制服务(sidecar)

  • VictoriaMetrics(vmsingle) —— 场景一首选。为时序写入高度优化,单节点就能吃下百万级 samples/s;列存压缩,7 天 retention 自动过期。一个静态二进制 ./victoria-metrics-prod,无外部依赖;兼容 InfluxDB / Prometheus / OpenTSDB / JSON 行协议。
  • QuestDB / InfluxDB v3 —— 同为单二进制时序库;QuestDB 用 SQL + InfluxDB 行协议、ingestion 极快;InfluxDB 生态成熟。场景一备选。
  • MinIO —— 场景二首选。自托管 S3 兼容对象存储,一个二进制起服务;为海量文件设计,支持生命周期过期(正好匹配 30~90 天留存)。视频文件的归宿,配合 SQLite/LMDB 存元数据。
  • NATS JetStream —— 单二进制消息系统,JetStream 提供持久化、at-least-once、重放。场景一的写入缓冲层(设备 → JetStream → 批量落库);也能做场景二「摄像头 → 存储 → 处理」的事件通知总线。

E. 更重(为什么不选)

  • ClickHouse —— 分析能力炸裂,但对你的规模偏重,且偏 OLAP 而非实时 ingestion;场景一若要做复杂聚合报表可备选。
  • TimescaleDB / PostgreSQL / MySQL —— 需要运行时 + 初始化 + 服务账号,违反「不能装太多依赖」的约束,列出来只是说明为什么 pass。

横向对比

评分用文字,避免看图说话:极高 / 高 / 中 / 可用 / 偏弱 / 不适用。

产品对比矩阵(可筛选)
形态
适配场景
产品类型并发模型部署 footprint场景一·心跳场景二·视频关键备注
SQLite(WAL 调优)嵌入式单写者 + WAL 并发读零依赖·单文件高极高先调优,多数情况够用
LMDB嵌入式 KVMVCC,读不阻塞写,单写单 C 库中极高读性能极强,写吞吐一般
RocksDB嵌入式 KVLSM,高写吞吐,单写C++ 库高中写洪流进程内首选
bbolt / sled嵌入式 KV单写 + 多读Go / Rust 库中高按技术栈选
DuckDB嵌入式 OLAP进程内并发写(append 无冲突),多进程只读单 C 库·零依赖中不适用分析查询强,非主存储
libSQLSQLite fork单写者(继承)嵌入式 + HTTP server中高加副本/远程,不改写并发
rqlite / dqlite分布式 SQLite写串行过 leader(HA)单二进制(Go)/ C 库可用中为高可用,非写吞吐
VictoriaMetrics单二进制 TSDB高并发写 + 列存压缩单个静态二进制极高不适用场景一首选
QuestDB / InfluxDB单二进制 TSDB高并发写单二进制极高不适用场景一备选
NATS JetStream单二进制 消息高吞吐 pub/sub + 持久单二进制高中做写入缓冲 / 事件总线
MinIO单二进制 对象存储高吞吐 blob单二进制不适用极高场景二视频归宿

决策树

照着走就行,不用硬记:

分场景推荐架构

场景一:IoT 心跳监控

设备心跳 → NATS JetStream(持久化、抗尖峰)→ 消费者批量写入 VictoriaMetrics(vmsingle,-retentionPeriod=7)→ 仪表盘用 MetricsQL 查。心跳写入走 InfluxDB 行协议:

不想引入 NATS 的话,可以简化成「设备直接批量写 VM」,或者退回「SQLite WAL 调优」兜底。我倾向于小流量先 SQLite 顶着,真看到瓶颈再上 VM,没必要一上来就铺。

场景二:摄像头短视频

摄像头写 30s 片段 → MinIO(S3,key 按 摄像头/日期/时间.mp4 组织,配生命周期规则自动删 30~90 天前的片段)→ 处理 Worker 拉视频做转码 / 识别 → 结果(缩略图、检测结果)回写 → SQLite 存元数据(路径、摄像头、时长、处理状态)。面板只查元数据,绝不扫视频本体。

落地配置示例

① SQLite WAL 调优(零成本兜底,两场景通用)

② VictoriaMetrics 单节点(场景一上量方案)

③ MinIO 对象存储(场景二视频归宿)

落地清单

  • 先量后换: 上线 WAL 调优,用真实流量压 24 小时,确认 QPS / 延迟达标再决定要不要引 sidecar。
  • 写入侧加缓冲: 不管选哪个库,入口都放一个内存队列 + 单写协程,把并发写变成串行批量写。
  • 设备端错峰: 心跳时间戳加 ±几秒随机 jitter,消掉 :00/:30 的万级尖峰。
  • 场景二绝不存视频进库: 视频只在 MinIO / 文件系统,库里只留 obj_key 字符串。

风险与权衡

老实说几个坑:

  • 嵌入式 ≠ 多写者。 LMDB / RocksDB / DuckDB / libSQL / bbolt 本质都是单写者。所谓「并发」多是「多读 + 单写」或「进程内无冲突并发」。如果你真需要多个独立进程同时高频写,纯嵌入路线无解,得上单二进制服务(VM/QuestDB)或分布式层(rqlite,但写仍串行)。
  • 单二进制也是要运维的。 VictoriaMetrics / MinIO 虽是一个文件,但仍是一个独立进程:要管启动、监控、磁盘、升级。好处是远比 PG/MySQL 轻——无运行时、无初始化、无账号体系。动手前先确认你的「不能装依赖」包不包含「可跑一个 sidecar」。
  • 视频体量要算账。 20 路 × 90 天 ≈ 5~15 TB。确认磁盘容量和生命周期过期策略(MinIO ILM 或脚本清理),否则存储会悄悄涨满。冷数据可以迁到更大但更慢的盘。
  • DuckDB 别当主库。 DuckDB 强在分析查询,多进程写入不支持。它适合做「SQLite/VM 存原始,DuckDB 做离线报表」,而不是 ingestion 主存储。

最后给个优先级:① 先 SQLite WAL 调优(零成本,两场景元数据都覆盖);② 场景一若上量,VictoriaMetrics(单二进制)+ 可选 NATS 缓冲;③ 场景二 MinIO + SQLite 元数据。全程不碰 PG/MySQL,轻量约束守住。

参考来源

  • [SQLite WAL 官方文档](https://www.sqlite.org/wal.html)
  • [libSQL GitHub](https://github.com/tursodatabase/libsql)
  • [VictoriaMetrics GitHub](https://github.com/VictoriaMetrics/VictoriaMetrics)
  • [DuckDB 并发模型](https://duckdb.org/docs/current/connect/concurrency)
  • [MinIO 官网](https://min.io/)
  • [NATS JetStream 文档](https://docs.nats.io/nats-concepts/jetstream)
  • [QuestDB 官网](https://questdb.io/)
  • [LMDB (Symas)](https://github.com/symas/lmdb)

*基于公开产品文档与社区实践整理(2026-07-08)。产品能力持续演进,落地前请以各项目最新官方文档为准。*

相关选购在淘宝查看「工控主机」的实时价格与现货去逛逛 →推广