辨析:标准 SQLite 持久化统计表主要是sqlite_stat1;sqlite_stat4在启用
SQLITE_ENABLE_STAT4编译选项且运行 ANALYZE 时可能出现更细粒度样本。并无广泛意义上的sqlite_stat3作为通用第三张系统表——若文档仍写 stat3,多为笔误或其它系统;请以目标发行版的sqlite_master与官方 fileformat 文档为准。
1 ANALYZE 在干什么
- 扫描索引 B-Tree 叶节点,采样键分布,写入统计表;
ANALYZE全库;ANALYZE tbl针对相关对象;- 代价:大表上可能耗时与 I/O 显著,应在维护窗口或异步任务跑。
2 sqlite_stat1 结构直觉
存每个索引的近似摘要,供优化器估计等值命中行数、范围扫描行数。
可用(谨慎)查询:
SELECT*FROMsqlite_stat1LIMIT5;勿在生产手工乱改行,除非你做科研;正规路径是重新 ANALYZE。
3 sqlite_stat4(若可用)
提供更丰富样本,利于高相关列、倾斜分布;二进制构建未开 STAT4 时根本没有这张表。部署文档应写明是否启用 STAT4。
4 统计过期的典型性能症状
- 同样 SQL,升级数据量后延迟突然线性变差;
EXPLAIN QUERY PLAN从索引扫描退化为全表扫描;- 批量导入/大批量 DELETE 后未及时更新。
5 手动更新策略
| 场景 | 建议 |
|---|---|
| 日终批导 | 导入结束ANALYZE affected_tables |
| 周期任务 | 周/月全库ANALYZE(视体量) |
| 仅热点表 | ANALYZE hot_table缩短窗口 |
| 与迁移同发 | schema 变更 + 新索引后必 ANALYZE |
6 批量维护与自动化
- Shell/cron:
sqlite3 app.db "ANALYZE;" - 失败告警:不要把 ANALYZE 放在「静默脚本」里吞错误。
- PRAGMA optimize(若版本支持):可对需要分析的表做启发式维护——读官方说明再启用。
7 与 VACUUM 的关系
物理紧缩不自动等价于统计刷新;大维护后常见组合拳:VACUUM(按需)→ANALYZE。
8 开源仓库实践
- CI:生成测试库后
ANALYZE,让EQP 测试稳定。 - Release note:若统计格式变,提醒用户升级后跑一次 ANALYZE。
9 批量窗口与「analyze 本身变慢」时的拆表策略
大表全库ANALYZE若超过允许窗口,可改为按表排队:先对JOIN 最多的维度表、再事实表,每段记录开始/结束时间与行数快照。若夜间仍不够,考虑降低写入峰值(合并批处理)或读副本上 analyze 再决定是否主库执行(谨慎:副本统计不一定等同于主库,仅作近似)。嵌入式设备可把 ANALYZE 绑在充电+Wi‑Fi场景,避免用户前台卡顿。
10 与查询计划的反馈闭环
建议在应用侧对TOP N 慢 SQL自动归档「上次 ANALYZE 时间戳」;若慢查询在大批量导入后集中爆发,告警优先级应高于「CPU 飙高」。统计维护本质是让优化器与数据分布再对齐,而不是运维日历上的装饰品。
11 与「只读副本」统计的边界
若你在工程上维护主从文件拷贝(非 SQLite 内置复制),在副本上ANALYZE得到的统计仅对副本有效;主库若继续大量写入,把统计文件抄回主库是错误操作。正确做法仍是在主库低峰或业务可接受窗口执行,或接受基于主库采样的在线估算(若自研统计中间件)。
总结
统计是优化器的眼睛;过期则计划瞎。把 ANALYZE 纳入数据生命周期(导入后、删改后、索引变更后),比事后集体救火便宜。