總結轉載
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條件和子查詢條件,普通的就不會查出來。