导航菜单

SQLite 的局限性

问题引入

用户认证系统上线后,我的数据开始快速增长:

当前数据量:
- 用户表:200 条
- 调用日志:每天 5 万条

预计增长:
- 1 个月后:日志 150 万条
- 6 个月后:日志 900 万条
- 1 年后:日志 1800 万条

我开始担心:SQLite 还能撑多久?

那时候的我还不清楚,这个问题会引出多大的变革。

SQLite 的特点

SQLite 是一款轻量级嵌入式数据库:

  • 零配置:无需安装,开箱即用
  • 单文件存储:整个数据库是一个文件
  • 自包含:不需要独立的服务器进程
  • 跨平台:支持所有主流操作系统

适合场景:

  • 移动应用(iOS/Android)
  • 桌面应用本地存储
  • 小型网站/原型开发
  • 物联网设备

我用 SQLite 起家,它陪伴了我的创业初期。但当数据量增长时,问题开始暴露。

问题 1:性能下降

随着数据量增长,我发现查询越来越慢:

# 这个查询越来越慢
db.execute(
    '''SELECT COUNT(*) FROM api_logs
       WHERE user_id = ? AND DATE(created_at) = ?'''
)

原因分析:

问题说明
全表扫描没有索引,每次查询扫描全部数据
B-Tree 退化数据量过大时,B-Tree 高度增加,查找变慢
单线程查询查询无法并行执行

实测数据:

数据量查询耗时
1 万条5ms
10 万条50ms
100 万条500ms
1000 万条5000ms

从 5ms 到 5000ms,整整 1000 倍的差距。我知道,不能再拖了。

问题 2:并发限制

SQLite 对并发写入的支持有限:

锁机制

SQLite 使用数据库级锁

┌─────────────────────────────────────┐
│  SQLite 数据库                       │
│  ┌─────────────────────────────┐   │
│  │  写锁 (独占)                 │   │
│  │  ┌─────────────────────┐   │   │
│  │  │  读锁 (共享)         │   │   │
│  │  └─────────────────────┘   │   │
│  └─────────────────────────────┘   │
└─────────────────────────────────────┘
  • 同一时间只能一个写入:写操作需要独占锁
  • 多个读取可以并发:读操作共享锁
  • 写入时读取阻塞:写锁会阻塞所有读操作

并发性能测试

并发用户数    SQLite QPS    MySQL QPS
─────────────────────────────────────
1             1000          1200
10            500           8000
50            100           35000
100           50            60000

结论:

  • SQLite 在并发场景下性能急剧下降
  • MySQL 可以线性扩展

从 1000 QPS 跌到 50 QPS,而 MySQL 能从 1200 涨到 60000。这个对比让我下定决心。

问题 3:备份困难

SQLite 是单文件存储:

备份方式

# 方式 1:直接复制文件(不推荐)
cp database.db backup.db

# 方式 2:使用 .backup 命令(推荐)
sqlite3 database.db ".backup 'backup.db'"

# 方式 3:使用 VACUUM INTO
sqlite3 database.db "VACUUM INTO 'backup.db'"

备份挑战

问题说明影响
文件锁定备份时需要获取读锁写入操作被阻塞
文件增大数据越多文件越大备份时间变长
恢复困难需要替换整个文件服务需要暂停
增量备份不支持原生增量备份每次备份全部数据

备份时间估算

数据量    文件大小    备份时间
────────────────────────────────
100MB     100MB      ~1 秒
1GB       1GB        ~10 秒
10GB      10GB       ~100 秒
100GB     100GB      ~1000 秒 (16 分钟)

问题:

  • 备份时间窗口越来越长
  • 备份期间性能下降
  • 恢复时需要停服

想象一下,如果数据库有 100GB,备份一次要 16 分钟。这期间系统几乎不可用。我不敢想。

何时需要迁移?

当出现以下信号时,考虑迁移到更强大的数据库:

性能信号

  • 查询响应时间超过 1 秒
  • 写入吞吐量持续低于需求
  • 索引优化后仍然缓慢

并发信号

  • 并发用户超过 50
  • 频繁的锁等待超时
  • 写入队列越来越长

业务信号

  • 需要 7x24 小时高可用
  • 数据量预计超过 100GB
  • 需要主从复制/读写分离

我的情况呢?三个信号都中了。

本节小结

✅ SQLite 的优点:

  • 零配置,易于部署
  • 轻量级,资源占用少
  • 适合小型应用和原型开发

⚠️ SQLite 的局限:

  • 并发写入能力弱
  • 大数据量性能下降
  • 备份和恢复不够灵活

🎯 下一步

既然 SQLite 无法满足需求,我得看看有哪些替代方案。

那一夜,我开始了数据库选型的调研。

搜索