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,我可以帮你分析执行计划! 🚀

相关推荐
CoderYanger6 小时前
Java EE 进阶:8.MyBatis 操作数据库(入门)(第二弹)
java·数据库·spring boot·spring·面试·java-ee·mybatis
wafrdggh8 小时前
2026电商快递批量查询怎么用?固乔助手模板设置评测
大数据·数据库·小程序
一个天蝎座 白勺 程序猿9 小时前
KingbaseES数据库归档重做日志文件管理:从配置到运维的实战指南
运维·数据库·oracle·kingbasees·金仓数据库
龙腾AI白云12 小时前
仿真到现实(Sim-to-Real)迁移:跨越仿真与现实鸿沟
数据库·机器学习·plotly·知识图谱·tornado
freejackman14 小时前
【实战二】字段级血缘追踪:拆解 AST 迷局,精准穿透函数链与子查询
大数据·数据库·sql
.痞老板.15 小时前
mysql初阶--增删改查操作
数据库·mysql
lambo mercy21 小时前
AI智能租房助手
数据库
浮生若城1 天前
MySQL:库与表的操作
数据库·mysql
薛定谔的悦1 天前
光储充一体机从主控到执行单元的双层架构
数据库·mongodb·架构
数字新视界1 天前
动环监控信创适配在智能机房管理中的应用价值与未来展望
大数据·服务器·数据库·动环监控系统·动力与环境监控系统