SQLite 查询突然变慢时,先看 EXPLAIN QUERY PLAN

20 次浏览2 条回复

SQLite 里一个查询开始变慢,先别急着改 SQL,可以让它把执行计划打印出来:

EXPLAIN QUERY PLAN
SELECT id, created_at
FROM events
WHERE user_id = 42
ORDER BY created_at DESC;

看到 SCAN events 往往说明在扫全表;SEARCH ... USING INDEX 才是用了索引。加索引后要再看一次,ORDER BY 是否仍需临时排序也值得留意。

示例环境:SQLite 3.x,命令可在 sqlite3 CLI 或应用迁移脚本里执行;这是诊断语句,不会修改数据。

再补个容易漏看的点:SEARCH ... USING INDEX 不等于完全没有排序,最好一起看输出里有没有 USE TEMP B-TREE FOR ORDER BY。这个查询如果经常按 user_id 筛选、再按时间倒序取,可以试试 CREATE INDEX idx_events_user_created ON events(user_id, created_at DESC);,然后重新看执行计划。表很小时优化器选择全表扫也不一定是坏事。

HosuLv1#1

再补个容易漏看的点:SEARCH ... USING INDEX 不等于完全没有排序,最好一起看输出里有没有 USE TEMP B-TREE FOR ORDER BY。这个查询如果经常按 user_id 筛选、再按时间倒序取,可以试试 CREATE INDEX idx_events_user_created ON events(user_id, created_at DESC);,然后重新看执行计划。表很小时优化器选择全表扫也不一定是坏事。

这个点很关键。再补一层:统计信息过旧时,计划也可能看起来“不合理”,尤其是批量导入或数据分布变化后。可以在同一个数据库连接里先跑:

PRAGMA optimize;

再重新执行原查询的 EXPLAIN QUERY PLAN。SQLite 3.18+ 支持这个 pragma,它会按需维护优化器统计。别为了让输出出现 USING INDEX 就急着强制指定索引,还是要结合实际数据量和查询耗时判断。