Clickhouse分布式查詢IN/JOIN與GLOABL IN GLOABL JOIN的區別


  • 當使用常規IN時,查詢被發送到遠程服務器,並且它們中的每個服務器都在運行子查詢 IN JOIN 條款,除非每個遠程服務器都存有全部數據,否則會造成數據不准確的情況
  • 使用 GLOBAL IN / GLOBAL JOINs,如select * from tablea where xx GLOABL in (select id from  tableb )這樣的形式, 首先從所有的遠程服務器中獲得tableb關於ID的匯總,並將結果收集在臨時表中。 然后將臨時表發送到每個遠程服務器,其中使用此臨時數據運行查詢。

對於非分布式查詢,請使用常規 IN / JOIN.
在使用子查詢時要小心 IN / JOIN 用於分布式查詢處理的子句。讓我們來看看一些例子。

假設集群中的每個服務器都有一個正常的 local_table. 每個服務器還具有 distributed_table表與 分布 類型。

對於查詢 distributed_table,查詢將被發送到所有遠程服務器,並使用以下命令在其上運行 local_table.
例如,查詢

SELECT uniq(UserID) FROM distributed_table

將被發送到所有遠程服務器

SELECT uniq(UserID) FROM local_table

並且並行運行它們中的每一個,直到達到可以結合中間結果的階段。 然后將中間結果返回給請求者服務器並在其上合並,並
將最終結果發送給客戶端。


現在讓我們執行一個查詢IN:

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

   計算兩個網站的受眾的交集。
注意
請記住,下面描述的算法可能會有不同的工作方式取決於 設置 distributed_product_mode 設置。
此查詢將以下列方式發送到所有遠程服務器

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

換句話說,IN子句中的數據集將在每台服務器上獨立收集,僅在每台服務器上本地存儲的數據中收集。
如果您已經為此情況做好准備,並且已經將數據分散到群集服務器上,以便單個用戶Id的數據完全駐留在單個服務器上,則這
將正常和最佳地工作。 在這種情況下,所有必要的數據將在每台服務器上本地提供。 否則,結果將是不准確的。 我們將查詢
的這種變體稱為 “local IN”.


若要更正數據在群集服務器上隨機傳播時查詢的工作方式,可以指定 distributed_table 在子查詢中。 查詢如下所示:

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

此查詢將以下列方式發送到所有遠程服務器

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

子查詢將開始在每個遠程服務器上運行。 由於子查詢使用分布式表,因此每個遠程服務器上的子查詢將重新發送到每個遠程
服務器

SELECT UserID FROM local_table WHERE CounterID = 34

 

例如,如果您有100台服務器的集群,則執行整個查詢將需要10,000個基本請求,這通常被認為是不可接受的。
在這種情況下,應始終使用GLOBAL IN而不是IN。 讓我們來看看它是如何工作的查詢

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

請求者服務器將運行子查詢

SELECT UserID FROM distributed_table WHERE CounterID = 34

結果將被放在RAM中的臨時表中。 然后請求將被發送到每個遠程服務器

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

和臨時表 _data1 將通過查詢發送到每個遠程服務器(臨時表的名稱是實現定義的)。
這比使用正常IN更優化。 但是,請記住以下幾點:
1. 創建臨時表時,數據不是唯一的。 要減少通過網絡傳輸的數據量,請在子查詢中指定DISTINCT。 (你不需要為正常人
做這個。)
2. 臨時表將被發送到所有遠程服務器。 傳輸不考慮網絡拓撲。 例如,如果10個遠程服務器駐留在與請求者服務器非常遠
程的數據中心中,則數據將通過通道發送10次到遠程數據中心。 使用GLOBAL IN時盡量避免使用大型數據集。
3. 將數據傳輸到遠程服務器時,無法配置網絡帶寬限制。 您可能會使網絡過載。
4. 嘗試跨服務器分發數據,以便您不需要定期使用GLOBAL IN
5. 如果您需要經常使用GLOBAL IN,請規划ClickHouse集群的位置,以便單個副本組駐留在不超過一個數據中心中,並
且它們之間具有快速網絡,以便可以完全在單個數據中心內處理查詢。
這也是有意義的,在指定一個本地表 GLOBAL IN 子句,以防此本地表僅在請求者服務器上可用,並且您希望在遠程服務器上
使用來自它的數據。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM