翻车案例:用Explain解读慢查询的死亡密码


翻车案例:用Explain解读慢查询的死亡密码

🎬 故事开场:当数据库加班到凌晨三点

场景:某电商系统在"双11"当天,查询"用户购买记录"的SQL突然变慢,数据库CPU飙到99%,运维工程师小王被紧急叫醒。经查,罪魁祸首是一条看似无害的SQL:

sql 复制代码
SELECT * FROM orders 
WHERE user_id = 12345 
AND order_time BETWEEN '2023-11-11 00:00:00' AND '2023-11-11 23:59:59';

🔍 用Explain破解慢查询之谜

1. Explain语法与输出字段解读

sql 复制代码
EXPLAIN FORMAT=JSON 
SELECT * FROM orders 
WHERE user_id = 12345 
AND order_time BETWEEN '2023-11-11 00:00:00' AND '2023-11-11 23:59:59';

关键输出解析(以MySQL为例):

json 复制代码
{
  "query_block": {
    "select_id": 1,
    "table": {
      "table_name": "orders",
      "access_type": "ALL",    -- ❌ 全表扫描!
      "possible_keys": null,   -- 索引失踪案!
      "rows": 10000000         -- 扫描1亿行???
    }
  }
}

Mermaid图示(查询执行计划):

graph TD A[全表扫描] -->|扫描1亿行| B[数据库崩溃] C[没有索引] -->|CPU飙车| B

🚨 典型慢查询翻车现场(附修复代码)

案例1:索引失踪案

问题SQL

sql 复制代码
SELECT * FROM orders 
WHERE user_id = 12345 
AND order_time > '2023-01-01';

Explain诊断

json 复制代码
"possible_keys": null

修复方案

sql 复制代码
-- 创建联合索引(注意字段顺序!)
ALTER TABLE orders ADD INDEX idx_user_time (user_id, order_time);

案例2:Like的致命诱惑

问题SQL

sql 复制代码
SELECT * FROM users 
WHERE name LIKE '%张三%';

Explain诊断

json 复制代码
"rows": 5000000, "filtered": 100.00

修复方案

sql 复制代码
-- 全局搜索考虑全文索引(MySQL 5.7+)
ALTER TABLE users ADD FULLTEXT(name);
SELECT * FROM users 
WHERE MATCH(name) AGAINST('+张三*' IN BOOLEAN MODE);

案例3:隐形排序陷阱

问题SQL

sql 复制代码
SELECT order_id, user_id FROM orders 
ORDER BY create_time 
LIMIT 10;

Explain诊断

json 复制代码
"filesort": true

修复方案

sql 复制代码
-- 在ORDER BY字段上添加索引
ALTER TABLE orders ADD INDEX idx_create_time (create_time);

🧠 常见面试题 & 答案

题1:Explain的access_type有哪些类型?优先级如何?

答案

  • 优先级从高到低
    • system(单行) > const(主键单行) > eq_ref(唯一索引) > ref(非唯一索引) > range(范围查询) > index(索引扫描) > ALL(全表扫描)
  • 考场杀手锏 :看到ALL直接喊"优化!"

题2:为什么WHERE id=1 AND name='张三'可能不走索引?

答案

  • 索引合并失效 :若没有联合索引(id,name),单独的单字段索引会被随机选择一个,另一个条件退化为回表查询
  • 实战演示
sql 复制代码
-- 错误写法(单字段索引)
CREATE INDEX idx_id ON users(id);
CREATE INDEX idx_name ON users(name);

-- 正确写法(联合索引)
ALTER TABLE users ADD INDEX idx_id_name (id, name);

题3:Using temporary; Using filesort如何优化?

答案

  • 优化路径
    1. 确保ORDER BY字段有索引
    2. 确保GROUP BY字段有索引
    3. 避免在ORDER BY中使用函数(如ORDER BY LOWER(name)
  • 代码示例
sql 复制代码
-- 原始SQL(触发filesort)
SELECT department, COUNT(*) 
FROM employees 
GROUP BY department 
ORDER BY department DESC;

-- 优化后(添加索引)
ALTER TABLE employees ADD INDEX idx_department (department);

题4:覆盖索引是什么?如何验证?

答案

  • 定义:查询字段全在索引中,避免回表查询
  • 验证方法
sql 复制代码
EXPLAIN SELECT user_id, order_time 
FROM orders 
WHERE user_id = 12345;  -- 若显示"Using index"即为覆盖索引

题5:为什么SELECT *SELECT id慢?

答案

  • 数据量差异SELECT *读取整行数据,而SELECT id仅取单字段
  • 索引覆盖 :若存在覆盖索引(id)SELECT id可直接从索引中获取,无需回表

🛠️ 代码实验室:动手优化慢查询

实验环境搭建(MySQL)

sql 复制代码
-- 创建测试表
CREATE TABLE `orders` (
  `id` bigint PRIMARY KEY AUTO_INCREMENT,
  `user_id` int NOT NULL,
  `order_time` datetime NOT NULL,
  `status` varchar(16) NOT NULL,
  INDEX idx_user_time (user_id, order_time)
) ENGINE=InnoDB;

-- 插入测试数据
INSERT INTO orders (user_id, order_time, status)
VALUES (12345, '2023-11-11 00:00:00', 'PAID'),
       (67890, '2023-11-11 01:00:00', 'CANCELLED');

实验任务:

  1. 执行慢查询
sql 复制代码
EXPLAIN SELECT * FROM orders WHERE status = 'PAID';
  • 预期输出:possible_keys: NULL(因为status无索引)
  1. 优化并验证
sql 复制代码
ALTER TABLE orders ADD INDEX idx_status (status);
EXPLAIN SELECT * FROM orders WHERE status = 'PAID';
-- 应显示key: idx_status

💡 面试官心理战

当面试官问 :"如果优化后的SQL还是慢,怎么办?"
反杀回答:"我会检查索引碎片化(执行ANALYZE TABLE)、查看慢查询日志、甚至考虑分库分表------毕竟数据库加班到凌晨三点,它也需要个按摩师(读写分离)!"


相关推荐
ssshooter1 小时前
复古话题:Vue2 的空格间距切换到 Vite 后消失了
前端·vue.js·面试
UrbanJazzerati1 小时前
Python自动化统计工具实战:Python批量分析Salesforce DML操作与错误处理
后端·面试
Q741_1474 小时前
海致星图招聘 数据库内核研发实习生 一轮笔试 总结复盘(1) 作答语言:C/C++ 链表 二叉树
开发语言·c++·经验分享·面试·笔试
Chan164 小时前
微服务 - Higress网关
java·spring boot·微服务·云原生·面试·架构·intellij-idea
Cx330❀5 小时前
【优选算法必刷100题】第43题(模拟):数青蛙
c++·算法·leetcode·面试
释怀°Believe6 小时前
Daily算法刷题【面试经典150题-7️⃣位运算/数学/】
算法·面试·职场和发展
CCPC不拿奖不改名6 小时前
网络与API:HTTP基础+面试习题
网络·python·网络协议·学习·http·面试·职场和发展
无限码力6 小时前
华为OD技术面真题 - 计算机网络 - 3
计算机网络·华为od·面试·华为od技术面真题·华为od面试八股文·华为od技术面计算机网络相关
Bigbig.6 小时前
驱动工程师面试题 - 操作系统1
linux·开发语言·面试·硬件架构
码农丁丁7 小时前
谈谈面试的本质
面试·职场和发展·技术管理·ai时代的技术管理