深入解析Doris查询计划的优化策略与实战技巧

1. 从“慢查询”到“查询计划”:为什么你需要看懂Doris的执行蓝图?

你有没有遇到过这种情况?写了一条看起来挺简单的SQL,比如 SELECT * FROM user_behavior WHERE date='2024-01-01',结果等了十几秒甚至更久才出结果。心里嘀咕:数据量也不算特别大啊,索引也建了,怎么就慢了呢?这时候,光盯着SQL语句本身是找不到答案的。你得知道数据库引擎——比如我们这里说的Doris——它到底是怎么“干活”的。

这就好比你去餐厅点菜,你告诉服务员“来份宫保鸡丁”(这就是你的SQL)。但后厨怎么做这道菜,是先炸鸡丁还是先炒花生米,是用大火爆炒还是小火慢炖,这些流程你看不到。如果上菜慢了,你得去后厨看看是哪个环节卡住了:是备料慢了,还是灶台不够用?数据库的查询计划,就是这份“后厨操作流程图”。

在Doris里,查询计划尤其重要。因为它是一个分布式系统,数据分散在多个节点上。一条查询过来,Doris的查询优化器会把它拆解成多个可以并行执行的子任务(Fragment),这些子任务在不同的机器上跑,最后再把结果汇总给你。如果这个“拆解”和“执行”的计划没做好,就很容易出现“一部分机器累死,一部分机器闲死”的情况,查询自然就快不起来。

所以,学会看Doris的查询计划,是你从“只会写SQL”到“能调优SQL”的关键一步。它不再是黑盒,你能清晰地看到数据从哪里扫描、在哪里过滤、如何聚合、怎样在节点间传输。看懂了计划,你就能精准地定位瓶颈:是扫描了太多数据?是聚合计算太重?还是网络传输成了拖累?接下来,我们就手把手教你如何获取并解读这份“执行蓝图”。

2. 庖丁解牛:如何获取与解读Doris查询计划?

拿到查询计划是分析的第一步。Doris提供了两种非常直观的方式,一种叫 EXPLAIN,另一种叫 EXPLAIN GRAPH。我习惯先用 EXPLAIN 看文本逻辑,再用 EXPLAIN GRAPH 看图形化流程,两者结合,心里就特别有谱。

2.1 使用 EXPLAIN:查看文本执行计划

这跟MySQL的用法很像,直接在SQL前加上 EXPLAIN 就行。我们来看一个最简单的例子:

EXPLAIN SELECT siteid, citycode, SUM(pv) FROM user_visit GROUP BY siteid, citycode;

执行后,你会得到一大段文本输出。别慌,我们拆开看。输出的核心是 PLAN FRAGMENT。Doris会把整个执行计划分成若干个片段(Fragment),每个片段可以独立在不同的后端节点(BE)上并行执行。片段之间通过 EXCHANGE 节点来交换数据。

比如,一个典型的聚合查询计划可能长这样:

PLAN FRAGMENT 0
OUTPUT EXPRS: `siteid`, `citycode`, sum(`pv`)
PARTITION: UNPARTITIONED
RESULT SINK
|
|  3:AGGREGATE (merge finalize)
|  |  output: sum(sum(`pv`))
|  |  group by: `siteid`, `citycode`
|  |  cardinality=-1
|  |
|  2:EXCHANGE
|
PLAN FRAGMENT 1
OUTPUT EXPRS:
PARTITION: RANDOM
STREAM DATA SINK
    EXCHANGE ID: 02
    UNPARTITIONED
|
|  1:AGGREGATE (update serialize)
|  |  output: sum(`pv`)
|  |  group by: `siteid`, `citycode`
|  |  cardinality=1
|  |
|  0:OlapScanNode
|     TABLE: user_visit
|     PREAGGREGATION: ON
|     partitions=4/4
|     rollup: user_visit
|     tabletRatio=32/32
|     tabletList=10001,10002...
|     cardinality=10000000
|     avgRowSize=45.0
|     numNodes=10

我来给你翻译一下:

  • PLAN FRAGMENT 1:这是执行的第一阶段。0:OlapScanNode 表示它在扫描 user_visit 表。下面那些 partitionstabletRatio 信息非常关键,它告诉你数据扫描的范围。比如 partitions=4/4 表示所有4个分区都参与了扫描,如果这里写 partitions=1/4,那说明分区裁剪生效了,只扫了1个分区,这是好事。tabletRatio=32/32 表示所有32个tablet(数据分片)都被扫描了。
  • 1:AGGREGATE (update serialize):扫描完数据,立刻在本地(每个BE上)进行初步的聚合(sum(pv)),并按 siteid, citycode 分组。注意这里的 cardinality=1 是个估计值,实际要看分组后的行数。
  • STREAM DATA SINK ... EXCHANGE ID: 02:第一阶段的结果,会通过一个数据流发送器(DataStreamSink)发送出去,交换ID是02。
  • PLAN FRAGMENT 0:这是执行的第二阶段(最终阶段)。2:EXCHANGE 节点接收来自第一阶段的数据。
  • 3:AGGREGATE (merge finalize):这里进行最终的聚合合并。因为第一阶段已经在每个BE上做了预聚合,这里只需要把各个BE上相同
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值