> ## 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](/ko/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'는 조인 알고리즘을 명시적으로 지정하는 방식으로 대체되어 Deprecated 상태가 되었으며, 이제 hash보다 parallel_hash가 우선 사용됩니다"}]}]} />

어떤 [JOIN](/ko/reference/statements/select/join) 알고리즘을 사용할지 지정합니다.

여러 알고리즘을 지정할 수 있으며, 특정 쿼리에서는 kind/엄격성 및 테이블 엔진에 따라 사용 가능한 알고리즘이 선택됩니다.

대부분의 알고리즘은 선택된 경우에만 쿼리에 영향을 줍니다. 그러나 일부 알고리즘은 최종적으로 선택되지 않는 낮은 우선순위의 대체 옵션으로 나열되기만 해도 계획을 변경합니다. 알고리즘을 선택하기 전에 해당 결정이 내려지기 때문입니다. 이러한 영향은 다음 2가지입니다:

* 조인 키 타입 추론이 더 엄격해집니다(예: 머지 조인은 `String`과 `Nullable(String)`처럼 서로 다른 타입의 키를 조인할 수 없음). 이로 인해 `USING` 컬럼의 결과 타입이 변경될 수 있으며, `Join` 엔진 테이블과의 조인이 `TYPE_MISMATCH`로 실패할 수 있습니다. `full_sorting_merge`와 `parallel_full_sorting_merge`에 의해 트리거됩니다.
* 조인의 보존 측에 대한 `ORDER BY ... LIMIT`는 조인이 정렬된 읽기를 깨뜨리는 것으로 간주되므로 프라이머리 키 순서로 읽는 대신 명시적으로 정렬합니다(머지 조인은 자체적인 조인 전 정렬을 삽입하고, 부분 병합 조인은 왼쪽 블록을 다시 정렬하며, 지연된 블록을 생성할 수 있는 조인도 정렬된 읽기를 전파하지 않음). 결과는 같지만 계획의 효율은 낮아집니다. `full_sorting_merge`, `parallel_full_sorting_merge`, `partial_merge`, `prefer_partial_merge`, `grace_hash`, `auto` 및 0이 아닌 `max_bytes_before_external_join` / `max_bytes_ratio_before_external_join`에 의해 트리거됩니다.

쿼리가 결국 `hash` 또는 다른 알고리즘으로 실행되더라도 둘 다 적용됩니다. 이것이 바람직하지 않다면 영향을 받는 쿼리의 `join_algorithm`에 위 알고리즘을 나열하지 마십시오.

가능한 값:

* grace\_hash

