如何将三个或更多表的分布式联接作为本地联接?

zha*_*ang 2 clickhouse

我主要对三个表的执行计划感到困惑,这是查询的执行计划如下(注:t1d,t2d,t3d是分布式表):

\n
select xxx\nfrom t1d t1d\nleft join \n    (select * from t2d where xxx group by xxx) t2d \nusing A\nleft join\n    (select * from t3d where xxx group by xxx) t3d\nusing A\nwhere t1d.xxx\ngroup by t1d.xxx\nSETTINGS distributed_product_mode=\'local\'\n
Run Code Online (Sandbox Code Playgroud)\n
\xe2\x94\x8c\xe2\x94\x80explain\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x90\n\xe2\x94\x82 Expression (Projection)                                                                           \xe2\x94\x82\n\xe2\x94\x82   CreatingSets (Create sets before main query execution)                                          \xe2\x94\x82\n\xe2\x94\x82     Expression (Before ORDER BY)                                                                  \xe2\x94\x82\n\xe2\x94\x82       Join (JOIN)                                                                                 \xe2\x94\x82\n\xe2\x94\x82         Expression ((Before JOIN + Projection))                                                   \xe2\x94\x82\n\xe2\x94\x82           SettingQuotaAndLimits (Set limits and quota after reading from storage)                 \xe2\x94\x82\n\xe2\x94\x82             Union                                                                                 \xe2\x94\x82\n\xe2\x94\x82               Expression ((Convert block structure for query from local replica + ))              \xe2\x94\x82\n\xe2\x94\x82                 CreatingSets (Create sets before main query execution)                            \xe2\x94\x82\n\xe2\x94\x82                   Expression (Before ORDER BY)                                                    \xe2\x94\x82\n\xe2\x94\x82                     AddingDelayedSource (Add non-joined rows after JOIN)                          \xe2\x94\x82\n\xe2\x94\x82                       Join (JOIN)                                                                 \xe2\x94\x82\n\xe2\x94\x82                         Expression (Before JOIN)                                                  \xe2\x94\x82\n\xe2\x94\x82                           SettingQuotaAndLimits (Set limits and quota after reading from storage) \xe2\x94\x82\n\xe2\x94\x82                             ReadFromPreparedSource (Read from NullSource)                         \xe2\x94\x82\n\xe2\x94\x82                   CreatingSet (Create set for JOIN)                                               \xe2\x94\x82\n\xe2\x94\x82                     Expression ((Projection + Before ORDER BY))                                   \xe2\x94\x82\n\xe2\x94\x82                       Aggregating                                                                 \xe2\x94\x82\n\xe2\x94\x82                         Expression (Before GROUP BY)                                              \xe2\x94\x82\n\xe2\x94\x82                           SettingQuotaAndLimits (Set limits and quota after reading from storage) \xe2\x94\x82\n\xe2\x94\x82                             ReadFromStorage (MergeTree)                                           \xe2\x94\x82\n\xe2\x94\x82               ReadFromPreparedSource (Read from remote replica)                                   \xe2\x94\x82\n\xe2\x94\x82     CreatingSet (Create set for JOIN)                                                             \xe2\x94\x82\n\xe2\x94\x82       Expression (Projection)                                                                     \xe2\x94\x82\n\xe2\x94\x82         SettingQuotaAndLimits (Set limits and quota after reading from storage)                   \xe2\x94\x82\n\xe2\x94\x82           Union                                                                                   \xe2\x94\x82\n\xe2\x94\x82             Expression ((Convert block structure for query from local replica + Before ORDER BY)) \xe2\x94\x82\n\xe2\x94\x82               SettingQuotaAndLimits (Set limits and quota after reading from storage)             \xe2\x94\x82\n\xe2\x94\x82                 ReadFromStorage (MergeTree)                                                       \xe2\x94\x82\n\xe2\x94\x82             ReadFromPreparedSource (Read from remote replica)                                     \xe2\x94\x82\n
Run Code Online (Sandbox Code Playgroud)\n

根据我的理解,我认为步骤如下:

\n
    \n
  1. t1_local 和 t2_local 在每个分片上进行本地连接作为您的回复,我使用解释语法发现 t2d 被写入 t2_local,这是真的,我对此很清楚。

    \n
  2. \n
  3. 发起者主机合并本地连接所有分片的结果

    \n
  4. \n
  5. 每个分片都会查询“select * from t3_local where xxx group by xxx”并在启动器上组合(也许这与步骤1同步)

    \n
  6. \n
  7. 发起者在步骤 2 的结果和步骤 3 的结果之间进行连接。

    \n
  8. \n
\n

我的问题是:我希望每个分片都可以进行本地连接

\n
select xxx\nfrom t1_local \nleft join (select xxx from t2_local)\nusing A\nleft join (select xxx from t3_local)\nusing A\n
Run Code Online (Sandbox Code Playgroud)\n

然后发起者合并所有分片的结果。\n我认为这比上面更快。但实际上执行计划并不能显示出来。

