PowerData

编者荐语:

来自PowerData-徐振超同学的精彩文章!

以下文章来源于数据极客圈 ,作者徐振超

[

数据极客圈 .

一入大数据深似海?别怕!“数据极客圈” 就是你的救生圈,走对圈子跟对人,趣析数据、畅聊趋势,快进圈子!

](#)

在上篇秘籍中,我们深入挖掘了 Doris 查询优化里 Schema 设计、索引优化以及分区裁剪优化扫表的关键策略,这些策略就像给 Doris 这位 “数据大侠” 配上了神兵利器,战斗力直线飙升。今天,咱们接着探索下篇,看看还有哪些进阶技巧,能让 Doris 在数据处理的战场上大杀四方,一路 “狂飙”。

一、同步物化视图:数据查询的 “秘密武器”

同步物化视图就像是一个超级 “数据仓库”,它可不是普通的表,而是提前按照我们定义好的 SELECT 语句,把数据算好存起来。它的存在,就是为了满足我们对原始明细数据各种维度分析的需求,同时还能让固定维度的分析查询快如闪电。

1.1 适用场景:这些情况它最拿手

混合需求场景:当你的分析需求既要查明细数据,又要做固定维度查询时,同步物化视图就像一个全能助手,能轻松应对。

少量数据查询场景:要是查询只涉及表中的少部分列或行,它能精准定位,快速出击,避免在大量数据中 “迷路”。

耗时操作场景:遇到查询里包含像长时间聚合操作这种耗时的 “硬骨头”,同步物化视图提前准备好结果,直接 “交卷”,大大节省时间。

索引匹配场景:当查询需要匹配不同的前缀索引,它也能巧妙应对,让查询顺利进行。

重复子查询场景:对于那些频繁重复使用相同子查询结果的查询,它简直就是 “救星”,直接拿缓存结果,性能提升显著。

而且,Doris 会自动帮我们维护物化视图的数据,保证基础表和物化视图表的数据一致,就像有个勤劳的小管家,不用我们操心额外的维护成本。查询的时候,系统会像个聪明的导航,自动找到最优的物化视图,直接从中读取数据。

1.2 注意事项:使用前要牢记

避免重复创建:可别在同一张表上创建多个长得差不多的物化视图,这就好比在一个小房间里放多个功能相似的家具,容易挤得慌,还可能导致多个物化视图冲突,让查询命中失败。

1.3 案例展示:实战见真章

假设我们有一张销售记录明细表 sales\_records,上面详细记录了每笔交易的各种信息,像交易 ID、销售员 ID、售卖门店 ID、销售日期还有交易金额。我们经常要分析不同门店的销售量。

为了让这些查询跑得更快,我们来创建一个物化视图 store\_amt,它按售卖门店分组,把同一门店的销售额加起来。具体步骤如下:

创建同步物化视图:用下面的 SQL 语句创建物化视图 store\_amt:

CREATE MATERIALIZED VIEW store_amt AS SELECT store_id, SUM(sale_amt) FROM sales_records GROUP BY store_id;

提交创建任务后,Doris 会在后台偷偷构建这个物化视图。我们可以用下面的命令查看创建进度:

SHOW ALTER TABLE MATERIALIZED VIEW FROM db_name;

当 State 字段变成 FINISHED,就说明 store\_amt 物化视图创建成功啦。

  1. 透明改写:物化视图建好后,我们查询不同门店销售量时,Doris 会自动找到 store\_amt 物化视图,直接读取预先聚合好的数据,查询效率瞬间起飞。查询语句是这样的:

SELECT store_id, SUM(sale_amt) FROM sales_records GROUP BY store_id;

我们还能用 EXPLAIN 命令检查查询有没有成功命中物化视图:

EXPLAIN SELECT store_id, SUM(sale_amt) FROM sales_records GROUP BY store_id;

在执行计划的末尾,如果看到类似下面这样的内容,那就表示查询成功命中 store\_amt 物化视图:

TABLE: default_cluster:test.sales_records(store_amt), PREAGGREGATION: ON

通过这些步骤,我们就利用同步物化视图优化了查询性能,让数据分析效率大幅提升。

二、使用异步物化视图透明改写:高效查询的 “新捷径”

异步物化视图用的是基于 SPJG(SELECT - PROJECT - JOIN - GROUP - BY)模式的透明改写算法,这算法就像一个聪明的侦探,能分析查询 SQL 的结构信息,自动找到合适的物化视图,还能把查询 SQL 改写成利用最优物化视图的形式,用预计算的物化视图结果,大大提高查询性能,降低计算成本。

2.1 案例实操:一步步看明白

创建基础表:先创建 tpch 数据库,再在里面创建 orders 和 lineitem 两张表,并且插入数据。

CREATE DATABASEIFNOTEXISTS tpch; USE tpch; CREATETABLEIFNOTEXISTS orders (    o_orderkey       integernotnull,    o_custkey        integernotnull,    o_orderstatus    char(1) notnull,    o_totalprice     decimalv3(15,2) notnull,    o_orderdate      datenotnull,    o_orderpriority  char(15) notnull,    o_clerk          char(15) notnull,    o_shippriority   integernotnull,    o_comment        varchar(79) notnull ) DUPLICATEKEY(o_orderkey, o_custkey) PARTITIONBYRANGE(o_orderdate)(    FROM ('2023-10-17') TO ('2023-10-20') INTERVAL1DAY ) DISTRIBUTEDBYHASH(o_orderkey) BUCKETS 3 PROPERTIES ("replication_num" = "1"); INSERTINTO orders VALUES    (1, 1, 'o', 99.5, '2023-10-17', 'a', 'b', 1, 'yy'),    (2, 2, 'o', 109.2, '2023-10-18', 'c','d',2, 'mm'),    (3, 3, 'o', 99.5, '2023-10-19', 'a', 'b', 1, 'yy'); CREATETABLEIFNOTEXISTS lineitem (    l_orderkey    integernotnull,    l_partkey     integernotnull,    l_suppkey     integernotnull,    l_linenumber  integernotnull,    l_quantity    decimalv3(15,2) notnull,    l_extendedprice  decimalv3(15,2) notnull,    l_discount    decimalv3(15,2) notnull,    l_tax         decimalv3(15,2) notnull,    l_returnflag  char(1) notnull,    l_linestatus  char(1) notnull,    l_shipdate    datenotnull,    l_commitdate  datenotnull,    l_receiptdate datenotnull,    l_shipinstruct char(25) notnull,    l_shipmode     char(10) notnull,    l_comment      varchar(44) notnull ) DUPLICATEKEY(l_orderkey, l_partkey, l_suppkey, l_linenumber) PARTITIONBYRANGE(l_shipdate) (FROM ('2023-10-17') TO ('2023-10-20') INTERVAL1DAY) DISTRIBUTEDBYHASH(l_orderkey) BUCKETS 3 PROPERTIES ("replication_num" = "1"); INSERTINTO lineitem VALUES    (1, 2, 3, 4, 5.5, 6.5, 7.5, 8.5, 'o', 'k', '2023-10-17', '2023-10-17', '2023-10-17', 'a', 'b', 'yyyyyyyyy'),    (2, 2, 3, 4, 5.5, 6.5, 7.5, 8.5, 'o', 'k', '2023-10-18', '2023-10-18', '2023-10-18', 'a', 'b', 'yyyyyyyyy'),    (3, 2, 3, 6, 7.5, 8.5, 9.5, 10.5, 'k', 'o', '2023-10-19', '2023-10-19', '2023-10-19', 'c', 'd', 'xxxxxxxxx');

创建异步物化视图:基于 tpch benchmark 里的原始表,创建一个异步物化视图 mv1。

CREATE MATERIALIZEDVIEW mv1   BUILDIMMEDIATEREFRESHCOMPLETEONMANUAL PARTITIONBY(l_shipdate)  DISTRIBUTEDBY RANDOM BUCKETS 2 PROPERTIES ('replication_num' = '1')   AS SELECT l_shipdate, o_orderdate, l_partkey, l_suppkey, SUM(o_totalprice) AS sum_total  FROM lineitem  LEFTJOIN orders ON lineitem.l_orderkey = orders.o_orderkey AND l_shipdate = o_orderdate  GROUPBY l_shipdate,  o_orderdate,  l_partkey,  l_suppkey;

使用物化视图进行透明改写:用 explain shape plan 查看查询计划,能看到经过 mv1 透明改写后的计划已经命中 mv1。

mysql> explain shape plan SELECT l_shipdate, SUM(o_totalprice) AS total_price    -> FROM lineitem    -> LEFTJOIN orders ON lineitem.l_orderkey = orders.o_orderkey AND l_shipdate = o_orderdate    -> WHERE l_partkey = 2AND l_suppkey = 3    -> GROUPBY l_shipdate; +-------------------------------------------------------------------+ | ExplainString(Nereids Planner)                                   | +-------------------------------------------------------------------+ | PhysicalResultSink                                                | | --PhysicalDistribute[DistributionSpecGather]                      | | ----PhysicalProject                                               | | ------hashAgg[GLOBAL]                                             | | --------PhysicalDistribute[DistributionSpecHash]                  | | ----------hashAgg[LOCAL]                                          | | ------------PhysicalProject                                       | | --------------filter((mv1.l_partkey = 2) and (mv1.l_suppkey = 3)) | | ----------------PhysicalOlapScan[mv1]                             | +-------------------------------------------------------------------+

通过 explain 也能查看当前计划经过 mv 改写的状态,比如有没有命中,命中的是哪个 mv 等信息。

2.2 总结与使用建议

通过使用异步物化视图,复杂的连接和聚合查询性能能大幅提升。使用时要注意:

预计算优势:它提前算好查询结果存起来,复杂查询频繁执行时,不用每次都重复计算,超省时间。

减少联接操作:把多个表数据合并到一个视图,查询时减少联接操作,效率自然提高。

自动更新:基表数据变了,物化视图自动更新,保证查询结果是最新的。

空间开销:要额外存储空间存预计算结果,创建时得权衡性能提升和空间消耗。

维护成本:维护物化视图要系统资源和时间,基表频繁更新,物化视图更新开销大,得选合适刷新策略。

适用场景:适合数据变化频率低、查询频率高的场景,数据经常变,实时计算可能更好。

合理利用异步物化视图,能让数据库查询性能在复杂查询和大数据量情况下大幅改善,不过也要综合考虑存储、维护等因素,平衡好性能和成本。

三、使用 Colocate Group 优化 Join:Join 操作的 “高速通道”

Colocate Group 是一种超高效的 Join 方式,它就像给执行引擎修了一条 “高速通道”,能有效避开 Join 操作中数据的 shuffle 开销。具体原理和案例可以参考 Colocation Join。

3.1 注意事项:特殊情况要留意

有时候,就算成功建立了 Colocate Group,执行计划可能还是显示为 Shuffle Join 或 Bucket Shuffle Join。这通常是 Doris 在整理数据,比如在 BE 间迁移 tablet,让数据在多个 BE 之间分布更均衡。

我们可以用命令 show proc "/colocation\_group"; 查看 Colocate Group 状态,要是 IsStable 显示 false,那就说明有 Colocate Group 不可用。

四、使用 Hint 调整 Join Shuffle 方式:定制 Join 的 “秘密指令”

Doris 支持用 Hint 来调整 Join 操作中数据 Shuffle 的类型,就像给 Doris 下了定制化的 “秘密指令”,优化查询性能。不过要注意,现在 Doris 基本能自动优化各种场景性能,大部分情况不用我们手动控制 Hint 调优,这部分主要给专业调优人员看,业务人员了解就行。

目前,Doris 有两种独立的 Distribute Hint,[shuffle] 和 [broadcast],用来指定 Join 右表的 Distribute Type。Distribute Type 放在 Join 右表前面,用 [] 括起来。同时,Doris 还能通过 Leading Hint 配合 Distribute Hint,指定 shuffle 方式。

4.1 示例展示:指令怎么用

SELECT COUNT(*) FROM t2 JOIN [broadcast] t1 ON t1.c1 = t2.c2; SELECT COUNT(*) FROM t2 JOIN [shuffle] t1 ON t1.c1 = t2.c2;

4.2 案例分析:效果看得见

我们用同一个例子看 Distribute Hint 的使用方法。

EXPLAIN SHAPE PLAN SELECT COUNT(*) FROM t1 JOIN t2 ON t1.c1 = t2.c2;

原始 SQL 的计划里,t1 连接 t2 用的是 hash distribute,也就是 DistributionSpecHash 方式。

+----------------------------------------------------------------------------------+  | ExplainString (Nereids Planner)                                                 |  +----------------------------------------------------------------------------------+  | PhysicalResultSink                                                               |  | --hashAgg [GLOBAL]                                                               |  | ----PhysicalDistribute [DistributionSpecGather]                                  |  | ------hashAgg [LOCAL]                                                            |  | --------PhysicalProject                                                          |  | ----------hashJoin [INNER_JOIN] hashCondition=((t1.c1 = t2.c2)) otherCondition=()|  | ------------PhysicalProject                                                      |  | --------------PhysicalOlapScan [t1]                                              |  | ------------PhysicalDistribute [DistributionSpecHash]                            |  | --------------PhysicalProject                                                    |  | ----------------PhysicalOlapScan [t2]                                            |  +----------------------------------------------------------------------------------+

加入 [broadcast] hint 后:

EXPLAIN SHAPE PLAN SELECT COUNT(*) FROM t1 JOIN [broadcast] t2 ON t1.c1 = t2.c2;

可以看到 t1 连接 t2 的分发方式变成了 broadcast,也就是 DistributionSpecReplicated 方式。

+----------------------------------------------------------------------------------+  | Explain String (Nereids Planner)                                                 |  +----------------------------------------------------------------------------------+  | PhysicalResultSink                                                               |  | --hashAgg [GLOBAL]                                                               |  | ----PhysicalDistribute [DistributionSpecGather]                                  |  | ------hashAgg [LOCAL]                                                            |  | --------PhysicalProject                                                          |  | ----------hashJoin [INNER_JOIN] hashCondition=((t1.c1 = t2.c2)) otherCondition=()|  | ------------PhysicalProject                                                      |  | --------------PhysicalOlapScan [t1]                                              |  | ------------PhysicalDistribute [DistributionSpecReplicated]                      |  | --------------PhysicalProject                                                    |  | ----------------PhysicalOlapScan [t2]                                            | +----------------------------------------------------------------------------------+

五、使用 Hint 控制代价改写:优化器的 “精细调控”

查询优化器生成执行计划时,会用基于规则的优化(RBO)和基于代价的优化(CBO)两类规则。RBO 像个按套路出牌的高手,通过预定义的启发式规则改进查询计划,不考虑数据统计信息,比如谓词下推、投影下推。CBO 则像个精打细算的商人,利用数据统计信息估算不同执行计划的代价,选代价最小的执行,像访问路径、连接算法的选择。

有时候,数据库管理员或开发人员想更精细控制查询优化过程,这就可以用查询 Hint 管理 CBO 规则。要注意,Doris 通常能自动优化性能,多数情况不用手工控制 Hint,这部分主要给专业调优人员。

5.1 CBO 规则控制 Hint 语法

SELECT /*+ USE_CBO_RULE(rule1, rule2, ...) */ ...

这个 Hint 紧跟在 SELECT 关键字后面,括号里写要启用的规则名称(规则名称不区分大小写)。目前 Doris 优化器支持好几种代价改写规则,能用 USE\_CBO\_RULE hint 显式启用,比如 PUSH\_DOWN\_AGG\_THROUGH\_JOIN \`PUSH\_DOWN\_AGG\_THROUGH

5.2 案例呈现:规则如何发力

咱们来看一个查询示例:

explain shape plan    select /*+ USE_CBO_RULE(push_down_agg_through_join_one_side) */            a.event_id,            b.group_id,            COUNT(a.event_id)    from a    join b on            a.device_id = b.device_id    group by            a.event_id,            b.group_id    ;

在这个例子里,我们启用了一个聚合下推的 CBO 规则。这一操作就像是给数据处理流程开辟了一条 “绿色通道”,使得表 a 能够在连接操作之前就进行提前聚合。如此一来,连接时需要处理的数据量大幅减少,从而有效降低了连接的开销,让整个查询过程如同坐上了 “加速快车”,得以快速推进。下压后的计划如下:

PhysicalResultSink --hashAgg[GLOBAL] ----hashAgg[LOCAL] ------hashJoin[INNER_JOIN] hashCondition=((a.device_id = b.device_id)) otherCondition=() --------hashAgg[LOCAL] ----------PhysicalOlapScan[a] --------filter((cast(experiment_id as DOUBLE) = 73.0)) ----------PhysicalOlapScan[b]

通过这个案例可以清晰地看到,合理运用 CBO 规则控制 Hint,能够精准地对查询优化过程进行干预,从而显著提升查询性能。

六、使用 Leading Hint 控制 Join 顺序:查询的 “定制导航”

Leading Hint 特性就像是为查询配备了一个 “定制导航”,允许专业调优人员手工指定查询中表的连接顺序,在特定场景下,这一功能对优化复杂查询性能有着显著效果。不过要清楚,当下 Doris 在大多数场景下都能凭借自身强大的自适应能力,将各种查询场景的性能优化得相当出色,所以一般情况下业务人员无需手动通过 Hint 来调整。这部分内容主要是为专业调优人员准备的,业务人员简单知晓即可。

6.1 案例解读:不同场景下的运用

案例 1:调整左右表顺序

对于下面这个查询:

mysql> explain shape plan select from t1 join t2 on t1.c1 = t2.c2; +------------------------------------------------------------------------------+ | _Explain_ String(Nereids Planner)                                              | +------------------------------------------------------------------------------+ | PhysicalResultSink                                                           | | --PhysicalDistribute[DistributionSpecGather]                                 | | ----PhysicalProject                                                          | | ------hashJoin[INNER_JOIN] hashCondition=((t1.c1 = t2.c2)) otherCondition=() | | --------PhysicalOlapScan[t1]                                                 | | --------PhysicalDistribute[DistributionSpecHash]                             | | ----------PhysicalOlapScan[t2]                                               | +------------------------------------------------------------------------------+

使用 Leading Hint,可以强制将 join order 指定为 t2 join t1,从而调整原始的连接顺序。

mysql> explain shape plan select/*+ leading(t2 t1) */ * from t1 join t2 on t1.c1 = t2.c2; +------------------------------------------------------------------------------+ | _Explain_ String(Nereids Planner)                                              | +------------------------------------------------------------------------------+ | PhysicalResultSink                                                           | | --PhysicalDistribute[DistributionSpecGather]                                 | | ----PhysicalProject                                                          | | ------hashJoin[INNER_JOIN] hashCondition=((t1.c1 = t2.c2)) otherCondition=() | | --------PhysicalOlapScan[t2]                                                 | | --------PhysicalDistribute[DistributionSpecHash]                             | | ----------PhysicalOlapScan[t1]                                               | |                                                                              | | Hint log:                                                                    | | Used: leading(t2 t1)                                                         | | UnUsed:                                                                      | | SyntaxError:                                                                 | +------------------------------------------------------------------------------+

从 Hint log 中可以清楚地看到应用成功的 hint:Used: leading (t2 t1) 。这表明通过 Leading Hint,我们成功地按照需求改变了表的连接顺序。

案例 2:强制生成左深树

mysql> explain shape plan select/*+ leading(t1 t2 t3) */ * from t1 join t2 on t1.c1 = t2.c2 join t3 on t2.c2 = t3.c3; +--------------------------------------------------------------------------------+ | _Explain_ String(Nereids Planner)                                                | +--------------------------------------------------------------------------------+ | PhysicalResultSink                                                             | | --PhysicalDistribute[DistributionSpecGather]                                   | | ----PhysicalProject                                                            | | ------hashJoin[INNER_JOIN] hashCondition=((t2.c2 = t3.c3)) otherCondition=()   | | --------hashJoin[INNER_JOIN] hashCondition=((t1.c1 = t2.c2)) otherCondition=() | | ----------PhysicalOlapScan[t1]                                                 | | ----------PhysicalDistribute[DistributionSpecHash]                             | | ------------PhysicalOlapScan[t2]                                               | | --------PhysicalDistribute[DistributionSpecHash]                               | | ----------PhysicalOlapScan[t3]                                                 | |                                                                                | | Hint log:                                                                      | | Used: leading(t1 t2 t3)                                                        | | UnUsed:                                                                        | | SyntaxError:                                                                   | +--------------------------------------------------------------------------------+

同样,从 Hint log 中我们能看到应用成功的 hint:Used: leading (t1 t2 t3) 。这说明通过指定的 Leading Hint,成功强制生成了左深树结构的查询计划。

案例 3:强制生成右深树

mysql> explain shape plan select/*+ leading(t1 {t2 t3}) */ * from t1 join t2 on t1.c1 = t2.c2 join t3 on t2.c2 = t3.c3; +----------------------------------------------------------------------------------+ | _Explain_ String(Nereids Planner)                                                  | +----------------------------------------------------------------------------------+ | PhysicalResultSink                                                               | | --PhysicalDistribute[DistributionSpecGather]                                     | | ----PhysicalProject                                                              | | ------hashJoin[INNER_JOIN] hashCondition=((t1.c1 = t2.c2)) otherCondition=()     | | --------PhysicalOlapScan[t1]                                                     | | --------PhysicalDistribute[DistributionSpecHash]                                 | | ----------hashJoin[INNER_JOIN] hashCondition=((t2.c2 = t3.c3)) otherCondition=() | | ------------PhysicalOlapScan[t2]                                                 | | ------------PhysicalDistribute[DistributionSpecHash]                             | | --------------PhysicalOlapScan[t3]                                               | |                                                                                  | | Hint log:                                                                        | | Used: leading(t1 { t2 t3 })                                                      | | UnUsed:                                                                          | | SyntaxError:                                                                     | +----------------------------------------------------------------------------------+

这里 Hint log 展示了应用成功的 hint:Used: leading (t1 { t2 t3}) ,意味着通过特定的 Leading Hint 设置,成功实现了强制生成右深树结构的查询计划。

案例 4:强制生成 bushy 树

mysql> explain shape plan select/*+ leading({t1 t2} {t3 t4}) */ * from t1 join t2 on t1.c1 = t2.c2 join t3 on t2.c2 = t3.c3 join t4 on t3.c3 = t4.c4; +-----------------------------------------------+ | _Explain_ String                                | +-----------------------------------------------+ | PhysicalResultSink                            | | --PhysicalDistribute                          | | ----PhysicalProject                           | | ------hashJoin[INNER_JOIN](t2.c2 = t3.c3)     | | --------hashJoin[INNER_JOIN](t1.c1 = t2.c2)   | | ----------PhysicalOlapScan[t1]                | | ----------PhysicalDistribute                  | | ------------PhysicalOlapScan[t2]              | | --------PhysicalDistribute                    | | ----------hashJoin[INNER_JOIN](t3.c3 = t4.c4) | | ------------PhysicalOlapScan[t3]              | | ------------PhysicalDistribute                | | --------------PhysicalOlapScan[t4]            | |                                               | | Used: leading({ t1 t2 } { t3 t4 })            | | UnUsed:                                       | | SyntaxError:                                  | +-----------------------------------------------+

从结果中可以看到,Hint log 展示了应用成功的 hint:Used: leading ({t1 t2} { t3 t4 }) ,这表明通过相应的 Leading Hint 设置,成功强制生成了 bushy 树结构的查询计划。

案例 5:view 作为整体参与连接

mysql>  explain shape plan select/*+ leading(alias t1) */count(*) from t1 join (select c2 from t2 join t3 on t2.c2 = t3.c3) asaliason t1.c1 = alias.c2; +--------------------------------------------------------------------------------------+ | _Explain_ String(Nereids Planner)                                                      | +--------------------------------------------------------------------------------------+ | PhysicalResultSink                                                                   | | --hashAgg[GLOBAL]                                                                    | | ----PhysicalDistribute[DistributionSpecGather]                                       | | ------hashAgg[LOCAL]                                                                 | | --------PhysicalProject                                                              | | ----------hashJoin[INNER_JOIN] hashCondition=((t1.c1 = alias.c2)) otherCondition=()  | | ------------PhysicalProject                                                          | | --------------hashJoin[INNER_JOIN] hashCondition=((t2.c2 = t3.c3)) otherCondition=() | | ----------------PhysicalProject                                                      | | ------------------PhysicalOlapScan[t2]                                               | | ----------------PhysicalDistribute[DistributionSpecHash]                             | | ------------------PhysicalProject                                                    | | --------------------PhysicalOlapScan[t3]                                             | | ------------PhysicalDistribute[DistributionSpecHash]                                 | | --------------PhysicalProject                                                        | | ----------------PhysicalOlapScan[t1]                                                 | |                                                                                      | | Hint log:                                                                            | | Used: leading(alias t1)                                                              | | UnUsed:                                                                              | | SyntaxError:                                                                         | +--------------------------------------------------------------------------------------+

这里的 Hint log 展示了应用成功的 hint:Used: leading (alias t1) ,说明在这种情况下,通过 Leading Hint 成功地让 view 作为一个整体按照指定顺序参与了连接操作。

案例 6:DistributeHint 与 LeadingHint 混用

explain shape plan    select        nation,        o_year,        sum(amount) as sum_profit    from        (            select                /*+ leading(orders shuffle {lineitem shuffle part} shuffle {supplier broadcast nation} shuffle partsupp) */               n_name as nation,                extract(yearfrom o_orderdate) as o_year,                l_extendedprice * (1 - l_discount) - ps_supplycost * l_quantity as amount            from                part,                supplier,                lineitem,                partsupp,                orders,                nation            where                s_suppkey = l_suppkey                and ps_suppkey = l_suppkey                and ps_partkey = l_partkey                and p_partkey = l_partkey                and o_orderkey = l_orderkey                and s_nationkey = n_nationkey                and p_name like'%green%'        ) as profit    groupby        nation,        o_year    orderby        nation,        o_year desc;

上述/*+ leading(orders shuffle {lineitem shuffle part} shuffle {supplier broadcast nation} shuffle partsupp) */这种 hint 指定方式,巧妙地混用了 leading 和 distribute hint 两种格式。其中,leading 用于把控总体的表之间的相对 join 顺序,而 shuffle 和 broadcast 则分别用于指定特定 join 所采用的 shuffle 方式。通过将这两种 Hint 结合使用,专业调优人员能够灵活地对连接顺序和连接方式进行全面控制,从而精准地手工定制出符合用户期望的计划行为。

6.2 使用建议:巧用 Hint 的关键

善用 EXPLAIN:在使用 Leading Hint 时,建议充分利用 EXPLAIN 命令来仔细分析执行计划。这就好比在出发前查看详细的地图,只有这样,才能确保 Leading Hint 能够切实达到我们预期的效果,让查询计划朝着我们期望的方向优化。

动态评估调整:Doris 版本不断升级,业务数据也处于动态变化之中。因此,在这些情况发生时,一定要重新评估 Leading Hint 的效果。就像随着城市的发展,导航路线可能需要适时调整一样,我们要及时记录并根据实际情况对 Leading Hint 进行调整,以保证其始终能为查询性能优化发挥最大作用。

总结

通过对同步物化视图、异步物化视图透明改写、Colocate Group 优化 Join、使用 Hint 调整 Join Shuffle 方式、控制代价改写以及控制 Join 顺序等一系列进阶优化技巧的深入探讨,我们为 Doris 的查询性能优化提供了更为丰富且精细的策略。在实际应用中,可以根据具体的数据特点、业务场景以及性能需求,灵活选择并组合运用这些技巧,让 Doris 在数据处理与查询的征程中一路 “开挂”,高效地为我们的业务赋能。实在搞不定,可以联系社区同学来辅助搞一波~

往期推荐

[

](http://mp.weixin.qq.com/s?__b...

Doris BE节点下线卡住?快速排障技巧全攻略!

Doris查询报错-230?别慌,教你几招秒解!

Doris Tablet 损坏如何应对?能恢复数据吗?

Doris的Stream Load那些事儿,你踩过哪些“坑”?

如何排查 Apache Doris 中 "Failed to commit txn" 导入失败问题?

Doris的Routine Load导入指南 

Doris 导入慢该如何排查和优化

Doris 建表与分区问题全解析

Doris Schema Change 常见问题分析

Doris 查询优化秘籍(上篇):关键优化策略剖析

Doris 磁盘问题全解析:从挂盘到 Trash 问题,一文读懂!

数据极客圈子介绍

圈子1

Apache Doris社区是目前国内最活跃的开源社区(之一)。Apache Doris(Apache 顶级项目) 聚集了世界全国各地的用户与开发人员,致力于打造一个内容完整、持续成长的互联网开发者学习生态圈! 

如果您对Apache Doris感兴趣,可以通过以下入口访问官方网站、社区论坛、GitHub和dev邮件组:

💡官网文档:https://doris.apache.org 

💡社区论坛:https://ask.selectdb.com 

💡GitHub:https://github.com/apache/doris 

💡dev邮件组:mailto:dev@doris.apache.org

      可以加作者微信(Faith\_xzc)直接进Doris官方社区群

圈子2

PowerData是由一群数据从业人员,因为热爱凝聚在一起,以开源精神为基础,组成的数据开源社区。

社区整理了一份每日一题汇总及社区分享PPT,内容涵盖大数据组件、编程语言、数据结构与算法、企业真实面试题等各个领域,帮助您提升自我,成功上岸。

可以加作者微信(Faith\_xzc)直接进PowrData官方社区群

叮咚✨ “数据极客圈” 向你敞开大门,走对圈子跟对人,行业大咖 “唠” 数据,实用锦囊天天有,就缺你咯!快快关注数据极客圈,共同成长!

图片


PowerData
1 声望2 粉丝

PowerData社区官方思否账号