MYSQL优化器的主要的优化策略及其示例
MySQL 优化器除了自动将 WHERE 条件前置谓词下推Predicate Pushdown之外还会进行许多其他关键优化以提高查询性能。以下是主要的优化策略及其示例1. 查询重写Query Rewriting优化器会重写 SQL使其更高效即便 SQL 写法不同最终执行计划可能相同。示例优化IN → EXISTS / JOIN 转换-- 原始语句SELECT*FROMusersWHEREidIN(SELECTuser_idFROMorders);-- 可能被优化为SELECTusers.*FROMusersJOINordersONusers.idorders.user_id;OR 合并优化-- 原始语句SELECT*FROMusersWHEREage20ORsalary5000;-- 可能拆分成两个 Range Scan 并合并2. 索引优化优化器会智能选择最佳索引甚至动态调整索引使用策略。示例优化覆盖索引Covering Index如果可以优化器会直接从索引读取数据避免回表减少 I/O。SELECTid,nameFROMusersWHEREage25;-- 如果 (age, id, name) 构成覆盖索引就不读表数据Index Skip ScanMySQL 8.0对复合索引(a, b)即使a未指定也能利用b的部分扫描。Multi-Range Read (MRR)先收集所有满足 WHERE 条件的 id再按主键排序读取数据减少随机 I/O。Index Condition Pushdown (ICP, 索引条件下推)让存储引擎在索引层过滤数据减少回表次数。-- 复合索引 (name, age)SELECT*FROMusersWHEREnameLIKE张%ANDage20;-- ICP 让存储引擎直接过滤 age 20避免回表3. 连接优化Join Optimizations优化器会调整 JOIN 顺序、方式减少计算量。示例优化JOIN 顺序优化小表优先 JOIN减少中间结果。SELECT*FROMlarge_tableJOINsmall_tableON...;-- 优化器可能会自动先处理 small_table使用Batched Key Access (BKA)减少 JOIN 时的随机 I/O结合 MRR。Hash Join / Nested Loop Join 选择MySQL 8.0 支持Hash Join适合无索引大表 JOIN 时。子查询优化Subquery MaterializationIN (...)子查询可能被物化临时表缓存避免重复计算。外连接转内连接OUTER JOIN → INNER JOINSELECT*FROMusersLEFTJOINordersONusers.idorders.user_idWHEREorders.user_idISNOTNULL;-- 优化器可能自动转成 INNER JOIN4. 聚合和分组优化Loose Index Scan松散索引扫描优化GROUP BY避免全表扫描SELECTcategory,COUNT(*)FROMproductsGROUPBYcategory;-- 如果 (category) 有索引可能直接扫描索引而非全表Using Temporary Filesort → 直接索引排序MySQL 会尝试避免临时表排序尽量使用索引。SELECT*FROMusersWHEREage20ORDERBYname;-- 如果 (age, name) 有索引优化器会避免 Filesort5. 数据访问优化Buffer Pool 缓存如果数据已经被缓存优化器会避免磁盘 I/O。并行查询MySQL 8.0某些查询可能并行执行如COUNT(*)。Optimizer Hints 优化器提示可手动指定索引、JOIN 顺序SELECT/* INDEX(users idx_age) */*FROMusersWHEREage20;6. 查询执行优化延迟 JOINDelayed Join先过滤数据再 JOIN减少中间结果集。LIMIT 优化SELECT*FROMusersLIMIT10;-- MySQL 检测到 LIMIT 时可能在索引扫描时直接返回 10 条统计信息更新优化器基于ANALYZE TABLE的统计信息决定执行计划。总结优化技术说明谓词下推Predicate Pushdown尽早用WHERE减少数据量覆盖索引Covering Index直接从索引读取数据避免回表ICP索引条件推送存储引擎层过滤数据MRR / BKA优化 JOIN 的随机 I/OHash Join大表 JOIN 优化MySQL 8.0Loose Index Scan快速GROUP BY子查询物化Subquery Materialization避免重复计算 IN 子查询延迟 JOIN先过滤再连接⚠️验证执行计划用EXPLAINEXPLAIN ANALYZEMySQL 8.0查看查询如何优化如果有具体查询优化问题可以提供 SQL我可以帮你分析执行计划