一条SQL跑了60秒——慢查询怎么排查?EXPLAIN怎么看?
本文目录
先说结论
Doris慢查询排查三板斧:① 看Profile(查询执行详情,定位瓶颈在哪个阶段);② 看EXPLAIN(执行计划,判断有没有走分区裁剪、索引命中、JOIN策略是否合理);③ 看BE监控(CPU/内存/磁盘IO,判断是不是资源瓶颈)。90%的慢查询问题出在:没走分区裁剪、JOIN策略不对、或者数据倾斜。
先把这段讲顺;面试官追问时,再展开下面的原理和细节。
详细讲解
在某元宇宙社交公司做实时大盘的时候,运营同事反馈有个报表页面加载超过1分钟。我一看SQL——一条三表JOIN带多个子查询,没有分区过滤,全表扫描了3个月的数据。定位原因只花了5分钟,但优化过程很有代表性。慢查询排查是Doris运维的日常工作,也是面试的高频考点。面试官想看的是你有没有系统性的排查方法论,而不是凭感觉猜。
排查第一步:看Profile——查询到底慢在哪?
Doris的Query Profile记录了查询执行的每个阶段的耗时,是排查慢查询的最有力工具:
实战技巧:Profile里看到ScanRows=5亿但你只需要最近1天的数据,说明没走分区裁剪;看到ShuffleBytes=10GB,说明JOIN的Shuffle开销巨大,考虑用Colocate Join。
排查第二步:看EXPLAIN——执行计划对不对?
常见慢查询原因和优化方案
| 原因 | EXPLAIN表现 | Profile表现 | 优化方案 |
|---|---|---|---|
| 没走分区裁剪 | Partitions=ALL | ScanRows极大 | WHERE里加分区列条件 |
| JOIN策略不对 | SHUFFLE JOIN | ShuffleBytes大 | Colocate Join或Broadcast hint |
| 没命中物化视图 | 扫描原表 | ScanRows=原表总行数 | 检查物化视图定义是否覆盖查询 |
| SELECT * | 输出列=全部列 | ScanBytes大 | 只选需要的列 |
| 数据倾斜 | 某个BE耗时远大于其他 | MaxTime远大于AvgTime | 调整分桶列或打散热点 |
| Compaction积压 | — | ScanRows正常但慢 | 检查VersionCount |
实战经验:从60秒优化到300ms的完整过程
在某元宇宙社交公司,运营反馈的那条60秒慢查询是这样的:
优化三步走:
第一步:加分区过滤。加上WHERE e.event_time >= '2024-01-01',分区裁剪从365天减到15天,ScanRows从18亿降到7500万。查询时间从60秒降到12秒。
第二步:用Colocate Join。dwd_user_event和dim_user已经在同一个Colocate Group,JOIN条件是e.user_id = u.user_id,刚好是分桶列。Shuffle消除后查询时间从12秒降到4秒。
第三步:利用物化视图。创建了一个异步物化视图预计算这些维度的聚合结果。命中物化视图后查询时间从4秒降到300ms。
最终效果:60秒到300ms,提升200倍。其中分区裁剪贡献最大(60到12秒),Colocate Join其次(12到4秒),物化视图锦上添花(4到0.3秒)。
慢查询日志和定期Review
实战踩坑:一条SELECT *拖慢整个集群
有一次某元宇宙社交公司的一个后端同事直接在Metabase里跑了SELECT * FROM dwd_user_event,没加任何WHERE条件。这张表有18亿行、50个列。3个BE节点的内存全部打满,其他人的查询全部排队等待。
应急处理:在FE的Web UI找到这个查询的query_id,KILL QUERY杀掉。事后给Metabase的连接用户设置exec_mem_limit=4GB和query_timeout=60s。
长期方案:建立Workload Group。Metabase的查询用户分配到'analyst'组,限制CPU 30%、内存 30%、最大并发10。实时大盘用单独的'dashboard'组,保障资源。在团队内分享Doris使用规范——查询必须带分区条件、不要SELECT *。
面试高频追问
追问一:EXPLAIN和Profile有什么区别?
EXPLAIN是执行前的预估(不实际执行,毫秒级返回),告诉你查询打算怎么执行。Profile是执行后的实际记录,告诉你查询实际怎么执行的、每个阶段花了多少时间。排查时先看EXPLAIN判断计划是否合理,再看Profile定位具体的性能瓶颈。
追问二:Doris的查询超时怎么设?
SET query_timeout = 60; 默认300秒。生产环境建议设60秒。临时的大查询可以针对会话单独调大。
追问三:怎么避免一条慢查询拖垮整个集群?
三个手段:① 设置query_timeout超时自动kill;② 设置exec_mem_limit单查询内存上限;③ 使用Workload Group给不同用户分配不同的CPU/内存配额。生产环境最推荐Workload Group。
总结
慢查询排查面试讲清楚三板斧:① Profile看实际耗时(ScanRows/ShuffleBytes/PeakMemory);② EXPLAIN看执行计划(分区裁剪/JOIN策略/物化视图命中);③ 常见优化方案(加分区过滤/Colocate Join/物化视图/Workload Group资源隔离)。能讲出一次完整的从60秒优化到300ms的过程和每步的量化效果,面试官会非常满意。