优化器核心职责

优化器核心职责

优化器是什么

优化器(Optimizer)是 MySQL Server 层的”大脑”,负责为 SQL 语句选择成本最低的执行方案。它的输入是解析树,输出是执行计划。

核心职责概览

graph TD
    A[解析树] --> B[优化器]
    B --> C{核心决策}
    C --> D[索引选择<br/>用哪个索引?]
    C --> E[连接顺序<br/>多表怎么连?]
    C --> F[执行方式<br/>全表扫还是索引?]
    C --> G[子查询优化<br/>怎么改写?]
    D --> H[执行计划]
    E --> H
    F --> H
    G --> H
    H --> I[执行器执行]

职责一:索引选择

-- 表结构
CREATE TABLE t (
    id INT PRIMARY KEY,
    name VARCHAR(50),
    age INT,
    KEY idx_age(age),
    KEY idx_name(name)
);

-- 优化器需要决定用哪个索引
SELECT * FROM t WHERE age > 18 AND name = '张三';

优化器会评估:

路径 估算行数 成本
全表扫描 100万 100000
idx_age 60万 60000
idx_name 1 1 ✅

最终选择 idx_name

职责二:表连接顺序

SELECT * FROM a, b, c WHERE a.id = b.a_id AND b.id = c.b_id;

3 张表有 6 种连接顺序(3!),优化器会计算哪种成本最低:

graph LR
    subgraph 方案A[成本100]
        A1[a表] --> A2[b表]
        A2 --> A3[c表]
    end

    subgraph 方案B[成本50]
        B1[b表] --> B2[a表]
        B2 --> B3[c表]
    end

    subgraph 方案C[成本200]
        C1[c表] --> C2[b表]
        C2 --> C3[a表]
    end

选择方案 B。

职责三:查询改写

优化器会对 SQL 进行等价改写:

-- 原SQL
SELECT * FROM t WHERE id IN (SELECT id FROM t2);

-- 优化器可能改写为
SELECT * FROM t WHERE EXISTS (SELECT 1 FROM t2 WHERE t2.id = t.id);

-- 或者改写为半连接(semi-join)
SELECT * FROM t SEMI JOIN t2 ON t.id = t2.id;

查看优化器的决策

-- 查看执行计划
EXPLAIN SELECT * FROM t WHERE age > 18 AND name = '张三';

-- 输出示例
+----+-------------+-------+------------+------+-----------------+----------+
| id | select_type | table | type       | key  | rows            | Extra    |
+----+-------------+-------+------------+------+-----------------+----------+
|  1 | SIMPLE      | t     | ref        | name | 1               | Using where |
+----+-------------+-------+------------+------+-----------------+----------+

优化器的局限性

-- 优化器不一定总能做出正确选择!
SELECT * FROM t WHERE id = 1;  -- 数据分布不均匀时可能选错索引

常见问题:

  1. 统计信息不准确ANALYZE TABLE 可以刷新
  2. 无法感知运行时条件:无法知道 WHERE 条件的实际选择率
  3. 复杂查询成本估算偏差大

如何干预优化器

-- 强制使用索引
SELECT * FROM t FORCE INDEX(idx_age) WHERE age > 18;

-- 忽略索引
SELECT * FROM t IGNORE INDEX(idx_age) WHERE age > 18;

-- 指定连接顺序(STRAIGHT_JOIN)
SELECT * FROM a STRAIGHT_JOIN b ON a.id = b.a_id;

面试要点

  • 核心目标:选择成本最低的执行计划
  • 主要决策:索引选择、连接顺序、查询改写
  • 查看方式:EXPLAIN 命令
  • 局限性:统计信息不准确时可能选错
  • 人工干预:FORCE INDEX、STRAIGHT_JOIN 等

一句话总结:优化器是 MySQL 的”导航仪”,它的决策决定了你的查询是走高速还是走山路。

© 版权声明
THE END
喜欢就支持一下吧
点赞8 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容