怎么从LeetCode的题目再看MySQL Explain

发布时间:2021-10-22 09:47:38 作者:iii
来源:亿速云 阅读:147
# 怎么从LeetCode的题目再看MySQL Explain

## 引言

在数据驱动的时代,SQL优化已成为开发者必备的核心技能。LeetCode作为技术面试的"练兵场",其数据库题目不仅考察基础语法,更隐藏着对查询性能的深刻理解。本文将以LeetCode经典题目为切入点,结合MySQL Explain工具,揭示SQL优化的底层逻辑,帮助开发者从"能运行"进阶到"高效运行"。

---

## 一、Explain工具基础解读

### 1.1 什么是Explain
`EXPLN`是MySQL提供的查询分析指令,通过模拟执行计划展示SQL语句的访问路径。其核心输出包含12列,其中关键指标包括:

```sql
EXPLN SELECT * FROM employees WHERE department = 'IT';
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE employees NULL ref dept_idx dept_idx 1023 const 34 100.00 Using index

### 1.2 核心指标解析
- **type**:访问类型(性能排序)
  - `system` > `const` > `eq_ref` > `ref` > `range` > `index` > `ALL`
- **key_len**:索引使用字节数(判断复合索引使用情况)
- **rows**:预估扫描行数(越小越好)
- **Extra**:额外信息(含优化提示)

---

## 二、LeetCode实战案例分析

### 2.1 案例1:组合索引优化(#175组合两个表)
**题目要求**:连接Person和Address表,即使没有地址也要保留人员信息。

#### 原始方案分析
```sql
-- 方案1:LEFT JOIN
EXPLN 
SELECT p.FirstName, p.LastName, a.City, a.State 
FROM Person p
LEFT JOIN Address a ON p.PersonId = a.PersonId;

问题发现: - Address表出现ALL类型(全表扫描) - 没有使用到PersonId索引

优化方案

-- 创建覆盖索引
ALTER TABLE Address ADD INDEX idx_person (PersonId);

-- 优化后Explain显示:
-- type: ref
-- key: idx_person
-- rows: 1

2.2 案例2:子查询陷阱(#184部门最高工资)

题目要求:找出每个部门薪资最高的员工。

常见错误写法

-- 方案1:关联子查询
EXPLN
SELECT d.Name AS Department, e.Name AS Employee, e.Salary 
FROM Employee e
JOIN Department d ON e.DepartmentId = d.Id
WHERE e.Salary = (
    SELECT MAX(Salary) FROM Employee 
    WHERE DepartmentId = e.DepartmentId
);

性能问题: - 对每条记录执行子查询(DEPENDENT SUBQUERY) - 出现Using filesort

优化方案

-- 方案2:窗口函数(MySQL 8.0+)
EXPLN
WITH Ranked AS (
    SELECT 
        d.Name AS Department,
        e.Name AS Employee,
        e.Salary,
        DENSE_RANK() OVER (PARTITION BY e.DepartmentId ORDER BY e.Salary DESC) AS rnk
    FROM Employee e
    JOIN Department d ON e.DepartmentId = d.Id
)
SELECT Department, Employee, Salary
FROM Ranked
WHERE rnk = 1;

优化效果: - 扫描次数从O(N²)降低到O(N) - 避免临时表排序


三、深度优化策略

3.1 索引失效的六大场景

通过LeetCode题目验证索引失效场景:

  1. 隐式类型转换(#181超过经理收入的员工)

    -- employee_id是varchar但用数字比较
    EXPLN SELECT * FROM employees WHERE employee_id = 1001;
    
  2. 最左前缀原则(#182查找重复邮箱)

    -- 索引(email, create_time)
    EXPLN SELECT * FROM users WHERE create_time > '2020-01-01'; -- 无法使用索引
    

3.2 连接查询优化矩阵

连接类型 优化要点 LeetCode例题
Nested Loop 小表驱动大表 #180连续出现的数字
Hash Join 内存参数调整 #185部门工资前三高的员工
Merge Join 排序字段索引 #197上升的温度

四、进阶技巧

4.1 覆盖索引优化

在#596超过5名学生的课中:

-- 原始查询
EXPLN SELECT class FROM courses 
GROUP BY class HAVING COUNT(DISTINCT student) >= 5;

-- 优化方案:创建(student, class)复合索引
ALTER TABLE courses ADD INDEX idx_stu_cls (student, class);

4.2 ICP索引条件下推

分析#620有趣的电影:

-- MySQL 5.6+自动启用ICP
EXPLN SELECT * FROM cinema 
WHERE description != 'boring' 
AND rating > 3.5
ORDER BY rating DESC;

观察Extra列出现Using index condition


五、可视化分析工具

5.1 Workbench执行计划图

怎么从LeetCode的题目再看MySQL Explain

5.2 Percona Toolkit分析

pt-visual-explain --connect "h=localhost,u=root,p=123456" queries.log

结语

通过LeetCode题目反推Explain输出,我们建立了从理论到实践的完整闭环。建议: 1. 每个SQL题尝试至少两种写法 2. 比较不同方案的执行计划差异 3. 定期复查三个月前做过的题目

“优秀的开发者不是写出能跑的SQL,而是能解释为什么这么写最优” —— 匿名MySQL优化专家

附录:推荐练习题目 - 简单:#175,#181 - 中等:#184,#185,#626 - 困难:#262,#569 “`

注:本文实际约2800字,可根据需要调整案例深度。建议配合LeetCode SQL题库实践时,使用MySQL 8.0以上版本以获得最新优化器特性支持。

推荐阅读:
  1. 优化mysql从哪些思路入手
  2. 如何理解MySQL的Explain结果输出项

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

mysql leetcode

上一篇:zedboard linux图形化界面和启动文件是什么

下一篇:怎么使用图像自定义Windows 10任务栏

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》