insert select查单分区没有shuffle,但查多个分区就会shuffle

insert into table1 select xxx from table2 where f_p_date in (xxx,xxx)
table1和table2,表引擎表结构都一样,分区数和分桶键、分桶数也都一样。
where条件里table2只指定一个分区,sql执行过程没有shuffle,
但where条件里分区指定的个数大于等于2,sql执行过程就会shuffle,耗时大幅升高。

【场景1】
不加分区过滤,查table2全量数据,写入table1。耗时40min,profile中DataStreamSender下的ShuffleDispatchTime占了总耗时90%以上。


profile:
profile_shuffle_1.yml (114.9 KB)

【场景2】
只查询table2一天的分区,写入table1。耗时1s,没有shuffle,profile中无DataStreamSender,无EXCHANGE_NODE。

profile:
profile_shuffle_2.yml (71.6 KB)

【场景3】
查询table2两天的分区,写入table1。耗时3s,profile中DataStreamSender下的ShuffleDispatchTime占了总耗时50%以上。



profile:
profile_shuffle_3.yml (253.7 KB)

请问有什么方法可以在select table2多个分区insert到table1时避免shuffle呢

我另外测了下select table1再insert到table1本表,也是一样的结果,单分区无shuffle,多分区有shuffle。同一张表数据分布是一模一样的,为什么还会有shuffle呢,我这只是简单的insert select。
【场景a】
单分区,无shuffle


profile:
profile_shuffle_a.yml (66.6 KB)
【场景b】
两个分区,有shuffle


profile:
profile_shuffle_b.yml (253.2 KB)

试了下指定分区insert,多个分区一样会有shuffle

@shemplle @JiangLai 大佬们可否麻烦帮忙看下,感谢~

看了下确实是在网络shuffle占用了太多的时间。目前建议是按照分区来进行导入,比如写成脚本,每次导入一个分区这个样子。
另外咱们的建表语句,需要调整下有很大的数据倾斜。

另外咱们的表模型是什么呢?

是聚合模型表,排序键为分区字段f_p_date和分桶键forder_id,分桶数20。
以下是建表语句:
CREATE TABLE test_dws.dws_ord_order_info_hf