\n

And*_*rew 10

How does JOINs work at Clickhouse?

\n

I\'ll try to explain with an example of joining 2 tables.

\n

ALGORITHM

\n

Let\'s assume each shard has a local_table and distributed wrapper over it.

\n

When you join distributed_table with other table (e.g. subquery):

\n
SELECT <fields> FROM distributed_table JOIN (SELECT * FROM some_other_table) USING field\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  1. Initiator host sends query to each shard with left table replaced by the corresponding local table:
  2. \n
\n
SELECT <fields> FROM local_table JOIN (SELECT * FROM some_other_table) USING field\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  1. Every shard executes the subquery:
  2. \n
\n
SELECT * FROM some_other_table\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  1. local_table is joined with previous result of each shard
  2. \n
  3. Results are sent to the initiator host from all the shards
  4. \n
  5. Initiator host combines the results
  6. \n
\n

Let\'s take a look at an example and play around with the distributed_product_mode setting and local/distributed tables

\n

EXAMPLE

\n

Say we have a cluster cluster_name of two shards: host1 and host2. Let\'s create tables there:

\n
CREATE TABLE source_local ON CLUSTER cluster_name\n(\n    `key` Int32,\n    `value` String\n)\nENGINE = ReplicatedMergeTree(\'/clickhouse/tables/{shard}/default.source_local\', \'{replica}\')\nORDER BY key;\n\nCREATE TABLE source ON CLUSTER cluster_name AS source_local\nENGINE = Distributed(cluster_name, default, source_local)\n
Run Code Online (Sandbox Code Playgroud)\n
CREATE TABLE to_join_local ON CLUSTER cluster_name\n(\n    `key` Int32,\n    `value` String\n)\nENGINE = ReplicatedMergeTree(\'/clickhouse/tables/{shard}/default.to_join_local\', \'{replica}\')\nORDER BY key;\n\nCREATE TABLE to_join ON CLUSTER cluster_name AS to_join_local\nENGINE = Distributed(cluster_name, default, to_join_local)\n
Run Code Online (Sandbox Code Playgroud)\n

Then, perform several insert at host1:

\n
INSERT INTO source_local VALUES (1, \'source1\'), (2, \'source2\');\nINSERT INTO to_join_local VALUES (1, \'tojoin1\');\n\n
Run Code Online (Sandbox Code Playgroud)\n

And one insert at host2:

\n
INSERT INTO to_join_local VALUES (2, \'tojoin2\');\n
Run Code Online (Sandbox Code Playgroud)\n

For better understanding let\'s visualize local tables:

\n

分片 1 和分片 2 本地表

\n

Let\'s start with the basic configuration ofdistributed_product_mode setting, setting it just to allow. It will not modify the algorithm but also will not throw unnecessary exceptions:

\n
SET distributed_product_mode = \'allow\'\n
Run Code Online (Sandbox Code Playgroud)\n

JOINING WITH THE DISTRIBUTED TABLE

\n
SET distributed_product_mode = \'allow\'\n
Run Code Online (Sandbox Code Playgroud)\n

Short explanation: Every host perfoms join of left local table with right subquery and then results are combined at the initiator host.

\n

Let\'s do this step by step according to the algorithm

\n
    \n
  1. The following query is sent to the shards:
  2. \n
\n
SELECT\n    source.key,\n    source.value,\n    to_join.value\nFROM source AS source\nINNER JOIN\n(\n    SELECT *\n    FROM to_join AS tj\n) AS to_join USING (key)\n
Run Code Online (Sandbox Code Playgroud)\n

(注:source表格已替换为source_local表格)

\n
    \n
  1. 所有分片执行相同的子查询:
  2. \n
\n
SELECT\n    source.key,\n    source.value,\n    to_join.value\nFROM source_local AS source\nINNER JOIN\n(\n    SELECT *\n    FROM to_join AS tj\n) AS to_join USING (key)\n
Run Code Online (Sandbox Code Playgroud)\n

由于它是分布式表,因此两个分片上的结果将相同:

\n
\xe2\x94\x8f\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\xb3\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x93\n\xe2\x94\x83 key \xe2\x94\x83 value   \xe2\x94\x83\n\xe2\x94\xa1\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x95\x87\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\xa9\n\xe2\x94\x82   1 \xe2\x94\x82 tojoin1 \xe2\x94\x82\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xb4\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xa4\n\xe2\x94\x82   2 \xe2\x94\x82 tojoin2 \xe2\x94\x82\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xb4\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x98\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  1. source_local表在每个分片上连接这个结果。
  2. \n
\n

Host1:和source_local的两行,与子查询的结果完全相同。因此,host1 上的联接结果将包含 2 行。12

\n

Host2:由于source_localhost2 上不包含任何内容,因此连接结果将为空。

\n

可视化:

\n

本地连接\n4-5。这些结果传输到发起者并在那里合并。\n最终结果:

\n
\xe2\x94\x8f\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\xb3\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\xb3\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x93\n\xe2\x94\x83 key \xe2\x94\x83 value   \xe2\x94\x83 to_join.value \xe2\x94\x83\n\xe2\x94\xa1\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x95\x87\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x95\x87\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\xa9\n\xe2\x94\x82   1 \xe2\x94\x82 source1 \xe2\x94\x82 tojoin1       \xe2\x94\x82\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xbc\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xbc\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xa4\n\xe2\x94\x82   2 \xe2\x94\x82 source2 \xe2\x94\x82 tojoin2       \xe2\x94\x82\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xb4\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xb4\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x98\n
Run Code Online (Sandbox Code Playgroud)\n

加入本地表

\n
SELECT * FROM to_join AS tj\n
Run Code Online (Sandbox Code Playgroud)\n

简短说明:每个分片执行两个本地表的联接,然后在发起者上组合结果

\n
    \n
  1. 以下查询被发送到分片:
  2. \n
\n
\xe2\x94\x8f\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\xb3\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x93\n\xe2\x94\x83 key \xe2\x94\x83 value   \xe2\x94\x83\n\xe2\x94\xa1\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x95\x87\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\xa9\n\xe2\x94\x82   1 \xe2\x94\x82 tojoin1 \xe2\x94\x82\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xb4\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xa4\n\xe2\x94\x82   2 \xe2\x94\x82 tojoin2 \xe2\x94\x82\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xb4\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x98\n
Run Code Online (Sandbox Code Playgroud)\n

2-3.在此输入图像描述\n4-5。因此,最终结果与之前的结果有所不同:

\n
\xe2\x94\x8f\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\xb3\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\xb3\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x93\n\xe2\x94\x83 key \xe2\x94\x83 value   \xe2\x94\x83 to_join.value \xe2\x94\x83\n\xe2\x94\xa1\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x95\x87\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x95\x87\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\xa9\n\xe2\x94\x82   1 \xe2\x94\x82 source1 \xe2\x94\x82 tojoin1       \xe2\x94\x82\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xb4\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xb4\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x98\n
Run Code Online (Sandbox Code Playgroud)\n

我认为这个请求应该可以解决您的问题

\n

连接分布式表,distributed_product_mode = \'local\'

\n
\xe2\x94\x8f\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\xb3\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\xb3\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x93\n\xe2\x94\x83 key \xe2\x94\x83 value   \xe2\x94\x83 to_join.value \xe2\x94\x83\n\xe2\x94\xa1\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x95\x87\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x95\x87\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\xa9\n\xe2\x94\x82   1 \xe2\x94\x82 source1 \xe2\x94\x82 tojoin1       \xe2\x94\x82\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xbc\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xbc\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xa4\n\xe2\x94\x82   2 \xe2\x94\x82 source2 \xe2\x94\x82 tojoin2       \xe2\x94\x82\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xb4\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xb4\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x98\n
Run Code Online (Sandbox Code Playgroud)\n

结果:

\n
\xe2\x94\x8c\xe2\x94\x80key\xe2\x94\x80\xe2\x94\xac\xe2\x94\x80value\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xac\xe2\x94\x80to_join.value\xe2\x94\x80\xe2\x94\x90\n\xe2\x94\x82   1 \xe2\x94\x82 source1 \xe2\x94\x82 tojoin1       \xe2\x94\x82\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xb4\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xb4\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x98\n
Run Code Online (Sandbox Code Playgroud)\n

我们与分布式表进行联接,但得到了与与本地表联接相同的结果。\n原因是distributed_product_mode = \'local\'Clickhouse 隐式执行与我们与本地表联接时相同的结果。这是文档

\n

此连接也按您想要的方式执行

\n

连接分布式表,distributed_product_mode = \'global\'

\n

相同的查询:

\n
SELECT\n    source.key,\n    source.value,\n    to_join.value\nFROM source AS source\nINNER JOIN\n(\n    SELECT *\n    FROM to_join_local AS tj\n) AS to_join USING (key)\n
Run Code Online (Sandbox Code Playgroud)\n

结果是:

\n
\xe2\x94\x8c\xe2\x94\x80key\xe2\x94\x80\xe2\x94\xac\xe2\x94\x80value\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xac\xe2\x94\x80to_join.value\xe2\x94\x80\xe2\x94\x90\n\xe2\x94\x82   1 \xe2\x94\x82 source1 \xe2\x94\x82 tojoin1       \xe2\x94\x82\n\xe2\x94\x82   2 \xe2\x94\x82 source2 \xe2\x94\x82 tojoin2       \xe2\x94\x82\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xb4\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xb4\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x98\n
Run Code Online (Sandbox Code Playgroud)\n

我们得到的结果与第一种情况的分布式表相同。有什么区别吗?\n是的,Clickhouse 执行查询的方式有区别:

\n

此时,第2 个右子查询将仅在一个分片上执行,然后它将分布在其他分片上。它可用于查询优化,但不影响结果。\n您可以使用GLOBAL JOIN代替来获得相同的结果JOIN

\n