- 특히
JOIN과 함께 사용할 때 쿼리 성능 향상 - 수집 프로세스의 속도를 저하시키지 않으면서 수집된 데이터를 실시간으로 보강
딕셔너리를 사용해 조인 속도 높이기
JOIN 속도를 높이는 데 사용할 수 있습니다. 여기서 말하는 유형은 조인 키가 기반 키-값 저장소의 키 속성과 일치해야 하는 LEFT ANY 유형입니다.
이 경우 ClickHouse는 딕셔너리를 활용해 Direct Join을 수행할 수 있습니다. 이는 ClickHouse에서 가장 빠른 조인 알고리즘이며, 오른쪽 테이블의 기반 테이블 엔진이 지연 시간이 짧은 키-값 요청을 지원할 때 적용할 수 있습니다. ClickHouse는 이를 지원하는 3개의 테이블 엔진을 제공합니다. Join(기본적으로 미리 계산된 해시 테이블), EmbeddedRocksDB, Dictionary입니다. 여기서는 딕셔너리 기반 접근 방식을 설명하지만, 동작 원리는 세 엔진 모두 동일합니다.
Direct Join 알고리즘을 사용하려면 오른쪽 테이블이 딕셔너리를 기반으로 해야 합니다. 즉, 해당 테이블에서 조인할 데이터가 이미 메모리에 지연 시간이 짧은 키-값 데이터 구조 형태로 존재해야 합니다.
예시
posts 테이블과 votes 테이블을 사용하는 JOIN이 필요합니다.
이 쿼리는 빠르지만, 좋은 성능을 내려면JOIN의 오른쪽에는 더 작은 데이터셋을 사용하십시오: 이 쿼리는 필요 이상으로 장황해 보일 수 있으며,PostId에 대한 필터링이 외부 쿼리와 서브쿼리 양쪽에 모두 들어갑니다. 이는 쿼리 응답 시간을 빠르게 유지하기 위한 성능 최적화입니다. 최적의 성능을 위해서는 항상JOIN의 오른쪽이 더 작은 집합이 되도록 하고, 가능한 한 작게 유지하십시오. JOIN 성능을 최적화하고 사용 가능한 알고리즘을 이해하는 방법은 이 블로그 글 시리즈를 참고하는 것이 좋습니다.
JOIN을 신중하게 작성해야 합니다. 이상적으로는 메트릭을 계산하기 위해 해당 블로그 하위 집합의 UpVote 및 DownVote 수를 보기 전에, 먼저 “SQL”을 포함하는 게시물만 필터링하면 됩니다.
딕셔너리 적용
votes 테이블의 크기를 확인해 보겠습니다:
아래 예시에서는 딕셔너리 데이터의 원본이 ClickHouse 테이블입니다. 이것이 딕셔너리에서 가장 일반적인 소스이지만, 파일, HTTP, Postgres를 포함한 데이터베이스 등 여러 소스도 지원됩니다. 아래에서 보시겠지만 딕셔너리는 자동으로 갱신할 수 있으므로, 자주 변경되는 소규모 데이터셋을 Direct JOIN에 사용할 수 있도록 유지하는 데 매우 적합합니다.딕셔너리에는 조회에 사용할 프라이머리 키(primary key)가 필요합니다. 이는 개념적으로 트랜잭션 데이터베이스의 프라이머리 키와 동일하며, 고유해야 합니다. 위 쿼리에서는 조인 키인
PostId에 대한 조회가 필요합니다. 따라서 딕셔너리는 votes 테이블에서 PostId별 upvote와 downvote의 합계로 채워져야 합니다. 다음은 이 딕셔너리 데이터를 가져오기 위한 쿼리입니다:
자가 관리형 OSS에서는 위 명령을 모든 노드에서 실행해야 합니다. ClickHouse Cloud에서는 딕셔너리가 모든 노드로 자동 복제됩니다. 위 작업은 RAM 64GB의 ClickHouse Cloud 노드에서 실행했으며, 로드에는 36초가 소요되었습니다.딕셔너리가 사용하는 메모리를 확인하려면:
PostId의 찬성표와 반대표는 간단한 dictGet 함수로 조회할 수 있습니다. 아래에서는 게시물 11227902의 값을 조회합니다:
쿼리 시점 보강
인덱싱 시점 보강
Location은 절대 바뀌지 않는다고 가정해 보겠습니다(실제로는 바뀝니다). 구체적으로는 users 테이블의 Location 컬럼입니다. 위치별로 posts 테이블에 대한 분석 쿼리를 수행하려고 한다고 가정해 보겠습니다. 이 테이블에는 UserId가 포함되어 있습니다.
딕셔너리는 users 테이블을 기반으로 사용자 ID를 위치에 매핑합니다:
Posts 테이블에서 이 딕셔너리를 삽입 시점에 활용하려면 스키마를 수정해야 합니다:Id < 0인 사용자는 제외하여Hashed딕셔너리 유형을 사용할 수 있게 합니다.Id < 0인 사용자는 시스템 사용자입니다.
Location이 MATERIALIZED 컬럼으로 선언되어 있습니다. 즉, 값은 INSERT 쿼리의 일부로 제공할 수 있지만 항상 계산됩니다.
ClickHouse는 DEFAULT 컬럼도 지원합니다(이 경우 값은 삽입할 수도 있고, 제공되지 않으면 계산됩니다).
테이블을 채우려면 S3에서 일반적인 INSERT INTO SELECT를 사용할 수 있습니다:
고급 딕셔너리 주제
딕셔너리 갱신
MIN 600 MAX 900의 LIFETIME을 지정했습니다. LIFETIME은 딕셔너리의 갱신 주기이며, 여기서 설정한 값에 따라 600초에서 900초 사이의 임의 간격으로 주기적으로 다시 로드됩니다. 이러한 임의 간격은 많은 수의 서버에서 업데이트할 때 딕셔너리 소스에 걸리는 부하를 분산하기 위해 필요합니다. 업데이트 중에도 이전 버전의 딕셔너리는 계속 쿼리할 수 있으며, 쿼리가 차단되는 경우는 초기 적재 시뿐입니다. (LIFETIME(0))을 설정하면 딕셔너리가 갱신되지 않습니다.
딕셔너리는 SYSTEM RELOAD DICTIONARY 명령으로 강제로 다시 로드할 수 있습니다.
ClickHouse 및 Postgres와 같은 데이터베이스 소스의 경우, 주기적 간격으로 업데이트하는 대신 실제로 변경되었을 때만 딕셔너리가 업데이트되도록 쿼리를 설정할 수 있습니다(이 여부는 쿼리 응답으로 결정됩니다). 자세한 내용은 여기에서 확인할 수 있습니다.
기타 딕셔너리 유형
추가 참고 자료
- 딕셔너리 모범 사례 — 레이아웃 선택, 딕셔너리와 조인 비교, 모니터링
- 딕셔너리를 사용해 쿼리 가속화하기
- 딕셔너리용 고급 구성