> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-detect-table-modification.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# join_* 会话设置

> 自动生成的 join_* 分组中的 ClickHouse 会话设置。

export const VersionHistory = ({rows = []}) => {
  if (rows.length === 0) {
    return null;
  }
  const headers = ["版本", "默认值", "注释"];
  const border = "1px solid rgba(128, 128, 128, 0.3)";
  const cell = {
    border,
    padding: "0.25rem 0.5rem",
    textAlign: "start",
    verticalAlign: "top"
  };
  return <details className="not-prose" style={{
    border,
    borderRadius: "0.5rem",
    margin: "0.5rem 0",
    padding: "0.5rem 0.75rem",
    fontSize: "0.8125rem",
    lineHeight: "1.125rem"
  }}>
      <summary style={{
    cursor: "pointer",
    fontWeight: 600,
    opacity: 0.72
  }}>
        版本历史
      </summary>
      <table style={{
    borderCollapse: "collapse",
    width: "100%",
    margin: "0.5rem 0 0"
  }}>
        <thead>
          <tr>
            {headers.map(header => <th key={header} style={{
    ...cell,
    fontWeight: 600,
    opacity: 0.72
  }}>
                {header}
              </th>)}
          </tr>
        </thead>
        <tbody>
          {rows.map((row, row_index) => <tr key={row.id ?? row_index}>
              {(row.items ?? []).map((item, item_index) => <td key={item_index} style={{
    ...cell,
    overflowWrap: "anywhere"
  }}>
                  {item?.label}
                </td>)}
            </tr>)}
        </tbody>
      </table>
    </details>;
};

export const SettingsInfoBlock = ({type, default_value, changeable_without_restart}) => {
  return <div className="not-prose" style={{
    display: "flex",
    flexWrap: "wrap",
    alignItems: "baseline",
    columnGap: "0.5rem",
    rowGap: "0.125rem",
    margin: "0.375rem 0",
    fontSize: "0.8125rem",
    lineHeight: "1.125rem"
  }}>
      <div style={{
    fontWeight: 600,
    opacity: 0.72
  }}>类型</div>
      <div style={{
    overflowWrap: "anywhere"
  }}>{type}</div>
      <div style={{
    fontWeight: 600,
    opacity: 0.72,
    marginInlineStart: "0.5rem"
  }}>默认值</div>
      <div style={{
    overflowWrap: "anywhere"
  }}>{default_value}</div>
      {changeable_without_restart && <div style={{
    fontWeight: 600,
    opacity: 0.72,
    marginInlineStart: "0.5rem"
  }}>
          无需重启即可更改
        </div>}
      {changeable_without_restart && <div style={{
    overflowWrap: "anywhere"
  }}>
          {changeable_without_restart}
        </div>}
    </div>;
};

