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

相关推荐
吴声子夜歌7 小时前
MongoDB 4.2——入门指南
数据库·mongodb
吴声子夜歌7 小时前
MongoDB 4.x——高可靠
数据库·mongodb
light blue bird8 小时前
组轴式执行引擎 ✅ 多线程调度组装组件
数据库·信息可视化·oracle·桌面端winform·多节点端·gdi图表绘制开发
码农学院8 小时前
Node.js MongoDB构建户外用品GEO优化内容管理平台
数据库·mongodb·node.js
吴声子夜歌8 小时前
MongoDB 4.x——治理经验
数据库·mongodb
黄华SJ520it9 小时前
门店预约系统开发:提升服务行业数字化转型
前端·数据库·系统开发
万事可爱^9 小时前
Claude 新发布的 Opus 5,系统提示语删了 80%,半价还能逼近 Fable 5
android·服务器·数据库·人工智能·claude
早点睡啊Y9 小时前
深入学LangChain官方文档:Observability 与 Studio——先看清 Agent 到底做了什么
java·数据库·langchain
Mico189 小时前
MySQL 8.0.35 GTID主从复制常见管理操作
mysql
@insist12310 小时前
信息系统管理工程师-数据层知识点详解:存储、数据库与信息安全
数据库·软考·软件水平考试·信息系统管理工程师·软考信管