SQLite Explain(解释)

SQLite 中,EXPLAINEXPLAIN QUERY PLAN 是两个强大的 调试工具,帮助你 理解 SQL 是如何被执行的


一、EXPLAIN vs EXPLAIN QUERY PLAN

命令作用输出内容
EXPLAIN显示 底层虚拟机指令(VM bytecode)每步操作的 opcode
EXPLAIN QUERY PLAN显示 查询执行计划(更直观)扫描/搜索方式、索引使用

日常使用推荐 EXPLAIN QUERY PLAN


二、EXPLAIN QUERY PLAN —— 快速判断性能

基本语法

EXPLAIN QUERY PLAN
SELECT * FROM users WHERE email = 'alice@example.com';

输出解读(关键字段)

输出关键词含义是否高效
SCAN TABLE全表扫描
SEARCH TABLE ... USING INDEX使用索引查找
SEARCH TABLE ... USING PRIMARY KEY使用主键
USING COVERING INDEX覆盖索引(无需回表)最快
TEMP B-TREE临时排序/分组可优化

示例分析

EXPLAIN QUERY PLAN
SELECT name FROM users WHERE email = 'alice@example.com';

情况 1:命中索引(理想)

SEARCH TABLE users USING INDEX idx_users_email (email=?)

高效!只查索引

情况 2:全表扫描(需优化)

SCAN TABLE users

慢!建议建索引:

CREATE INDEX idx_users_email ON users(email);

情况 3:覆盖索引(最优)

SEARCH TABLE users USING COVERING INDEX idx_cover (email=?) 

不读表,直接从索引取数据


三、EXPLAIN —— 深入虚拟机指令

EXPLAIN
SELECT name FROM users WHERE id = 5;

输出示例

addr  opcode         p1    p2    p3    p4             p5  comment
----  -------------  ----  ----  ----  -------------  --  -------
0     Init           0     10    0                    00  Start at 10
1     Integer        5     1     0                    00  r[1]=5
2     OpenRead       0     3     0     2            00  root=3
3     SeekRowid      0     8     1                    00  Seek to rowid=r[1]
4     Column         0     1     2                    00  r[2]=name
5     ResultRow      2     1     0                    00  Output r[2]
6     Halt           0     0     0                    00

常见 opcode 含义

opcode含义
OpenRead打开表/索引
SeekRowid用主键查找
Column读取列值
ResultRow输出一行结果
Copy / SCopy复制寄存器
Goto跳转

适合研究 SQLite 内部机制


四、实战:用 EXPLAIN QUERY PLAN 优化查询

原始慢查询

SELECT * FROM orders WHERE user_id = 123 AND status = 'completed' ORDER BY created_at DESC;

执行计划(差)

SCAN TABLE orders

全表扫描 + 临时排序 → 慢!


优化步骤

1. 建复合索引

CREATE INDEX idx_orders_user_status_date 
ON orders(user_id, status, created_at DESC);

2. 再看执行计划(理想)

SEARCH TABLE orders USING INDEX idx_orders_user_status_date (user_id=? AND status=?)

直接定位 + 索引已有序 → 无需排序!


五、常见优化模式

查询类型推荐索引执行计划目标
WHERE a = ?INDEX ON t(a)USING INDEX ... (a=?)
WHERE a = ? AND b = ?INDEX ON t(a, b)USING INDEX ... (a=? AND b=?)
ORDER BY x DESCINDEX ON t(x DESC)避免 TEMP B-TREE
WHERE a > ? ORDER BY aINDEX ON t(a)范围扫描 + 顺序

六、查看索引是否生效(黄金命令)

-- 1. 查看所有索引
PRAGMA index_list(users);

-- 2. 查看索引结构
PRAGMA index_info(idx_users_email);

-- 3. 分析查询计划
EXPLAIN QUERY PLAN SELECT ...;

-- 4. 更新统计信息(帮助优化器)
ANALYZE;

七、图形化工具(推荐)

工具功能
DB Browser for SQLite一键 EXPLAIN QUERY PLAN
DBeaver可视化执行计划树
SQLite Expert索引建议

八、快速诊断清单

-- 1. 执行计划
EXPLAIN QUERY PLAN SELECT ...;

-- 2. 是否全表扫描?
-- → 有 SCAN?建索引!

-- 3. 是否临时排序?
-- → 有 TEMP B-TREE?加 ORDER BY 列到索引

-- 4. 是否回表?
-- → 无 COVERING?加 SELECT 列到索引

九、真实案例:从 2s → 5ms

-- 慢查询(2秒)
SELECT * FROM logs WHERE app = 'web' AND level = 'ERROR' ORDER BY timestamp DESC LIMIT 100;

-- 执行计划
SCAN TABLE logs
TEMP B-TREE FOR ORDER BY

-- 优化:建复合索引
CREATE INDEX idx_logs_app_level_time 
ON logs(app, level, timestamp DESC);

-- 新计划
SEARCH TABLE logs USING INDEX idx_logs_app_level_time (app=? AND level=?)
-- → 5ms!

总结:EXPLAIN 使用流程

graph TD
    A[写 SQL] --> B{EXPLAIN QUERY PLAN}
    B --> C{有 SCAN?}
    C -->|是| D[建索引]
    C -->|否| E{有 TEMP B-TREE?}
    E -->|是| F[索引包含 ORDER BY 列]
    E -->|否| G[是否 COVERING?]
    G -->|否| H[索引包含 SELECT 列]
    G -->|是| I[完美!]

快速参考卡

-- 查看执行计划(推荐)
EXPLAIN QUERY PLAN SELECT ...;

-- 查看虚拟机指令(高级)
EXPLAIN SELECT ...;

-- 更新优化器统计
ANALYZE;

-- 查看索引
PRAGMA index_list(表名);

需要我帮你:

  • 分析一段 SQL 的 EXPLAIN QUERY PLAN 输出
  • 为你的查询设计最优索引
  • 把慢查询优化到毫秒级

把你的 SQL 和表结构发我!

文章已创建 2326

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部