8.2 诊断工具箱


8.2 诊断工具箱:CLI、完整性校验与性能剖析

本节摘要:SQLite 的诊断工具集中在一个命令行工具与一组 PRAGMA 里。本节给出一条完整的排障路径:从"感觉慢"出发,先查库健康(integrity_check 家族与空间统计),再查计划(EXPLAIN 与 .eqp),再查执行(.timer 与状态计数),最后对照 MySQL 与 PostgreSQL 的诊断入口,形成可复用的排障流程。

第一站:库健康检查

拿到任何"行为异常"的库,先跑完整性家族:

PRAGMA integrity_check; -- 全量校验:逐页核对 B-Tree 结构、单元格边界、索引一致性 PRAGMA quick_check; -- 快速版:跳过部分索引内容核对,大库先跑它 PRAGMA foreign_key_check; -- 外键违例清单(开了外键约束的库)

integrity_check 输出 ok 即健康;否则列出每个损坏页的报告。三个命令各有分工:怀疑断电损坏跑全量;日常巡检用 quick;数据"莫名消失"先查外键违例再看业务逻辑。空间健康是第二类体检:PRAGMA freelist_count 看空闲页数量——freelist 占比超过两三成说明删除频繁且从未 VACUUM,此时文件虚胖、扫描路径变长;PRAGMA page_count 加页大小算出实际占用;dbstat 虚表(第 2 章用过)能下钻到每张表每棵索引的页数分布,找出"谁占着空间"。

-- 空间体检组合 PRAGMA page_count; -- 总页数 PRAGMA freelist_count; -- 空闲页数,占比高即碎片化 SELECT name, SUM(pgsize)/1024 AS kb FROM dbstat GROUP BY name ORDER BY kb DESC LIMIT 10; -- 空间占用前十的对象

第二站:计划与执行验证

慢查询的标准流程在第 5、6 章已建立,这里收拢成 CLI 操作序列:

sqlite3 app.db .mode column .headers on .timer on -- 打开真实耗时 .eqp on -- 每条语句自动先显示查询计划 EXPLAIN QUERY PLAN SELECT ... ; -- 计划与行号 SELECT ... ; -- .timer 给出 real 时间 .stats on -- 语句级的缓存命中、排序溢出等计数

.stats on 的输出值得专门一课:它展示当前会话的页缓存命中与未命中次数、排序器使用情况、语句编译次数。把"慢"归因到这三类——缓存未命中多去查 7.1 的预算,编译次数多去查 7.3 的语句复用,排序溢出多去查 temp_store 与索引消除。对照另外两家的入口:MySQL 的 EXPLAIN ANALYZE(8.0 新增)给出真实执行行数,PostgreSQL 的 EXPLAIN (ANALYZE, BUFFERS) 直接报每节点的页命中与读盘——三库里只有 PG 能把"计划假设对不对"与"页从哪来"一次看全;SQLite 用 .stats 与 .timer 的组合近似补齐。

第三站:把证据链写进报告

一份合格的性能工单包含五件事,全部可用 SQLite 自身工具产出:

证据项 采集命令 看什么
库版本与配置 SELECT sqlite_version(); 加 PRAGMA 组合 版本差异可能就是问题本身
库健康 integrity_check 加 freelist_count 排除损坏与碎片
空间分布 dbstat 聚合 大表大索引是谁
计划 EXPLAIN QUERY PLAN SCAN 还是 SEARCH、有无 TEMP B-TREE
耗时分解 .timer 加 .stats 真实时间加缓存命中率

五项齐全后再谈改法——多数"SQLite 太慢"的工单走到第三站就真相大白:不是引擎慢,是 freelist 占了 40%、或查询在无索引的表上全扫、或循环里每次重新 prepare。

💡 关键直觉:诊断的本质是把"感觉"替换成"计数器"。SQLite 的计数器都是 PRAGMA 与状态查询的形态,随手可得;先采数再下结论的习惯,比任何单个工具都值钱。

与服务端诊断的对照

MySQL 的诊断体系重"服务视角":SHOW PROCESSLIST 看谁在跑、慢查询日志按时间阈值捕获、performance_schema 逐阶段计时。PostgreSQL 重"统计视角":pg_stat_statements 把每条语句的累计耗时与调用数排成榜、auto_explain 自动捕获慢计划。SQLite 没有"服务",自然没有这两类设施——它的对等物是应用内的 profiling:包一层 step 计时、定期采样 sqlite3_status。做混合架构的团队值得把三套诊断词汇做成对照表,故障时才知道每个系统该问哪个问题。

常见问题速答

**数据库多大需要"拆"?**SQLite 没有技术上的大小红线,数百 GB 的单库在官方邮件列表里屡见不鲜。真正该拆的信号是三个运维量:VACUUM 或备份的窗口超出可接受时长(线性于库大小);单文件达到所在文件系统或同步盘的规格边界;业务上数据天然按用户或租户分片(此时一租户一库反而更符合 SQLite 的形态)。相反,"库大了会慢"的说法要拆开看——B-Tree 层数只是对数增长,慢与不慢看索引与缓存,不看绝对大小。

**wal_checkpoint 返回的那行怎么解读?**四个数字依次是:忙标记(1 表示本次未能完成全部工作)、WAL 里的总页数、本次成功回写主文件的页数、检查点推进后整个文件可安全重用的页数。诊断口诀:第二列长期大于第四列说明 WAL 在堆积;忙列为 1 且第三列很小,去应用里找长命读事务。配合 4.3 节的四个病因清单,WAL 膨胀问题基本都能在五分钟内定位。

本节要点回顾

  • 健康检查三件套:integrity_check 排损坏、freelist_count 看碎片、dbstat 找空间大户。
  • 慢查询五站:版本配置、库健康、空间分布、计划、耗时分解;.stats 把慢归因到缓存、编译、排序三类。
  • PG 的 EXPLAIN ANALYZE BUFFERS 是三库中最完整的单命令证据源;SQLite 靠 CLI 组合近似。
  • 没有"服务"就没有服务级监控——SQLite 的性能基线要靠应用内采样自建。

**慢查询日志有对应物吗?**SQLite 没有内置的慢日志——没有服务进程就没有集中的观测点。替代方案在应用侧:给语句执行包一层计时钩子(C API 的 trace 机制或语言绑定的回调),超过阈值的语句连同计划快照落进应用日志;再配合定期抽样的 sqlite3_status 峰值数据。搭好后你会得到与慢查询日志等价的信息,且过滤维度完全自定义——这是没有服务层的自由,也是代价。

数据保住了、健康查清了,下一节处理最后一道防线:安全。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U