쿼리 조건 캐시
쿼리 조건 캐시 (Query condition cache)
쿼리 조건 캐시는 같은 데이터에 같은 필터 조건을 평가하면 항상 같은 결과가 나온다는 아이디어에 기반합니다. 각 필터와 granule(기본 8192행 블록)에 대해 해당 granule의 어떤 행도 필터를 만족하지 않는지 단일 비트로 기억해, 이후 평가에서 일치하지 않는 granule을 건너뜁니다.
출처: 문서
본문
쿼리 조건 캐시는 버전 26.9부터 유일한 쿼리 분석이고 24.3부터 기본값인 애널라이저(analyzer)와 함께 동작합니다.
많은 실세계 워크로드는 같거나 거의 같은 데이터(예: 기존 데이터에 새 데이터를 더한 것)에 대한 반복 쿼리를 포함합니다. ClickHouse는 그러한 쿼리 패턴을 최적화하기 위한 다양한 최적화 기법을 제공합니다. 한 가지 가능성은 인덱스 구조(예: 기본 키 인덱스, 스킵 인덱스, 프로젝션)를 사용해 물리적 데이터 레이아웃을 조정하거나 사전 계산(머티얼라이즈드 뷰)을 하는 것입니다. 다른 가능성은 ClickHouse의 쿼리 캐시를 사용해 반복 쿼리 평가를 피하는 것입니다. 첫 번째 접근 방식의 단점은 데이터베이스 관리자의 수동 개입과 모니터링이 필요하다는 것입니다. 두 번째 접근 방식은 (쿼리 캐시가 트랜잭션적으로 일관되지 않으므로) 오래된 결과를 반환할 수 있는데, 이것은 사용 사례에 따라 받아들여질 수도 아닐 수도 있습니다.
쿼리 조건 캐시는 두 문제 모두에 대한 우아한 해결책을 제공합니다. 그것은 필터 조건(예: WHERE col = 'xyz')을 같은 데이터에 대해 평가하면 항상 같은 결과를 반환한다는 아이디어에 기반합니다. 더 구체적으로, 쿼리 조건 캐시는 평가된 각 필터와 각 granule(기본 8192행 블록)에 대해 granule의 어떤 행도 필터 조건을 만족하지 않는지 기억합니다. 정보는 단일 비트로 기록됩니다: 0 비트는 필터와 일치하는 행이 없음을, 1 비트는 일치하는 행이 하나 이상 존재함을 나타냅니다. 전자의 경우 ClickHouse는 필터 평가 중 해당 granule을 건너뛸 수 있고, 후자의 경우 granule을 로드해 평가해야 합니다.
쿼리 조건 캐시는 세 가지 전제 조건이 충족되면 효과적입니다:
- 첫째, 워크로드가 같은 필터 조건을 반복적으로 평가해야 합니다. 이것은 쿼리가 여러 번 반복되면 자연스럽게 발생하지만, 두 쿼리가 같은 필터를 공유해도 발생할 수 있습니다. 예:
SELECT product FROM products WHERE quality > 3과SELECT vendor, count() FROM products WHERE quality > 3. - 둘째, 데이터의 대부분이 불변, 즉 쿼리 사이에 변하지 않아야 합니다. ClickHouse에서는 파트가 불변이고 INSERT로만 생성되므로 일반적으로 그렇습니다.
- 셋째, 필터가 선택적(selective)이어야 합니다. 즉 상대적으로 적은 행만 필터 조건을 만족해야 합니다. 필터 조건과 일치하는 행이 적을수록 더 많은 granule이 0 비트(일치 행 없음)로 기록되고, 이후 필터 평가에서 더 많은 데이터를 "가지치기"할 수 있습니다.
메모리 소비
쿼리 조건 캐시는 필터 조건과 granule당 단일 비트만 저장하므로 메모리를 거의 소비하지 않습니다. 쿼리 조건 캐시의 최대 크기는 서버 설정 query_condition_cache_size(기본: 100 MB)로 구성할 수 있습니다. 100 MB 캐시 크기는 100 * 1024 * 1024 * 8 = 838,860,800 엔트리에 해당합니다. 각 엔트리가 마크(기본 8192행)를 나타내므로, 캐시는 단일 컬럼의 최대 6,871,947,673,600(6.8조)행을 덮을 수 있습니다. 실무에서 필터는 둘 이상의 컬럼에 대해 평가되므로 그 수는 필터링된 컬럼 수로 나눠야 합니다.
구성 설정과 사용법
use_query_condition_cache 설정은 특정 쿼리 또는 현재 세션의 모든 쿼리가 쿼리 조건 캐시를 활용해야 하는지를 제어합니다.
예를 들어, 다음 쿼리의 첫 실행:
SELECT col1, col2
FROM table
WHERE col1 = 'x'
SETTINGS use_query_condition_cache = true;
은 조건을 만족하지 않는 테이블의 범위를 저장합니다. 같은 쿼리의 이후 실행, 역시 use_query_condition_cache = true 파라미터가 있으면, 쿼리 조건 캐시를 활용해 더 적은 데이터를 스캔합니다.
ORDER BY ... LIMIT n (TopK) 쿼리
TopK 최적화(ORDER BY <column> LIMIT n, 동적 필터링 또는 정렬 컬럼의 minmax 스킵 인덱스로 가속)를 사용하는 쿼리도 쿼리 조건 캐시를 사용합니다. TopK 읽기는 쿼리가 실행되는 동안 변하는 임계값에 기반해 granule을 건너뛸 수 있으므로, 캐시 엔트리는 TopK 계획 매개변수와 읽힌 파트 집합으로 분할됩니다: 같은 파트에 대해 같은 계획을 가진 쿼리만 그것들을 재사용합니다. 그러한 읽기는 use_query_condition_cache_for_top_k(기본: 활성) 설정으로 캐시에서 완전히 제외할 수 있는데, 이것은 use_query_condition_cache도 활성화된 경우에만 효과가 있습니다.
관리
쿼리 조건 캐시는 ClickHouse 재시작 사이에 유지되지 않습니다.
쿼리 조건 캐시를 지우려면 SYSTEM CLEAR QUERY CONDITION CACHE를 실행하세요.
캐시의 내용은 시스템 테이블 system.query_condition_cache에 표시됩니다. 쿼리 조건 캐시의 현재 MB 크기를 계산하려면 SELECT formatReadableSize(sum(entry_size)) FROM system.query_condition_cache를 실행하세요. 개별 필터 조건을 조사하려면 system.query_condition_cache에서 condition 필드를 확인할 수 있습니다. 이 필드는 디버그 빌드에서만 사용 가능함을 주의하세요.
데이터베이스 시작 이후의 쿼리 조건 캐시 히트와 미스 수는 시스템 테이블 system.events에서 "QueryConditionCacheHits"와 "QueryConditionCacheMisses" 이벤트로 표시됩니다. 두 카운터 모두 use_query_condition_cache = true 설정으로 실행되는 SELECT 쿼리에 대해서만 갱신되며, 다른 쿼리는 "QueryCacheMisses"에 영향을 주지 않습니다.
관련 콘텐츠
- 블로그: Introducing the Query Condition Cache
- Predicate Caching: Query-Driven Secondary Indexing for Cloud Data Warehouses (Schmidt et. al., 2024)