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

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

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

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

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

class name age
102 EEE 10
102 GGG 10
103 DDD 8
103 BBB 9
103 AAA 10
103 CCC 10
103 GGG 11

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、结果

Clickhouse 分布式子查询——global in/join(慎用慎用)_第1张图片
Clickhouse 分布式子查询——global in/join(慎用慎用)_第2张图片
Clickhouse 分布式子查询——global in/join(慎用慎用)_第3张图片
Clickhouse 分布式子查询——global in/join(慎用慎用)_第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)