← 返回信息流
AI 资讯Hacker News·2 小时前

学习运行SQLite的几个关键技巧

原标题:Learning a few things about running SQLite

速览

本文总结了运行SQLite时需要注意的几个关键方面,包括配置细节、性能优化和最佳实践。这些技巧有助于开发者更高效地使用SQLite,避免常见陷阱,提升应用稳定性。对于需要轻量级数据库支持的项目,本文提供了实用指导。

AI 深度解读

背景

原文作者是一位正在使用 Django 构建网站的开发者,他选择 SQLite 作为数据库。尽管之前读过不少博客,认为 SQLite 在小站点生产环境中完全可行,但他逐渐意识到:SQLite 依然是一个数据库,数据库操作本身很复杂,而他对数据库运维知之甚少。这是作者第四次使用 SQLite 做网站,但这次因为 Django ORM 的强大能力,他让数据库承担了更多工作,因此遇到了不少新问题。

核心内容

作者分享了自己在运行 SQLite 过程中学到的一些小经验。

1. ANALYZE 的重要性

作者在对一个仅有 4000 行的表执行全文搜索查询(使用 SQLite 的 FTS5)时,查询耗时长达 5 秒。这显然不合理。他发现问题在于没有运行 ANALYZE 命令。运行 ANALYZE 后,该查询立即从 5 秒缩短到约 0.05 秒(甚至更小,小到作者不再关心)。ANALYZE 会生成关于每张表行数等统计信息,帮助查询优化器做出更好的选择。作者推测,未运行 ANALYZE 时可能发生了某种意外的二次复杂度问题。

2. 清理数据库很棘手

作者有时会误插入大量不需要的行(例如来自 django-tasks-db 的已完成任务),需要清理。他遇到了几次这样的情况:

  • 运行清理命令(比如 DELETE 大量行),命令执行超过 5 秒。
  • 在此期间,其他工作进程尝试写入数据库,但由于设置了 5 秒超时,写入失败。
  • 工作进程崩溃,导致 VM 关闭。

作者目前的做法是分批小量清理,避免单次数据库操作超过 5 秒。这让他理解了为什么有些人会使用像 Postgres 这样支持多个写操作同时进行的“真正的”数据库。未来他可能会考虑在需要这类操作时暂停网站进行计划维护。

3. ORM 查询的性能目前还不错

作者一直使用 Django ORM 进行查询,几乎不关心查询性能,除了 ANALYZE 那个问题外,大部分情况都运行正常。数据库目前很小(约 10000 行),预计会一直保持较小规模,因此他希望这种策略能持续有效。

4. 备份 SQLite 的两种方式

作者尝试了两种备份方法:

方式一:restic

sqlite3 /data/calendar.db "VACUUM INTO '/tmp/calendar.sqlite'"
gzip /tmp/calendar.sqlite
# 上传备份到 S3
# 有时备份进程被 OOM 杀死导致数据库锁住,需要解锁
restic -r s3://s3.amazonaws.com/some_bucket/ unlock
restic -r s3://s3.amazonaws.com/some_bucket/ backup /tmp/calendar.sqlite.gz
restic -r s3://s3.amazonaws.com/some_bucket/ snapshots
restic -r s3://s3.amazonaws.com/some_bucket/ forget -l 1 -H 6 -d 2 -w 2 -m 2 -y 2
restic -r s3://s3.amazonaws.com/some_bucket/ prune

方式二:Litestream 作者最近开始尝试 Litestream,因为觉得增量备份可能更高效(restic 备份有时被 OOM 杀死)。配置一个配置文件后运行:

litestream replicate -config litestream.yml

他在配置文件中设置了 retention: 400h 来保留一定历史,但不确定是否有效。备份目标是 AWS S3,但作者抱怨 AWS 控制台生成凭证很麻烦,未来可能迁移到其他 S3 兼容存储。

5. 可以使用多个数据库

当前项目只有一个数据库,但作者之前在 Mess with DNS 项目中用过一个小技巧:将表拆分到三个独立的数据库文件中,因为不需要所有表都在同一个数据库里。这很有帮助。Mess with DNS 从 2022 年至今一直运行在 SQLite 上,效果很好,作者认为从 Postgres 迁移到 SQLite 是一个很棒的选择。

6. 后记

作者觉得学习所使用技术的基本知识总是很有趣。他第一次在 Web 项目中使用 SQLite 是 2022 年,而今天才知道 ANALYZE 的存在。他想象一两年后还会学到其他一些非常基础的特性。

关键要点

  • 运行 ANALYZE 至关重要:即使在小型数据库上,缺失统计信息也可能导致查询计划极差,查询时间从 5 秒降到 0.05 秒。
  • 清理大量行时要小心并发:长时间运行的 DELETE 语句可能会阻塞其他写操作,导致超时和崩溃。分批小量操作是可行的临时方案。
  • Django ORM 在小规模下表现良好:作者目前没有遇到性能瓶颈,但未来若数据增长可能需要关注。
  • 备份方法选择VACUUM INTO + restic 是简单方案,但可能被 OOM 杀死;Litestream 提供增量备份,配置更简单,但需要处理 AWS 凭证的麻烦。
  • 多数据库文件是可行技巧:将不相关的表拆分到不同 SQLite 文件可以避免单点锁竞争,适合特定场景。
  • SQLite 适合小规模项目:作者在 Mess with DNS 项目中已运行 SQLite 4 年,效果良好,从 Postgres 迁移也是正确决定。

意义与影响

这篇文章以实际开发者的第一人称视角,揭示了 SQLite 在小型生产环境中的真实运维经验。它打破了“SQLite 简单到不需要维护”的误区,强调了数据库运维的基本操作(如 ANALYZE)和常见陷阱(如长时间写操作导致的阻塞)。对于正在考虑使用 SQLite 作为生产数据库的开发者,尤其是配合 Django ORM 的场景,本文提供了宝贵的实战参考。

同时,作者对比了备份策略(restic vs Litestream)和数据库文件拆分技巧,展示了在资源受限的小型项目中如何灵活应对数据库问题。文章也呼应了业界对 SQLite 适合“低并发、小数据量”场景的共识,并指出当需要多写并发时,Postgres 等传统数据库仍不可替代。整体而言,这是一篇诚实、接地气的运维笔记,能帮助更多开发者避免类似错误,并更理性地评估 SQLite 在项目中的适用性。

查看原文 →jvns.ca