总结转载
https://clickhouse.tech/docs/zh/sql-reference/operators/in/#select-distributed-subqueries
SELECT uniq(UserID) FROM distributed_table WHERE CounterID = 101500 AND UserID IN (SELECT UserID FROM distributed_table WHERE CounterID = 34)
这条语句不使用global in 的话 前面一段查到一个UserID就会跑到子查询里面看in不in 子查询是分布式的 就会接收到这个查询请求之后下发到每个本地表 比如前面的UserID有n个 分布的本地表有n个 那么复杂度就是 n^2
但是用了global in 之后 就会将子查询符合条件的UserID全部查出来之后放到内存做临时表 一次性全部分发给请求的各个节点的本地表执行前面那段 查出符合条件的数据 请求的复杂度就只有n了
所以使用global的前提条件就是左表是分布式表,右表是小表
备注:
SELECT uniq(UserID) FROM distributed_table WHERE CounterID = 101500 AND UserID IN (SELECT UserID FROM local_table WHERE CounterID = 34) 该语句时会向集群各个节点发送 SELECT uniq(UserID) FROM local_table WHERE CounterID = 101500 AND UserID IN (SELECT UserID FROM local_table WHERE CounterID = 34) 这样的查询请求,复杂度是n
使用注意:
- 创建临时表时,数据不是唯一的,为了减少通过网络传输的数据量,请在子查询中使用DISTINCT(你不需要在普通的IN中这么做)
- 临时表将发送到所有远程服务器。其中传输不考虑网络的拓扑结构。例如,如果你有10个远程服务器存在与请求服务器非常远的数据中心中,则数据将通过通道发送数据到远程数据中心10次。使用GLOBAL IN时应避免大数据集。
- 当使用global…JOIN,首先会在请求者服务器运行一个子查询来计右表(right table)。将此临时表传递给每个远程服务器,并使用传输的临时数据在其上运行查询。会出现网络传输,因此尽量将小表放在右表。
https://blog.csdn.net/weixin_42003671/article/details/116533735
这个例子说明了 分布式子查询在使用global in/join 是sql的执行顺序和in不一样
普通的是按照执行顺序查出符合条件的数据,例子中的 'GGG' 存在重复的数据,在普通的in/join中会筛选符合子查询和where条件的数据
使用了global之后,会先选出符合子查询条件的数据,然后再根据where的判断条件晒出数据,这个时候一条 'GGG' 符合子查询条件,筛出来之后在分布式表中存在一条满足where条件,这就会被选出来,但是这条数据并不同时满足where条件和子查询条件,普通的就不会查出来。