← 返回文章列表
FIG.03 — ARTICLE SHEET №01 · DOC.2026

SQLite 查询优化记录:从 800ms 到 30ms

一次导出功能变慢的排查过程,涉及索引、覆盖查询和避免函数包裹列。

本文目录 · 3 SECTIONS

一个数据导出任务在数据量涨到百万行后,单次查询从几十毫秒涨到八百多毫秒。排查下来不是 SQLite 不行,而是查询写法没有匹配索引。

慢在哪里

原始查询长这样:

SELECT * FROM events
WHERE strftime('%Y-%m', created_at) = '2026-03'
ORDER BY created_at DESC;

问题在于对 created_at 做了函数包裹,索引无法使用,只能全表扫描。

改成范围查询

把函数比较改成范围条件,让索引直接命中:

SELECT * FROM events
WHERE created_at >= '2026-03-01'
  AND created_at <  '2026-04-01'
ORDER BY created_at DESC;

这一步之后,查询时间降到了 120ms 左右。

再补一个覆盖索引

导出只需要 id、时间和状态,那就建一个只包含这些字段的索引:

CREATE INDEX idx_events_export
ON events(created_at DESC, status, id);

SQLite 可以直接从索引里读取字段,不用回表,最终稳定在 30ms 左右。

阶段耗时
原始查询约 800ms
范围查询约 120ms
覆盖索引约 30ms

排查工具是 EXPLAIN QUERY PLAN,先看扫描方式,再决定改 SQL 还是加索引,顺序不要反过来。

最后把结论写进规范:时间字段永远不要包在函数里比较,日期过滤一律用半开区间。