订阅更新

一条SQL跑了60秒——慢查询怎么排查?EXPLAIN怎么看?

Doris手册 第 11 题 约 5 分钟读完

本文目录
  1. 先说结论
  2. 排查第一步:看Profile——查询到底慢在哪?
  3. 排查第二步:看EXPLAIN——执行计划对不对?
  4. 常见慢查询原因和优化方案
  5. 实战经验:从60秒优化到300ms的完整过程
  6. 慢查询日志和定期Review
  7. 实战踩坑:一条SELECT \拖慢整个集群
  8. 面试高频追问
  9. 总结

先说结论

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=ALLScanRows极大WHERE里加分区列条件
JOIN策略不对SHUFFLE JOINShuffleBytes大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的过程和每步的量化效果,面试官会非常满意。

刷题进度保存在当前浏览器