[Grace hash 조인](https://en.wikipedia.org/wiki/Hash_join#Grace_hash_join)을 사용합니다. Grace hash는 메모리 사용을 제한하면서도 복잡한 조인을 고성능으로 처리할 수 있는 알고리즘 옵션입니다.

grace 조인의 첫 번째 단계에서는 오른쪽 테이블을 읽고 키 컬럼의 해시 값에 따라 N개의 버킷으로 분할합니다(초기 N 값은 `grace_hash_join_initial_buckets`입니다). 이는 각 버킷을 독립적으로 처리할 수 있도록 수행됩니다. 첫 번째 버킷의 행은 메모리 내 해시 테이블에 추가되고, 나머지는 디스크에 저장됩니다. 해시 테이블이 메모리 제한을 초과하면(예: [`max_bytes_in_join`](/ko/reference/settings/session-settings/max-bytes#max_bytes_in_join)로 설정한 경우) 버킷 수를 늘리고 각 행에 할당된 버킷을 다시 계산합니다. 현재 버킷에 속하지 않는 행은 모두 플러시되고 재할당됩니다.

`INNER/LEFT/RIGHT/FULL ALL/ANY JOIN`을 지원합니다.

* hash

[해시 조인 알고리즘](https://en.wikipedia.org/wiki/Hash_join)을 사용합니다. kind와 엄격성의 모든 조합을 지원하며, `JOIN ON` 절에서 `OR`로 결합된 여러 조인 키도 지원하는 가장 범용적인 구현입니다.

`hash` 알고리즘을 사용할 때는 `JOIN`의 오른쪽 부분을 RAM에 업로드합니다.

* parallel\_hash

`hash` 조인의 변형으로, 데이터를 버킷으로 분할하고 하나의 해시 테이블 대신 여러 해시 테이블을 동시에 구축하여 이 과정을 더 빠르게 처리합니다.

`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는 오른쪽 테이블을 블록 단위로 조인 키 기준 정렬하고, 정렬된 블록에 대해 MinMax 인덱스를 생성합니다. 그런 다음 왼쪽 테이블의 일부를 `join key` 기준으로 정렬한 뒤 오른쪽 테이블과 조인합니다. 불필요한 오른쪽 테이블 블록을 건너뛰는 데에도 MinMax 인덱스가 사용됩니다.

* direct

`direct`(nested loop라고도 함) 알고리즘은 왼쪽 테이블의 행을 키로 사용해 오른쪽 테이블에서 lookup을 수행합니다.
[Dictionary](/ko/reference/engines/table-engines/special/dictionary), [EmbeddedRocksDB](/ko/reference/engines/table-engines/integrations/embedded-rocksdb), [MergeTree](/ko/reference/engines/table-engines/mergetree-family/mergetree) 테이블과 같은 특수 스토리지에서 지원됩니다.

MergeTree 테이블의 경우 이 알고리즘은 조인 키 필터를 스토리지 계층으로 직접 푸시다운합니다. 키가 테이블의 프라이머리 키 인덱스를 lookup에 사용할 수 있으면 더 효율적일 수 있지만, 그렇지 않으면 왼쪽 테이블의 각 블록마다 오른쪽 테이블 전체를 스캔합니다.

`INNER` 및 `LEFT` 조인만 지원하며, 다른 조건 없이 단일 컬럼 동등 조인 키만 지원합니다.

* auto

`auto`로 설정하면 먼저 `hash` 조인을 시도하고, 메모리 제한을 초과하면 실행 중에 다른 알고리즘으로 전환합니다.

* full\_sorting\_merge

조인 전에 조인 대상 테이블을 완전히 정렬하는 [Sort-merge algorithm](https://en.wikipedia.org/wiki/Sort-merge_join)입니다.

* ie\_join

조인 대상 테이블의 표현식 간 부등식 비교(`<`, `<=`, `>`, `>=`)가 2개 있는 `ON` 절을 포함하는 `JOIN`을 위한 정렬 기반 [IEJoin](https://vldb.org/pvldb/vol8/p2074-khayyat.pdf) 알고리즘입니다. `ALL INNER/LEFT/RIGHT/FULL JOIN` 및 `SEMI`/`ANTI` `LEFT/RIGHT JOIN`을 지원합니다.

목록 내 위치가 우선순위를 결정합니다. 다른 알고리즘 뒤에 나열하면 IEJoin은 해당 알고리즘을 적용할 수 없을 때만 사용됩니다(`ON` 절에 동등 조건이 없는 경우). 첫 번째로 나열하면 `ON` 절에 부등 조건이 2개 있을 때마다 사용됩니다. 나머지 조건(동등 조건 포함)은 `ALL INNER JOIN`에서는 조인 결과에 대한 필터로 적용되며, 다른 종류에서는 매칭에 영향을 주는 잔여 조건으로 연산자 내부에서 평가됩니다. 목록에 `ie_join`이 없으면 부등 조건만 있는 `INNER JOIN`은 필터가 적용된 `CROSS JOIN`으로 실행되며, 다른 종류는 지원되지 않습니다.

두 입력은 조인 전에 모두 메모리에 누적됩니다. [`max_rows_in_join`](/ko/reference/settings/session-settings/max-rows#max_rows_in_join) 및 [`max_bytes_in_join`](/ko/reference/settings/session-settings/max-bytes#max_bytes_in_join)은 양쪽의 누적 입력을 함께 제한하며(오른쪽만이 아님), 오버플로우 시 수행할 작업은 [`join_overflow_mode`](/ko/reference/settings/session-settings/join#join_overflow_mode)로 설정합니다. 누적된 입력 위에 연산자가 구축하는 정렬 인덱스는 제한에 포함되지 않습니다. 조인 연산자 자체는 단일 스레드에서 실행되며, 입력의 조인 전 정렬만 병렬화됩니다.

* parallel\_full\_sorting\_merge

`full_sorting_merge`와 같지만, 해시 호환 동등 조인은 단일 머지 조인 대신 조인 키의 해시를 기준으로 독립적인 세그먼트별 머지 조인으로 샤딩되어 병렬로 실행됩니다(`max_threads`까지). 이를 통해 모든 스레드를 사용하면서 머지 조인의 낮은 스트리밍 메모리 사용량을 유지하며, 결과는 정렬되지 않습니다.

조인 키에 의한 해시 샤딩은 해시가 머지 조인 비교와 일치하는 키 타입의 일반 동등 조인에만 적용되며, 어느 한쪽도 이미 정렬되어 있지 않을 때만 적용됩니다. 다음 경우에는 건너뜁니다:

* `ASOF` 조인 및 floating-point / `JSON` / `Object` / `Dynamic` 키 타입: 해시가 머지 조인 비교와 일관되지 않으므로 동일한 키가 서로 다른 세그먼트에 배치될 수 있습니다.
* 이미 정렬된 쪽(MergeTree 순서 읽기 또는 사전 정렬된 모든 입력): 세그먼트별 머지에 순서를 보존하는 분산을 수행하면 파이프라인이 교착 상태에 빠질 수 있습니다. 대신 순서 읽기와 해당 `read_in_order_use_virtual_row` 최적화가 유지됩니다.
* 이니시에이터가 분산 계획(`make_distributed_plan`)을 구축하는 동안: 분산된 정렬은 원격 실행을 위해 직렬화할 수 없기 때문입니다. 로컬 단일 프래그먼트 계획과 워커별 프래그먼트는 해당 설정을 비활성화한 상태에서 다시 최적화되므로, 여전히 샤딩할 수 있습니다.

이를 건너뛰면 일반적인 병렬성이 아니라 이 재작성만 비활성화됩니다. 조인은 단일 `full_sorting_merge`로 실행되며, 순서대로 읽는 MergeTree 쪽은 `query_plan_join_shard_by_pk_ranges`가 활성화되어 있으면 여전히 프라이머리 키 범위별로 소스에서 샤딩될 수 있습니다(이 범위는 조인에서 사용하는 동일한 비교 기준으로 정렬되므로 동일한 키가 함께 유지됨).

* prefer\_partial\_merge

ClickHouse는 가능하면 항상 `partial_merge` 조인을 사용하려고 시도하며, 그렇지 않으면 `hash`를 사용합니다. *Deprecated*이며, `partial_merge,hash`와 같습니다.

* default (deprecated)

레거시 값이므로 더 이상 사용하지 마십시오.
`direct,hash`와 같으며, 즉 direct 조인과 hash 조인을 이 순서대로 사용하려고 시도합니다.

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

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

오른쪽 테이블에서 하나의 키에 일치하는 행이 여러 개 있을 때 `ANY` 엄격성을 사용하는 JOIN 작업의 동작을 변경합니다.

<Note>
  이 설정은 [`Join`](/ko/reference/engines/table-engines/special/join) 테이블 엔진을 사용하는 테이블과 해시 기반 조인 알고리즘에 적용됩니다.

  조인이 병렬로 구성되면 행의 순서가 비결정적일 수 있습니다. 즉, `join_any_take_last_row = 1`은 `ANY JOIN` 쿼리에서 비결정적인 행을 반환할 수 있습니다.
</Note>

가능한 값:

* 0 — 오른쪽 테이블에 일치하는 행이 여러 개 있으면, 먼저 발견된 행만 조인됩니다.
* 1 — 오른쪽 테이블에 일치하는 행이 여러 개 있으면, 마지막에 발견된 행만 조인됩니다.

관련 항목:

* [JOIN 절](/ko/reference/statements/select/join)
* [Join 테이블 엔진](/ko/reference/engines/table-engines/special/join)
* [join\_default\_strictness](/ko/reference/settings/session-settings/join#join_default_strictness)

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

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

[JOIN 절](/ko/reference/statements/select/join)의 기본 엄격성을 설정합니다.

가능한 값:

* `ALL` — 오른쪽 테이블에 일치하는 행이 여러 개 있으면 ClickHouse는 일치하는 행들로 [카테시안 곱](https://en.wikipedia.org/wiki/Cartesian_product)을 생성합니다. 이는 표준 SQL의 일반적인 `JOIN` 동작입니다.
* `ANY` — 오른쪽 테이블에 일치하는 행이 여러 개 있으면, 먼저 찾은 첫 번째 행만 조인됩니다. 오른쪽 테이블에 일치하는 행이 하나뿐이면 `ANY`와 `ALL`의 결과는 같습니다.
* `ASOF` — 정확히 일치하지 않는 시퀀스를 조인할 때 사용합니다.
* `빈 문자열` — 쿼리에서 `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": "해시 조인에서 행 목록으로 출력할지 결정할 때 사용하는, 오른쪽 테이블의 키별 평균 행 수 하한값입니다."}]}]} />

해시 조인에서 행 목록으로 출력할지 결정할 때 사용하는, 오른쪽 테이블의 키별 평균 행 수 하한값입니다.

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

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

조인이 다음 제한 중 하나에 도달할 때 ClickHouse가 수행할 동작을 정의합니다:

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

이 설정은 [`join_algorithm`](/ko/reference/settings/session-settings/join#join_algorithm)
값이 `hash`, `parallel_hash` 또는 `ie_join`일 때만 적용됩니다. 다른
알고리즘(예: `partial_merge`, `grace_hash`, `auto`)은 이러한
제한을 디스크로 스필하거나, 다시 파티셔닝하거나, 전략을 전환하는 방식으로
다르게 처리합니다. 자세한 내용은
[`join_algorithm`](/ko/reference/settings/session-settings/join#join_algorithm)을 참조하십시오.

가능한 값:

* `THROW` — ClickHouse는 예외를 발생시키고 쿼리를 중지합니다.
* `BREAK` — ClickHouse는 쿼리를 중지하고 예외를 발생시키지 않습니다.

기본값: `THROW`.

**관련 항목**

* [JOIN 절](/ko/reference/statements/select/join)
* [Join 테이블 엔진](/ko/reference/engines/table-engines/special/join)

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

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

[JOIN](/ko/reference/statements/select/join)의 동작 방식을 설정합니다. 테이블을 병합할 때 빈 셀이 생길 수 있습니다. ClickHouse는 이 설정에 따라 이를 서로 다르게 채웁니다.

가능한 값:

* 0 — 빈 셀은 해당 필드 유형의 기본값으로 채워집니다.
* 1 — `JOIN`은 표준 SQL과 동일하게 동작합니다. 해당 필드의 유형은 [Nullable](/ko/reference/data-types/nullable)로 변환되며, 빈 셀은 [NULL](/ko/reference/syntax)로 채워집니다.
