跳到主要内容

慢查询排查

场景描述

BI 看板页面加载需要 30 秒,排查后发现底层 SQL 查询需要扫描全表 2 亿行数据。

排查流程

常见慢查询场景及优化

1. 全表扫描

-- ❌ 慢:WHERE 条件无索引
SELECT * FROM orders WHERE user_name = '张三';

-- ✅ 优化:添加索引
ALTER TABLE orders ADD INDEX idx_user_name (user_name);

2. 深分页

-- ❌ 慢:OFFSET 100万
SELECT * FROM orders ORDER BY id LIMIT 10 OFFSET 1000000;

-- ✅ 优化:游标分页
SELECT * FROM orders WHERE id > 1000000 ORDER BY id LIMIT 10;

3. 大表 JOIN

-- ❌ 慢:两个大表直接 JOIN
SELECT a.*, b.*
FROM order_detail a -- 10亿行
JOIN product b ON a.product_id = b.id; -- 500万行

-- ✅ 优化:小表广播(Spark)
SELECT /*+ BROADCAST(b) */ a.*, b.*
FROM order_detail a
JOIN product b ON a.product_id = b.id;

4. 不合理的子查询

-- ❌ 慢:相关子查询每行执行一次
SELECT user_id, (SELECT COUNT(*) FROM orders WHERE orders.user_id = u.id) AS order_cnt
FROM users u;

-- ✅ 优化:改写为 JOIN
SELECT u.id AS user_id, COALESCE(o.cnt, 0) AS order_cnt
FROM users u
LEFT JOIN (SELECT user_id, COUNT(*) AS cnt FROM orders GROUP BY user_id) o
ON u.id = o.user_id;

5. 窗口函数滥用

-- ❌ 慢:全量数据上开窗
SELECT *, ROW_NUMBER() OVER (ORDER BY created_at) AS rn FROM orders;

-- ✅ 优化:先过滤再开窗
SELECT *, ROW_NUMBER() OVER (ORDER BY created_at) AS rn
FROM orders WHERE dt = '2024-01-15';

EXPLAIN 关键字段解读

字段含义优化信号
type访问类型ALL(全表扫描) → range(范围) → ref(索引) → const
key使用的索引NULL = 未用索引
rows预估扫描行数越少越好
Extra附加信息Using filesort / Using temporary 需优化

常见面试问题

Q1: 数据分析师需要关注 SQL 性能吗?

答案

需要。数据分析师写的 SQL 经常在大数据集上执行,不注意性能会导致:

  • 查询超时影响分析效率
  • 占用集群资源影响他人
  • BI 看板加载慢影响用户体验

核心关注:避免全表扫描、用好分区、控制数据量

Q2: Hive / Spark SQL 慢查询如何排查?

答案

  1. 看 Spark UI 的 Stage 和 Task 执行时间
  2. 检查 Shuffle 数据量(Shuffle Read/Write)
  3. 检查是否有数据倾斜(某个 Task 特别慢)
  4. 检查分区裁剪是否生效(Partition Pruning)
  5. 检查是否触发了小文件问题

相关链接