Clickhouse 分布式子查询——global in/join(慎用慎用)

Posted 羲凡丞相

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Clickhouse 分布式子查询——global in/join(慎用慎用)相关的知识,希望对你有一定的参考价值。

@羲凡——只为了更好的活着

Clickhouse 分布式子查询——global in/join(慎用慎用)

不能一味的追求查询效率,将分布式子查询都改成global in,一定要结合业务逻辑

假设:有一个分布式表,字段班级、姓名、年龄,ck集群有两个分片,查询103班级年龄10岁的人

classnameage
102EEE10
102GGG10
103DDD8
103BBB9
103AAA10
103CCC10
103GGG11

1、建表语句

CREATE TABLE test_db.staff_replica ON CLUSTER your_ck_cluster
(
    class		UInt8
	,name     	LowCardinality(FixedString(3))
	,age        UInt8
)
ENGINE=ReplicatedMergeTree('/clickhouse/tables/{shard}/{database}/{table}', '{replica}')
ORDER BY (class ,name ,age );

CREATE TABLE test_db.staff_all ON CLUSTER your_ck_cluster
AS test_db.staff_replica
ENGINE = Distributed(your_ck_cluster, test_db, staff_replica, rand());

2、数据分别插入两个分片

--插入分片A
insert into staff_replica values(103,'AAA',10),(103,'BBB',9),(103,'GGG',11);
--插入分片B
insert into staff_replica values(103,'CCC',10),(103,'DDD',8),(102,'GGG',10),(102,'EEE',10);

3、查询sql

--普通 in
select * from test_db.staff_all 
where age=10 and name in (select name from test_db.staff_all a where class=103) ;
--global in
select * from test_db.staff_all 
where age=10 and name global in (select name from test_db.staff_all a where class=103) ;
--普通 join
select a.* from test_db.staff_all a 
join (select name from test_db.staff_all a where class=103) b on a.name=b.name
where a.age=10  ;
--global join
select a.* from test_db.staff_all a global 
join (select name from test_db.staff_all a where class=103) b on a.name=b.name
where a.age=10  ;

4、结果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

问:用 global in/join, 为啥102班级的GGG同学也被筛选出来了?

答:分布式子查询在使用global in/join 是sql的执行顺序和in不一样

下面以global in为例,global join的情况也是一样的

a.普通in的执行情况

-- 1.将下面的查询分发到每个分片机器上执行
select * from test_db.staff_replica 
where age=10 and name in (select name from test_db.staff_all a where class=103) ;
--2.将上sql中分布式子查询再拆成本地表,在每台机器上查询
select name from test_db.staff_replica a where class=103
--3.说白了就是将下面的语句执行了n的平方次,n为分片的数量
select * from test_db.staff_replica 
where age=10 and name in (select name from test_db.staff_replica a where class=103) ;

b.global in的执行情况

-- 1.select name from test_db.staff_all a where class=103 的结果存在RAM中的临时表,比如 _data1
--2.将数据_data1和下面的sql请求将被发送到每个执行服务器
select * from test_db.staff_all where age=10 and name global in _data1
语言表达有限,没看懂的可以看一下 官网 关于global in/join的解释

|
|
|

====================================================================

@羲凡——只为了更好的活着

若对博客中有任何问题,欢迎留言交流

以上是关于Clickhouse 分布式子查询——global in/join(慎用慎用)的主要内容,如果未能解决你的问题,请参考以下文章

ClickHouse 分布式原理:Distributed引擎

clickhouse,数据查询与写入优化,分布式子查询优化,外部聚合/排序优化,基于JOIN引擎的优化,SQL优化案例,物化视图提速,查询优化常用经验法则,选择和主键不一样的排序键,数据入库优化(代码

ClickHouse 极简教程分布式下的 IN/JOIN 及 GLOBAL关键字

大数据ClickHouse进阶(二十二):ClickHouse优化

Colocate Join :ClickHouse的一种高性能分布式join查询模型

Colocate Join :ClickHouse的一种高性能分布式join查询模型