这些设置可在 [system.settings](/zh/reference/system-tables/settings) 中查看，且由 [source](https://github.com/ClickHouse/ClickHouse/blob/master/src/Core/Settings.cpp) 自动生成。

<div id="join_algorithm">
  ## join\_algorithm
</div>

<SettingsInfoBlock type="JoinAlgorithm" default_value="direct,parallel_hash,hash" />

<VersionHistory rows={[{"id": "row-1","items": [{"label": "24.12"},{"label": "direct,parallel_hash,hash"},{"label": "已弃用 'default'，改为显式指定 join 算法，同时现在优先使用 parallel_hash 而不是 hash"}]}]} />

指定使用哪种 [JOIN](/zh/reference/statements/select/join) 算法。

可以指定多种算法，系统会根据具体查询的 kind/严格性 和表引擎选择可用的算法。

大多数算法仅在被选用于查询时才会影响查询。不过，有些算法仅因被列出就会改变规划 — 即使它们只是最终未被选中的低优先级回退选项 — 因为决策会在选择算法之前作出。此类影响有两种：

* 连接键类型推断会变得更严格 (例如，merge join 无法连接不同类型的键，如 `String` 和 `Nullable(String)`) 。这可能会更改 `USING` 列的结果类型，并可能导致与 `Join` 引擎表的连接因 `TYPE_MISMATCH` 而失败。由 `full_sorting_merge` 和 `parallel_full_sorting_merge` 触发。
* 连接中保留侧的 `ORDER BY ... LIMIT` 会执行显式排序，而不是按主键顺序读取，因为假定连接会破坏有序读取 (merge join 会插入自己的连接前排序；partial merge join 会重新排序左侧块；能够生成延迟块的 join 也不会传播有序读取) 。结果相同，但计划效率较低。由 `full_sorting_merge`、`parallel_full_sorting_merge`、`partial_merge`、`prefer_partial_merge`、`grace_hash` 和 `auto` 触发；非零的 `max_bytes_before_external_join` / `max_bytes_ratio_before_external_join` 也会触发。

即使查询最终使用 `hash` 或其他算法运行，两者仍会生效。如果不希望如此，请勿在受影响查询的 `join_algorithm` 中列出上述算法。

可能的值：

* grace\_hash

使用 [Grace hash join](https://en.wikipedia.org/wiki/Hash_join#Grace_hash_join)。Grace hash 提供了一种算法选项，可在限制内存使用的同时，高效处理复杂连接。

grace join 的第一阶段会读取右表，并根据键列的哈希值将其拆分为 N 个桶 (初始时，N 为 `grace_hash_join_initial_buckets`) 。这样做是为了确保每个桶都能独立处理。第一个桶中的行会加入内存中的哈希表，其余行则保存到磁盘。如果哈希表增长到超出内存限制 (例如，由 [`max_bytes_in_join`](/zh/reference/settings/session-settings/max-bytes#max_bytes_in_join) 设置) ，则会增加桶的数量，并重新确定每一行所属的桶。不属于当前桶的行都会被刷出并重新分配。

支持 `INNER/LEFT/RIGHT/FULL ALL/ANY JOIN`。

* hash

使用 [Hash join algorithm](https://en.wikipedia.org/wiki/Hash_join)。这是最通用的实现，支持所有 kind 和 严格性 的组合，也支持在 `JOIN ON` 部分中通过 `OR` 组合的多个连接键。

使用 `hash` 算法时，`JOIN` 的右侧部分会被加载到 RAM 中。

* parallel\_hash

这是 `hash` join 的一种变体，它会将数据拆分到多个桶中，并并发构建多个哈希表，而不是只构建一个，以加快这一过程。

使用 `parallel_hash` 算法时，`JOIN` 的右侧部分会被加载到 RAM 中。

* partial\_merge

这是 [sort-merge algorithm](https://en.wikipedia.org/wiki/Sort-merge_join) 的一种变体，其中只有右表会被完全排序。

`RIGHT JOIN` 和 `FULL JOIN` 仅在 `ALL` 严格性 下受支持 (不支持 `SEMI`、`ANTI`、`ANY` 和 `ASOF`) 。

使用 `partial_merge` 算法时，ClickHouse 会对数据进行排序并将其写入磁盘。ClickHouse 中的 `partial_merge` 算法与经典实现略有不同。首先，ClickHouse 会按连接键对右表分块排序，并为已排序的块创建 min-max 索引。然后，它会按 `join key` 对左表的各个部分进行排序，并与右表执行连接。min-max 索引也会用于跳过不需要读取的右表块。

* direct

`direct` (也称为 nested loop) 算法会使用左表中的行作为键，在右表中执行 lookup。
它适用于 [Dictionary](/zh/reference/engines/table-engines/special/dictionary)、[EmbeddedRocksDB](/zh/reference/engines/table-engines/integrations/embedded-rocksdb) 和 [MergeTree](/zh/reference/engines/table-engines/mergetree-family/mergetree) 表等特殊存储。

对于 MergeTree 表，该算法会将连接键过滤条件直接下推到存储层。如果该键可以利用表的主键索引进行 lookup，这种方式会更高效；否则，它会针对左表的每个块对右表执行全表扫描。

支持 `INNER` 和 `LEFT` join，并且仅支持不带其他条件的单列等值连接键。

* auto

设置为 `auto` 时，会先尝试 `hash` join；如果超出内存限制，则会动态切换到其他算法。

* full\_sorting\_merge

[Sort-merge algorithm](https://en.wikipedia.org/wiki/Sort-merge_join)，会在连接前对参与连接的表进行完全排序。

* ie\_join

基于排序的 [IEJoin](https://vldb.org/pvldb/vol8/p2074-khayyat.pdf) 算法，适用于其 `ON` 部分包含两个参与连接表表达式之间不等比较 (`<`、`<=`、`>`、`>=`) 的 `JOIN`。支持 `ALL INNER/LEFT/RIGHT/FULL JOIN` 和 `SEMI`/`ANTI` `LEFT/RIGHT JOIN`。

在列表中的位置决定优先级：若列在其他算法之后，仅当其他算法不适用时才使用 IEJoin (即 `ON` 部分没有等值条件)；若列在首位，只要 `ON` 部分包含两个不等条件便会使用它。对于 `ALL INNER JOIN`，其余条件 (包括等值条件) 会作为过滤器应用于连接结果；对于其他 kind，则会在 operator 内部作为影响匹配的残余条件进行评估。如果列表中没有 `ie_join`，仅含不等条件的 `INNER JOIN` 会作为带过滤器的 `CROSS JOIN` 执行，其他 kind 不受支持。

连接前，两个输入都会累积到内存中：[`max_rows_in_join`](/zh/reference/settings/session-settings/max-rows#max_rows_in_join) 和 [`max_bytes_in_join`](/zh/reference/settings/session-settings/max-bytes#max_bytes_in_join) 会限制两侧合计的累积输入 (而不只是右侧)，溢出时的操作由 [`join_overflow_mode`](/zh/reference/settings/session-settings/join#join_overflow_mode) 设置；operator 在累积输入之上构建的排序索引不计入该限制。连接 operator 本身在单个线程中运行；只有输入在连接前的排序会并行执行。

* parallel\_full\_sorting\_merge

与 `full_sorting_merge` 相同，但兼容哈希的等值连接会按连接键的哈希分片为相互独立、并行运行的每分片 merge join (最多 `max_threads` 个)，而不是单个 merge join。这在使用所有线程的同时保留了 merge join 较低的流式内存使用量，且结果不保证有序。

仅对键类型的普通等值连接应用按连接键哈希分片，且该键类型的哈希必须与 merge join 比较结果一致，并且仅在两侧均未排序时应用。以下情况会跳过：

* `ASOF` join，以及浮点数 / `JSON` / `Object` / `Dynamic` 键类型：其哈希与 merge join 比较结果不一致，因此相等的键可能落在不同分片中。
* 已排序的侧 (按顺序读取的 MergeTree，或任何预排序输入)：保序地将数据分散到每分片 merge join 中可能会导致管道死锁。因此会保留按顺序读取及其 `read_in_order_use_virtual_row` 优化。
* 当 initiator 构建分布式查询计划 (`make_distributed_plan`) 时，因为分散排序无法序列化以供远程执行。本地单片段计划和每个 worker 的片段会在禁用该设置后重新优化，因此仍可进行分片。

跳过它只会禁用此重写，而不会禁用一般的并行性：join 将作为单个 `full_sorting_merge` 运行，并且当启用 `query_plan_join_shard_by_pk_ranges` 时，按顺序读取的 MergeTree 侧仍可在源端按主键范围分片 (主键范围使用与 join 相同的比较方式排序，因此相等的键会保持在一起)。

* prefer\_partial\_merge

如果可能，ClickHouse 总是会尝试使用 `partial_merge` join，否则使用 `hash`。*已弃用*，等同于 `partial_merge,hash`。

* default (deprecated)

旧版取值，请不要再使用。
等同于 `direct,hash`，即尝试使用 direct join 和 hash join (按此顺序) 。

<div id="join_any_take_last_row">
  ## join\_any\_take\_last\_row
</div>

<SettingsInfoBlock type="Bool" default_value="0" />

当右表中某个键对应多于一条匹配行时，此设置会更改具有 `ANY` 严格性 的 JOIN 操作行为。

<Note>
  此设置适用于 [`Join`](/zh/reference/engines/table-engines/special/join) 引擎表以及基于哈希的 JOIN 算法。

  如果 join 是并行构建的，行的顺序可能是非确定性的。这意味着对于 `ANY JOIN` 查询，`join_any_take_last_row = 1` 可能会返回非确定性的行。
</Note>

可能的值：

* 0 — 如果右表中某个键对应多于一条匹配行，则仅关联找到的第一行。
* 1 — 如果右表中某个键对应多于一条匹配行，则仅关联找到的最后一行。

另请参阅：

* [JOIN clause](/zh/reference/statements/select/join)
* [Join 表引擎](/zh/reference/engines/table-engines/special/join)
* [join\_default\_strictness](/zh/reference/settings/session-settings/join#join_default_strictness)

<div id="join_default_strictness">
  ## join\_default\_strictness
</div>

<SettingsInfoBlock type="JoinStrictness" default_value="ALL" />

设置 [JOIN 子句](/zh/reference/statements/select/join)的默认严格性。

可能的值：

* `ALL` — 如果右表有多行匹配，ClickHouse 会根据匹配行创建[笛卡尔积](https://en.wikipedia.org/wiki/Cartesian_product)。这是标准 SQL 中 `JOIN` 的常规行为。
* `ANY` — 如果右表有多行匹配，则只会连接找到的第一行。如果右表只有一行匹配，则 `ANY` 和 `ALL` 的结果相同。
* `ASOF` — 用于连接匹配关系不确定的序列。
* `Empty string` — 如果查询中未指定 `ALL` 或 `ANY`，ClickHouse 会抛出异常。

<div id="join_on_disk_max_files_to_merge">
  ## join\_on\_disk\_max\_files\_to\_merge
</div>

<SettingsInfoBlock type="UInt64" default_value="64" />

限制 MergeJoin 操作在磁盘上执行时，并行排序可使用的文件数量。

该设置的值越大，占用的 RAM 越多，对磁盘 I/O 的需求越少。

可能的值：

* 任意大于等于 2 的正整数。

<div id="join_output_by_rowlist_perkey_rows_threshold">
  ## join\_output\_by\_rowlist\_perkey\_rows\_threshold
</div>

<SettingsInfoBlock type="UInt64" default_value="5" />

<VersionHistory rows={[{"id": "row-1","items": [{"label": "24.9"},{"label": "5"},{"label": "在 hash join 中，用于判断是否按行列表输出的右表每个键平均行数下限。"}]}]} />

在 hash join 中，用于判断是否按行列表输出的右表每个键平均行数下限。

<div id="join_overflow_mode">
  ## join\_overflow\_mode
</div>

<SettingsInfoBlock type="OverflowMode" default_value="throw" />

定义了当 join 达到以下任一限制时，ClickHouse 将执行的操作：

* [max\_bytes\_in\_join](/zh/reference/settings/session-settings/max-bytes#max_bytes_in_join)
* [max\_rows\_in\_join](/zh/reference/settings/session-settings/max-rows#max_rows_in_join)

此设置仅对 [`join_algorithm`](/zh/reference/settings/session-settings/join#join_algorithm)
为 `hash`、`parallel_hash` 和 `ie_join` 时生效。其他算法 (例如 `partial_merge`、`grace_hash`、`auto`) 处理这些限制的方式不同——例如落盘、重新分区或切换策略——请参见
[`join_algorithm`](/zh/reference/settings/session-settings/join#join_algorithm)。

可能值：

* `THROW` — ClickHouse 抛出异常并停止查询。
* `BREAK` — ClickHouse 停止查询，但不抛出异常。

默认值：`THROW`。

**另请参见**

* [JOIN 子句](/zh/reference/statements/select/join)
* [Join 表引擎](/zh/reference/engines/table-engines/special/join)

<div id="join_use_nulls">
  ## join\_use\_nulls
</div>

<SettingsInfoBlock type="Bool" default_value="0" />

设置 [JOIN](/zh/reference/statements/select/join) 的行为方式。合并表时，可能会出现空单元。ClickHouse 会根据此设置采用不同方式填充这些空单元。

可能的值：

* 0 — 空单元将使用相应字段类型的默认值填充。
* 1 — `JOIN` 的行为与 standard SQL 相同。相应字段的类型会转换为 [Nullable](/zh/reference/data-types/nullable)，空单元则会填充为 [NULL](/zh/reference/syntax)。
