文章摘要
作者在Django项目中使用SQLite数据库,发现即使数据量不大,查询也可能很慢。通过实践认识到,运行ANALYZE命令对优化查询性能很重要,并开启了WAL模式。
文章总结
最近我在开发一个Django网站时选择了SQLite作为数据库。虽然很多博客都说SQLite完全适合小型网站的生产环境,但我逐渐意识到,数据库运维本身就很复杂,而我对此知之甚少。以下是我在运行SQLite过程中学到的一些经验。
ANALYZE的重要性
有一次我在一个4000行的表上执行全文搜索查询,竟然花了5秒钟。运行ANALYZE后,查询时间瞬间降至0.05秒。这个命令会生成统计信息(比如每张表的行数等),帮助查询优化器做出更好的决策。
数据库清理的挑战
当我需要清理大量不需要的数据行时,遇到了几个问题:清理命令执行时间超过5秒(可能因为事务中运行了Python代码),同时其他工作进程尝试写入数据库时会因超时而崩溃。我的解决方案是分批执行清理操作,避免单次查询超过5秒。这让我理解了为什么有人会选择支持并发写入的PostgreSQL。
ORM查询性能
目前我使用Django ORM进行各种查询,除了ANALYZE的问题外,整体表现尚可。数据库规模很小(约1万行),预计会保持这个规模。
备份策略
我尝试了两种备份方式:使用restic进行完整备份(有时会因内存不足被杀死),以及使用Litestream进行增量备份(配置保留400小时的历史记录)。两种方式都备份到AWS S3,但生成凭证的过程比较繁琐。
多数据库方案
在之前的项目中,我将表拆分到三个独立的数据库文件中,因为不需要所有表都在同一个数据库里。这个方案运行了4年,效果很好。
总的来说,从2022年首次在Web项目中使用SQLite到现在,我还在不断学习这些基础功能。预计未来一两年还会发现其他重要的特性。
评论总结
根据评论内容,主要围绕SQLite使用体验、备份策略、性能优化及数据库选择展开,观点如下:
1. SQLite备份与云存储方案
- 用户simonw分享AWS备份痛点,自建工具生成S3桶级凭证(uvx s3-credentials create my-existing-s3-bucket),并推荐Restic搭配Cloudflare R2。
- 用户andrewaylett提供高效备份脚本:使用.dump + zstd压缩,支持WAL模式下的非阻塞写入,压缩比达1.8GB→286MB。
2. SQLite查询优化与学习曲线
- 用户datadrivenangel调侃“学习读查询计划”的难度,引用XKCD漫画(链接)。
- 用户striking推荐SQLite的.expert模式自动推荐索引,并指出“小批量清理”策略同样适用于Postgres等“真实”数据库。
3. SQLite性能与适用场景 - 用户Kalanos强调SQLite仅适合本地系统,网络或高并发场景需Postgres。 - 用户noxer提供DELETE优化技巧:分批删除、延迟间隔、预加载rowid(SELECT不阻塞),并建议按数据存储顺序删除。
4. 工具与监控建议 - 用户ryan42推荐Django的silk/debug-toolbar自动报告性能问题。 - 用户pianopatrick建议用SQLite CLI替代Python代码执行清理操作。 - 用户arlattimore质疑ORM删除慢是否因逐条调用delete而非批量删除。
5. 其他讨论 - 用户masklinn解释SQLite统计视图(sqlite_stat1/4)对查询计划器的作用。 - 用户m0ose询问“dead man’s switch”在备份监控中的含义。