MYSQL优化器的主要的优化策略及其示例

MySQL 优化器除了 自动将 WHERE 条件前置(谓词下推,Predicate Pushdown) 之外,还会进行许多其他关键优化,以提高查询性能。以下是主要的优化策略及其示例:


1. 查询重写(Query Rewriting)

优化器会 重写 SQL,使其更高效,即便 SQL 写法不同,最终执行计划可能相同。

示例优化

  • IN → EXISTS / JOIN 转换

    sql 复制代码
    -- 原始语句
    SELECT * FROM users WHERE id IN (SELECT user_id FROM orders);
    
    -- 可能被优化为
    SELECT users.* FROM users JOIN orders ON users.id = orders.user_id;
  • OR 合并优化

    sql 复制代码
    -- 原始语句
    SELECT * FROM users WHERE age > 20 OR salary > 5000;
    
    -- 可能拆分成两个 Range Scan 并合并

2. 索引优化

优化器会 智能选择最佳索引 ,甚至 动态调整索引使用策略

示例优化

  1. 覆盖索引(Covering Index)

    • 如果可以,优化器会直接从索引读取数据,避免回表(减少 I/O)。
    sql 复制代码
    SELECT id, name FROM users WHERE age = 25;
    -- 如果 (age, id, name) 构成覆盖索引,就不读表数据
  2. Index Skip Scan(MySQL 8.0+)

    • 对复合索引 (a, b),即使 a 未指定,也能利用 b 的部分扫描。
  3. Multi-Range Read (MRR)

    • 先收集 所有满足 WHERE 条件的 id,再按主键排序读取数据(减少随机 I/O)。
  4. Index Condition Pushdown (ICP, 索引条件下推)

    • 让存储引擎 在索引层过滤数据 (减少回表次数)。
    sql 复制代码
    -- 复合索引 (name, age)
    SELECT * FROM users WHERE name LIKE '张%' AND age > 20;
    -- ICP 让存储引擎直接过滤 age > 20,避免回表

3. 连接优化(Join Optimizations)

优化器会 调整 JOIN 顺序、方式,减少计算量。

示例优化

  1. JOIN 顺序优化

    • 小表优先 JOIN(减少中间结果)。
    sql 复制代码
    SELECT * FROM large_table JOIN small_table ON ...;
    -- 优化器可能会自动先处理 small_table
  2. 使用 Batched Key Access (BKA)

    • 减少 JOIN 时的随机 I/O(结合 MRR)。
  3. Hash Join / Nested Loop Join 选择

    • MySQL 8.0+ 支持 Hash Join(适合无索引大表 JOIN 时)。
  4. 子查询优化(Subquery Materialization)

    • IN (...) 子查询可能被 物化(临时表缓存),避免重复计算。
  5. 外连接转内连接(OUTER JOIN → INNER JOIN)

    sql 复制代码
    SELECT * FROM users LEFT JOIN orders ON users.id = orders.user_id
    WHERE orders.user_id IS NOT NULL;  -- 优化器可能自动转成 INNER JOIN

4. 聚合和分组优化

  1. Loose Index Scan(松散索引扫描)

    • 优化 GROUP BY,避免全表扫描:

      sql 复制代码
      SELECT category, COUNT(*) FROM products GROUP BY category;
      -- 如果 (category) 有索引,可能直接扫描索引而非全表
  2. Using Temporary + Filesort → 直接索引排序

    • MySQL 会尝试避免临时表排序,尽量使用索引。
    sql 复制代码
    SELECT * FROM users WHERE age > 20 ORDER BY name;
    -- 如果 (age, name) 有索引,优化器会避免 Filesort

5. 数据访问优化

  1. Buffer Pool 缓存

    • 如果数据已经被缓存,优化器会 避免磁盘 I/O
  2. 并行查询(MySQL 8.0+)

    • 某些查询可能 并行执行 (如 COUNT(*))。
  3. Optimizer Hints 优化器提示

    • 可手动指定索引、JOIN 顺序:

      sql 复制代码
      SELECT /*+ INDEX(users idx_age) */ * FROM users WHERE age = 20;

6. 查询执行优化

  1. 延迟 JOIN(Delayed Join)

    • 先过滤数据再 JOIN,减少中间结果集。
  2. LIMIT 优化

    sql 复制代码
    SELECT * FROM users LIMIT 10;
    -- MySQL 检测到 LIMIT 时,可能在索引扫描时直接返回 10 条
  3. 统计信息更新

    • 优化器基于 ANALYZE TABLE 的统计信息决定执行计划。

总结

优化技术 说明
谓词下推(Predicate Pushdown) 尽早用 WHERE 减少数据量
覆盖索引(Covering Index) 直接从索引读取数据,避免回表
ICP(索引条件推送) 存储引擎层过滤数据
MRR / BKA 优化 JOIN 的随机 I/O
Hash Join 大表 JOIN 优化(MySQL 8.0+)
Loose Index Scan 快速 GROUP BY
子查询物化(Subquery Materialization) 避免重复计算 IN 子查询
延迟 JOIN 先过滤再连接

⚠️ 验证执行计划

EXPLAIN + EXPLAIN ANALYZE(MySQL 8.0+)查看查询如何优化!

如果有具体查询优化问题,可以提供 SQL,我可以帮你分析执行计划! 🚀

相关推荐
Y381532662几秒前
MySQL 慢查询排查实战:EXPLAIN 看懂 type 与 Extra,一个字段定位性能问题
数据库·mysql
Logintern091 小时前
PostgreSQL 的 ORDER BY 多列排序
数据库·postgresql
今天AI了吗2 小时前
DeepSeek Harness 深度解析:从评测架构到实战落地
java·网络·数据库·人工智能·架构·java-ee
数据库小学妹2 小时前
为什么MySQL索引用B+树?从存储底层讲透原理
数据库·mysql·b+树·索引优化·磁盘io·数据库原理
BestHeaker2 小时前
制造业 MES 开发入门:和互联网业务开发的 5 个本质差异(一)
数据库·经验分享·制造业·mes
自动化监测Learner4 小时前
Navicat Premium 17 中文版安装教程(2026最新版)
java·linux·数据库
张文是假的啊4 小时前
常用JPA注解解释
数据库
Allen_LVyingbo5 小时前
医疗AI基础2026-构建可靠智能体的编程路径(上)
大数据·数据库·人工智能·python·自动化
疯狂打码的少年5 小时前
【数据库技术】多值依赖与第四范式(4NF)
数据库·笔记·算法