Clickhouse 分布式子查询——global in/join(慎用慎用)
Posted 羲凡丞相
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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、结果
问:用 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优化