2020-10-10 12:31:51
优化复杂的MySQL查询需结合执行计划分析、索引策略调整及查询结构重构,以下从关键方向展开说明:
1. 使用EXPLAIN分析执行计划通过EXPLAIN命令查看查询的执行路径,重点关注以下指标:
Using filesort:需额外排序,可能因ORDER BY字段无索引导致。
Using temporary:使用临时表,常见于GROUP BY或DISTINCT操作。
示例:
EXPLAIN SELECT * FROM orders WHERE user_id = 100;若输出中type=ALL且key=NULL,说明未使用索引,需优化。
2. 合理创建和使用索引为WHERE、JOIN、ORDER BY涉及的字段建索引。
选择区分度高的字段(如用户ID优于性别)。
遵循最左前缀原则:索引(a,b,c)可用于a或(a,b)查询,但无法用于b单独查询。
避免索引列上使启手用函数或表达式:如WHERE YEAR(create_time) = 2023会导致索引失效。
使用NOT、!=、OR(除非所有条件均含索引)。
隐式类型转换(如字符串与数字比较)。
将嵌套子查询改为JOIN,MySQL对JOIN的优化更高效。
示例:-- 低效:子查询SELECT * FROM users WHERE id IN (SELECT user_id FROM orders WHERE amount > 100);-- 高效:JOINSELECT u.* FROM users u JOIN orders o ON u.id = o.user_id WHERE o.amount > 100;
避免SELECT *,仅查询必要字段。
大分页优化:将LIMIT 10000, 20改为WHERE id > 10000 LIMIT 20(需id有索引)。
对重复计算的中间结果,可存入临胡旁枣时表并加索引。
确保关联字段类型一致且均有索引(如int对int)。
小表驱裤拆动大表:在嵌套循环JOIN中,外层表应尽可能小。
示例:-- 低效:大表驱动小表SELECT * FROM large_table l JOIN small_table s ON l.id = s.id;-- 高效:小表驱动大表SELECT * FROM small_table s JOIN large_table l ON s.id = l.id;
确保分组字段有索引,避免临时表和filesort。
必要时开启SQL_BIG_RESULT提示优化器直接使用磁盘临时表。
开启slow_query_log,分析执行时间超过阈值的查询。
通过log_queries_not_using_indexes定位未使用索引的查询。
字段类型匹配:确保JOIN、WHERE条件中的字段类型一致。
索引覆盖:查询字段全部包含在索引中,避免回表操作。
避免排序:若ORDER BY字段无索引,可考虑增加索引或调整查询逻辑。
优化复杂MySQL查询需遵循以下步骤:
示例优化案例:
-- 原始查询(低效)SELECT * FROM orders o JOIN users u ON o.user_id = u.id WHERE YEAR(o.create_time) = 2023 GROUP BY u.name ORDER BY o.amount DESC LIMIT 10000, 20;-- 优化后(高效)-- 1. 添加索引:ALTER TABLE orders ADD INDEX idx_user_create (user_id, create_time);-- 2. 修改查询SELECT u.name, o.amount FROM (SELECT * FROM orders WHERE create_time BETWEEN '2023-01-01' AND '2023-12-31' ORDER BY amount DESC LIMIT 10000, 20) o JOIN users u ON o.user_id = u.id;通过索引优化、查询重构和分页调整,显著提升查询效率。