join_algorithm
어떤 JOIN 알고리즘을 사용할지 지정합니다. 여러 알고리즘을 지정할 수 있으며, 특정 쿼리에서는 Kind/엄격성 및 테이블 엔진에 따라 사용 가능한 알고리즘이 선택됩니다. 해시 기반 알고리즘이 디스크로 스필되는지 여부는 이 선택의 일부가 아닙니다.max_bytes_before_external_join / max_bytes_ratio_before_external_join은 모두의 스필 임계값이며(둘 중 하나가 0이 아니면 enable_adaptive_memory_spill_scheduler가 메모리 압박 상황에서 조인을 더 일찍 스필할 수 있음), max_rows_in_join / max_bytes_in_join은 모두의 하드 한도입니다. 단, legacy_join_size_limits_trigger_spilling이 두 한도를 다시 디스크 스필 트리거로 전환하는 경우는 예외입니다. 선택한 값에 따라 조인의 스필 방식이 결정됩니다. grace_hash는 첫 번째 블록부터 오른쪽 테이블을 파티션으로 나누며, hash와 parallel_hash는 메모리에 수집한 뒤 임계값을 초과하면 전환합니다.
대부분의 알고리즘은 선택된 경우에만 쿼리에 영향을 줍니다. 그러나 일부 알고리즘은 최종적으로 선택되지 않는 낮은 우선순위의 대체 옵션으로 나열되기만 해도 계획을 변경합니다. 알고리즘을 선택하기 전에 해당 결정이 내려지기 때문입니다. 이러한 영향은 다음 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는 첫 번째 블록부터 외부 처리됩니다. hash와 parallel_hash가 먼저 메모리에 수집한 후 스필 임계값을 초과할 때만 파티션으로 나누는 것과 달리, 오른쪽 테이블을 즉시 파티션으로 나눕니다. 오른쪽 측이 메모리에 맞지 않을 것을 이미 알고 있고 메모리 내 단계를 건너뛰려면 이를 선택하십시오. 스필 임계값 자체는 모든 해시 알고리즘이 사용하는 max_bytes_before_external_join / max_bytes_ratio_before_external_join와 동일하며, legacy_join_size_limits_trigger_spilling이 켜져 있지 않다면 둘 중 하나가 0이 아니어야 합니다. 임계값이 없으면 grace_hash는 목록의 다음 알고리즘으로 넘어가며, 이것만 지정된 경우 거부됩니다.
grace 조인의 첫 번째 단계에서는 오른쪽 테이블을 읽고 키 컬럼의 해시 값에 따라 N개의 버킷으로 나눕니다(초기 N은 grace_hash_join_initial_buckets입니다). 각 버킷을 독립적으로 처리할 수 있도록 나눕니다. 첫 번째 버킷의 행은 메모리 내 해시 테이블에 추가하고, 나머지는 디스크에 저장합니다. 해시 테이블이 스필 임계값을 초과할 정도로 커지면 버킷 수를 늘리고 각 행에 할당된 버킷도 함께 변경합니다. 현재 버킷에 속하지 않는 모든 행은 플러시하고 다시 할당합니다.
INNER/LEFT/RIGHT/FULL ALL/ANY JOIN을 지원합니다.
- hash
JOIN ON 절에서 OR로 결합된 여러 조인 키를 지원하는 가장 범용적인 구현입니다.
hash 알고리즘을 사용할 때 JOIN의 오른쪽 부분은 RAM에 업로드됩니다.
- parallel_hash
hash 조인의 변형입니다.
parallel_hash 알고리즘을 사용할 때 JOIN의 오른쪽 부분은 RAM에 업로드됩니다.
- partial_merge
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, EmbeddedRocksDB, MergeTree 테이블과 같은 특수 스토리지에서 지원됩니다.
MergeTree 테이블의 경우 이 알고리즘은 조인 키 필터를 스토리지 계층으로 직접 푸시다운합니다. 키가 테이블의 프라이머리 키 인덱스를 lookup에 사용할 수 있으면 더 효율적일 수 있지만, 그렇지 않으면 왼쪽 테이블의 각 블록마다 오른쪽 테이블 전체를 스캔합니다.
INNER 및 LEFT 조인만 지원하며, 다른 조건 없이 단일 컬럼 동등 조인 키만 지원합니다.
- auto
auto로 설정하면 먼저 hash 조인을 시도하고, 메모리 제한을 초과하면 실행 중에 다른 알고리즘으로 전환합니다.
- full_sorting_merge
- ie_join
<, <=, >, >=)가 2개 있는 ON 절을 포함하는 JOIN을 위한 정렬 기반 IEJoin 알고리즘입니다. ALL INNER/LEFT/RIGHT/FULL JOIN 및 SEMI/ANTI LEFT/RIGHT JOIN을 지원합니다.
목록 내 위치가 우선순위를 결정합니다. 기본값처럼 다른 알고리즘 뒤에 나열하면 IEJoin은 해당 알고리즘을 적용할 수 없을 때만 사용됩니다(ON 절에 동등 조건이 없는 경우). 첫 번째로 나열하면 ON 절에 부등 조건이 2개 있을 때마다 사용됩니다. 나머지 조건(동등 조건 포함)은 ALL INNER JOIN에서는 조인 결과에 대한 필터로 적용되며, 다른 Kind에서는 매칭에 영향을 주는 잔여 조건으로 연산자 내부에서 평가됩니다. ON 절에 적합한 부등 조건이 2개를 초과하면, 알고리즘에서 사용할 2개는 컬럼 min/max 통계의 추정 선택도를 기준으로 선택합니다(Column statistics의 basic 유형 참조). 추정값을 사용할 수 없는 경우(통계가 없거나 use_statistics가 비활성화된 경우)에는 구문 순서상 처음 2개를 사용합니다. 목록에 ie_join이 없으면 부등 조건만 있는 INNER JOIN은 필터가 적용된 CROSS JOIN으로 실행되며, 다른 Kind는 지원되지 않습니다.
두 입력은 조인 전에 메모리에 누적됩니다. max_rows_in_join 및 max_bytes_in_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
partial_merge 조인을 사용하려 시도하며, 그렇지 않으면 hash를 사용합니다. Deprecated, partial_merge,hash와 같습니다.
- default (deprecated)
direct,hash와 같습니다. 즉, direct 조인과 해시 조인을 이 순서대로 사용하려 시도합니다.
join_any_take_last_row
오른쪽 테이블에서 하나의 키에 일치하는 행이 여러 개 있을 때ANY 엄격성을 사용하는 JOIN 작업의 동작을 변경합니다.
이 설정은
Join 테이블 엔진을 사용하는 테이블과 해시 기반 조인 알고리즘에 적용됩니다.조인이 병렬로 구성되면 행의 순서가 비결정적일 수 있습니다. 즉, join_any_take_last_row = 1은 ANY JOIN 쿼리에서 비결정적인 행을 반환할 수 있습니다.- 0 — 오른쪽 테이블에 일치하는 행이 여러 개 있으면, 먼저 발견된 행만 조인됩니다.
- 1 — 오른쪽 테이블에 일치하는 행이 여러 개 있으면, 마지막에 발견된 행만 조인됩니다.
join_default_strictness
JOIN 절의 기본 엄격성을 설정합니다. 가능한 값:ALL— 오른쪽 테이블에 일치하는 행이 여러 개 있으면 ClickHouse는 일치하는 행들로 카테시안 곱을 생성합니다. 이는 표준 SQL의 일반적인JOIN동작입니다.ANY— 오른쪽 테이블에 일치하는 행이 여러 개 있으면, 먼저 찾은 첫 번째 행만 조인됩니다. 오른쪽 테이블에 일치하는 행이 하나뿐이면ANY와ALL의 결과는 같습니다.ASOF— 정확히 일치하지 않는 시퀀스를 조인할 때 사용합니다.빈 문자열— 쿼리에서ALL또는ANY를 지정하지 않으면 ClickHouse가 예외를 발생시킵니다.
join_on_disk_max_files_to_merge
디스크에서 실행되는 MergeJoin 작업의 병렬 정렬에 사용할 수 있는 파일 수를 제한합니다. 이 설정값이 클수록 더 많은 RAM을 사용하고, 필요한 디스크 I/O는 줄어듭니다. 가능한 값:- 2 이상의 모든 양의 정수.
join_output_by_rowlist_perkey_rows_threshold
해시 조인에서 행 목록으로 출력할지 결정할 때 사용하는, 오른쪽 테이블의 키별 평균 행 수 하한값입니다.join_overflow_mode
조인이 다음 제한 중 하나에 도달할 때 ClickHouse가 수행할 동작을 정의합니다: 해시 기반의 모든join_algorithm
값은 디스크로 스필하는 알고리즘을 포함해 이 설정을 따릅니다. 즉, 제한에
도달하면 스필이 발생하는 대신 쿼리가 중지됩니다. 예외는
legacy_join_size_limits_trigger_spilling으로, 이 설정을 켜면 이미 디스크에서
실행 중인 조인 부분은 이 설정을 따르는 대신 계속 스필합니다.
ie_join 또한 양쪽에서 누적한 입력에 대해 이 설정을 따릅니다. partial_merge는 여전히
전략을 전환하는 방식으로 제한을 처리합니다. 자세한 내용은
join_algorithm을 참조하십시오.
가능한 값:
THROW— ClickHouse는 예외를 발생시키고 쿼리를 중지합니다.BREAK— ClickHouse는 쿼리를 중지하고 예외를 발생시키지 않습니다.
THROW.
관련 항목