Clickhouse 查询分布式表子查询 (Distributed Subqueries )

官方文档:https://clickhouse.tech/docs/en/sql-reference/operators/in/#select-distributed-subqueries

在分布式表上执行in/join等子查询的时候建议使用global in或global
joins,直接使用普通的in/join可能有数据正确性的问题,直接使用 in 在分布式表又可能导致性能问题。

如我们有3台服务器,每台服务器上有一张叫local_table的表,另外还有一张分布式表distribute_table指向这个loacl_table表。

case1:
在server1上提交查询sql1:

SELECT uniq(UserID) FROM distributed_table

实际上sq1将被翻译成如下在3台服务器上执行,执行完成将结果汇总给到server1上合并,然后在返回给用

SELECT uniq(UserID) FROM local_table

case2:
在server1上提交查询sql2:带子查询

SELECT uniq(UserID) FROM distributed_table WHERE CounterID = 101500 AND UserID IN (SELECT UserID FROM local_table WHERE CounterID = 34)

实际上sq1将被翻译成如下sql在3台服务器上执行,执行完成将结果汇总给到server1上合并,然后在返回给用

SELECT uniq(UserID) FROM local_table WHERE CounterID = 101500 AND UserID IN (SELECT UserID FROM local_table WHERE CounterID = 34)

这种情况数据可能会是错误的,因为每个server上的userId都只有自己服务器上的serverID,如:server1上有userid:1,2 ;server2上有userId:3,4,5,server3上有userId:6,7,8。本来应该在每个local上的 userid in(1,2,3,4,5,6,7,8) ,但是现在只是分别在1上in(1,2),server2上in(3,4,5),server3上in(6,7,8),结果很可能就错误了。

在server1上提交查询Sql3:带子查询但是从分布式表查询

SELECT uniq(UserID) FROM distributed_table WHERE CounterID = 101500 AND UserID IN (SELECT UserID FROM distributed_table WHERE CounterID = 34)

实际上sq1将被翻译成如下sql在3台服务器上执行,但是执行的时候发现有distributed_table,然后又从每台机器上把这个子查询发给3台server查询

SELECT uniq(UserID) FROM local_table WHERE CounterID = 101500 AND UserID IN (SELECT UserID FROM distributed_table WHERE CounterID = 34)

发给3台的子查询

SELECT UserID FROM local_table WHERE CounterID = 34

这样相当于这样一个查询要执行n*n次,n为服务器数量,这个性能会非常低下。

在server1上提交查询Sql3:带子查询使用global in

SELECT uniq(UserID) FROM distributed_table WHERE CounterID = 101500 AND UserID GLOBAL IN (SELECT UserID FROM distributed_table WHERE CounterID = 34)

此时server1将会提交一个子查询

SELECT UserID FROM distributed_table WHERE CounterID = 34

然后在3台服务器上执行如下sql,然后将结果返回给server1结果将会在内存中保存一张临时表

SELECT UserID FROM local_table WHERE CounterID = 34

然后从server1发出整个sql查询

SELECT uniq(UserID) FROM local_table WHERE CounterID = 101500 AND UserID GLOBAL IN _data1

这样整个查询可能只需要执行n*2次,比之前要少很多倍。

注意:
1、使用global in 查询时返回的子查询结果是不去重的,所有数据都会保存到内存临时表中然后发送给各个server进行整个sql查询,这样可能会导致数据量和网络浪费,在查询时可以指定distinct,普通的in查询没有这个问题。
2、同时拷贝数据到其他节点去执行查询时,没有网络带宽流量的限制,可能导致网络资源进展。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值