JOIN 지원을 제공합니다. 성능을 극대화하려면 이 가이드에 나열된 조인 최적화 권장 사항을 따르는 것이 좋습니다.
- 최적의 성능을 위해서는 쿼리의
JOIN수를 줄이는 것이 좋으며, 특히 밀리초 단위의 응답 성능이 필요한 실시간 분석 워크로드에서는 더욱 중요합니다. 하나의 쿼리에서 조인은 최대 3~4개를 목표로 하십시오. 데이터 모델링 섹션에서는 비정규화, Dictionaries, 구체화된 뷰(Materialized View)를 포함해 조인을 최소화하는 여러 방법을 자세히 설명합니다. - ClickHouse 24.12부터는 쿼리 플래너가 최적의 성능을 위해 2개 테이블 조인의 순서를 자동으로 재정렬하여 더 작은 테이블을 오른쪽에 배치합니다. 25.9 버전에서는 이 기능이 확장되어 3개 이상의 테이블을 조인하는 쿼리의 조인 순서까지 최적화할 수 있게 되었습니다.
- 쿼리에 Direct JOIN, 즉 아래와 같은
LEFT ANY JOIN이 필요한 경우에는 가능하면 Dictionaries를 사용하는 것이 좋습니다.
- inner join을 수행하는 경우에는
IN절을 사용하는 서브쿼리로 작성하는 편이 더 효율적인 경우가 많습니다. 다음 쿼리를 살펴보십시오. 두 쿼리는 기능적으로 동일합니다. 둘 다 질문에는 ClickHouse가 언급되지 않았지만comments에는 언급된posts의 수를 찾습니다.
INNER join만이 아니라 ANY INNER JOIN을 사용하는 이유는 카테시안 곱이 발생하지 않도록 하기 위해서입니다. 즉, 각 게시물마다 일치하는 항목은 하나만 있으면 됩니다.
이 조인(join)은 서브쿼리(subquery)를 사용해 다시 작성할 수 있으며, 이렇게 하면 성능이 크게 향상됩니다:
JOIN할 데이터의 크기를 최소화할 수 있습니다. 아래 예시에서는 2020년 이후 Java 관련 게시물의 up-vote 수를 계산하려고 합니다.
더 큰 테이블을 왼쪽에 둔 단순한 쿼리는 56초 만에 완료됩니다:
INNER JOIN을 서브쿼리로 옮기고 외부 쿼리와 내부 쿼리 모두에 필터를 유지하면 이 쿼리를 한층 더 개선할 수 있습니다.
JOIN 알고리즘 선택
이러한 알고리즘은 조인 쿼리가 계획되고 실행되는 방식을 결정합니다. 기본적으로 ClickHouse는 사용된 조인 유형, 엄격성, 그리고 조인되는 테이블의 engine에 따라 direct 또는 해시 조인 알고리즘을 사용합니다. 또한 리소스 가용성과 사용량에 따라 런타임에 사용할 조인 알고리즘을 적응적으로 선택하고 동적으로 변경하도록 ClickHouse를 구성할 수 있습니다.
join_algorithm=auto인 경우 ClickHouse는 먼저 해시 조인 알고리즘을 시도하고, 해당 알고리즘의 메모리 제한을 초과하면 실행 중에 부분 병합 조인으로 전환합니다. 어떤 알고리즘이 선택되었는지는 trace 로깅을 통해 확인할 수 있습니다. 또한 ClickHouse는 join_algorithm setting을 통해 원하는 조인 알고리즘을 직접 지정할 수 있습니다.
각 조인 알고리즘에서 지원하는 JOIN 유형은 아래와 같으며, 최적화 전에 이를 고려해야 합니다.
각
JOIN 알고리즘에 대한 자세한 설명은 여기에서 확인할 수 있으며, 각 알고리즘의 장점, 단점, 스케일링 특성도 함께 설명합니다.
적절한 조인 알고리즘을 선택할 때는 메모리와 성능 중 무엇을 우선적으로 최적화할지에 따라 달라집니다.
JOIN 성능 최적화
-
(1) 오른쪽 테이블의 데이터를 딕셔너리와 같은 인메모리 저지연 키-값 데이터 구조에 미리 로드할 수 있고, 조인 키가 기반 키-값 저장소의 키 속성과 일치하며,
LEFT ANY JOIN동작으로 충분하다면 Direct JOIN을 적용할 수 있으며 가장 빠른 방식입니다. - (2) 테이블의 물리적 행 순서가 조인 키의 정렬 순서와 일치한다면, 상황에 따라 달라집니다. 이 경우 full sorting merge join은 정렬 단계를 건너뛰므로 메모리 사용량이 크게 줄어들고, 데이터 크기와 조인 키 값의 분포에 따라 일부 해시 조인 알고리즘보다 더 빠르게 실행될 수도 있습니다.
- (3) 오른쪽 테이블이 parallel hash join의 추가 메모리 사용 오버헤드를 감안하더라도 메모리에 들어간다면, 이 알고리즘 또는 해시 조인이 더 빠를 수 있습니다. 이는 데이터 크기, 데이터 타입, 조인 키 컬럼의 값 분포에 따라 달라집니다.
- (4) 오른쪽 테이블이 메모리에 들어가지 않는다면, 이 경우도 상황에 따라 달라집니다. ClickHouse는 메모리 제약을 받지 않는 조인 알고리즘을 세 가지 제공합니다. 이 세 가지는 모두 데이터를 일시적으로 디스크에 spill합니다. Full sorting merge join과 부분 병합 조인은 먼저 데이터를 정렬해야 합니다. 반면 Grace hash join은 대신 데이터로 해시 테이블을 구축합니다. 데이터 양, 데이터 타입, 조인 키 컬럼의 값 분포에 따라 데이터를 정렬하는 것보다 해시 테이블을 구축하는 편이 더 빠를 수 있습니다. 반대의 경우도 마찬가지입니다.
메모리 사용량 최적화
- (1) 테이블의 물리적 행 순서가 조인 키의 정렬 순서와 일치하면 full sorting merge join의 메모리 사용량은 최저 수준까지 낮아집니다. 또한 정렬 단계가 비활성화되므로 조인 속도도 우수하다는 장점이 있습니다.
- (2) grace hash join은 조인 속도를 어느 정도 희생하는 대신, 많은 수의 버킷을 사용하도록 구성하여 메모리 사용량을 매우 낮게 조정할 수 있습니다. 부분 병합 조인은 의도적으로 적은 양의 주 메모리를 사용합니다. 외부 정렬이 활성화된 full sorting merge join은 일반적으로 부분 병합 조인보다 더 많은 메모리를 사용하지만(행 순서가 키 정렬 순서와 일치하지 않는다고 가정), 그 대신 조인 실행 시간은 훨씬 더 우수합니다.