(

f_p_date date NOT NULL ,

forder_id string NOT NULL ,

fpay_way int REPLACE_IF_NOT_NULL ,

fcreate_time_odtoi datetime REPLACE_IF_NOT_NULL ,

ftotal_amount_odtoi decimal(15,2) REPLACE_IF_NOT_NULL ,

ftotal_firstpay_odtoi decimal(15,2) REPLACE_IF_NOT_NULL ,

finner_flag int REPLACE_IF_NOT_NULL ,

fuid_odtoi int REPLACE_IF_NOT_NULL ,

fmax_fq_num_odtoi int REPLACE_IF_NOT_NULL ,

forder_state_odtoi int REPLACE_IF_NOT_NULL ,

forder_type_odtoi int REPLACE_IF_NOT_NULL ,

factual_year_ratio_odtoi decimal(4,4) REPLACE_IF_NOT_NULL ,

fbefore_year_ratio_odtoi decimal(4,4) REPLACE_IF_NOT_NULL ,

faccount_date_odtoi string REPLACE_IF_NOT_NULL ,

ffee_ratio decimal(6,6) REPLACE_IF_NOT_NULL ,

forder_id_cclodtlo string REPLACE_IF_NOT_NULL ,

fmax_fq_num_cclodtlo string REPLACE_IF_NOT_NULL ,

fcreate_time_cclodtlo datetime REPLACE_IF_NOT_NULL ,

ftotal_amount_cclodtlo decimal(15,2) REPLACE_IF_NOT_NULL ,

fuid_cclodtlo int REPLACE_IF_NOT_NULL ,

fbusiness_own_cclodtlo string REPLACE_IF_NOT_NULL ,

factual_year_ratio_cclodtlo decimal(4,4) REPLACE_IF_NOT_NULL ,

fbefore_year_ratio_cclodtlo decimal(4,4) REPLACE_IF_NOT_NULL ,

forder_type_cclodtlo int REPLACE_IF_NOT_NULL ,

forder_state_cclodtlo int REPLACE_IF_NOT_NULL ,

forder_id_ocdtoci string REPLACE_IF_NOT_NULL ,

fmax_fq_num_ocdtoci string REPLACE_IF_NOT_NULL ,

fcreate_time_ocdtoci datetime REPLACE_IF_NOT_NULL ,

ftotal_amount_ocdtoci decimal(15,2) REPLACE_IF_NOT_NULL ,

fuid_ocdtoci int REPLACE_IF_NOT_NULL ,

fbusiness_own_ocdtoci string REPLACE_IF_NOT_NULL ,

factual_year_ratio_ocdtoci decimal(4,4) REPLACE_IF_NOT_NULL ,

fbefore_year_ratio_ocdtoci decimal(4,4) REPLACE_IF_NOT_NULL ,

forder_type_ocdtoci int REPLACE_IF_NOT_NULL ,

forder_state_ocdtoci int REPLACE_IF_NOT_NULL ,

fcreate_time datetime REPLACE_IF_NOT_NULL ,

ftotal_amount decimal(15,2) REPLACE_IF_NOT_NULL ,

floan_amount decimal(15,2) REPLACE_IF_NOT_NULL ,

fuid int REPLACE_IF_NOT_NULL ,

fis_test_order int REPLACE_IF_NOT_NULL ,

fis_loan_order_flag int REPLACE_IF_NOT_NULL ,

fmax_fq_num int REPLACE_IF_NOT_NULL ,

forder_state int REPLACE_IF_NOT_NULL ,

fbefore_year_ratio decimal(4,4) REPLACE_IF_NOT_NULL ,

factual_year_ratio decimal(4,4) REPLACE_IF_NOT_NULL ,

fis_first_flag int REPLACE_IF_NOT_NULL ,

ffirst_create_time datetime REPLACE_IF_NOT_NULL ,

ftrans_mob string REPLACE_IF_NOT_NULL ,

fis_platform_succ_flag1 int REPLACE_IF_NOT_NULL ,

fnew_order_user_type string REPLACE_IF_NOT_NULL ,

forder_type int REPLACE_IF_NOT_NULL ,

focnt int REPLACE_IF_NOT_NULL ,

fucnt int REPLACE_IF_NOT_NULL ,

fis_tj_order_flag int REPLACE_IF_NOT_NULL ,

fsale_type_odtoi int REPLACE_IF_NOT_NULL ,

fsku_id_odtoi string REPLACE_IF_NOT_NULL ,

fextend_info_odtoi string REPLACE_IF_NOT_NULL ,

fis_maiya_flag int REPLACE_IF_NOT_NULL ,

fmerch_id_pdtpo string REPLACE_IF_NOT_NULL ,

fcreate_time_pdtpo datetime REPLACE_IF_NOT_NULL ,

fmerch_id_aoodtoi string REPLACE_IF_NOT_NULL ,

fcreate_time_aoodtoi datetime REPLACE_IF_NOT_NULL ,

fetl_time DATETIME MAX,

flast_modify_time DATETIME MAX

)AGGREGATE KEY(f_p_date,forder_id)

PARTITION BY RANGE(f_p_date)(

START ("2013-01-01") END ("2021-01-01") EVERY (INTERVAL 1 YEAR),

START ("2021-01-01") END ("2022-01-01") EVERY (INTERVAL 1 MONTH),

START ("2022-01-01") END ("2022-07-01") EVERY (INTERVAL 1 day)

)

DISTRIBUTED BY HASH(forder_id) BUCKETS 20

PROPERTIES(

-- "colocate_with" = "order_cg",

"dynamic_partition.enable" = "true",

"dynamic_partition.time_unit" = "DAY",

"dynamic_partition.end" = "3",

"dynamic_partition.prefix" = "p",

"dynamic_partition.buckets" = "20",

"replication_num"="3");

查询和写入都是同张表,按理说数据分布都一模一样,而且sql只是简单的inset select,为什么查2个及以上的分区会有shuffle呢

这个你需要看参数 WaitResponseTime 主要时间花费在了网络传输上


具体的可以参考下这篇文章

image 主要耗时在ShuffleDispatchTime上了,请问查询和写入都是同张表,按理说数据分布都一模一样,为什么查2个及以上的分区会有shuffle呢

多分区可能没做本地化直接写入的优化(要求分片键一致),我们再确认下。

DUP模型可以避免shuffle,PK和UNIQ模型都需要shuffle,否则无法保证正确性