데이터 스킵 인덱스

데이터 스킵 인덱스 (Data Skipping Indexes)

개요

데이터 스킵 인덱스는 그룹 범위에 대한 부분 조건(partial condition)을 저장하는 보조 구조예요. ClickHouse는 기본 인덱스처럼 스캔을 줄일 수 없지만, 조건이 그룹을 definitively 거부한다고 결정할 수 있을 때 데이터 파트의 그룹 요청 시 각 그룹 범위를 건너뛸 수 있어요. 즉 인덱스는 간단한 형식으로 정보를 저장해서, 특정 조건에 대해 그 그룹에서 답을 찾을 수 없다는 것을 입증할 수 있게 해줘요. 그 증명이 성립하면 해당 그룹은 완전히 건너뛰게 돼요.

요청이 그룹을 definitively 거부하는지 여부는 쿼리 조건이 무엇인지에 따라 달라져요. 인덱스 구조인 minmax와 같은 일부 인덱스 구조는 단순 비교(예: a > b)에 대해 "그룹을 거부한다"를 결정하기 쉬워요. set 인덱스는 그룹에 어떤 값이 있는지, 그룹 범위에 대해 일부 조건이 참인지(예: a IN (b, c))를 확정하기 쉬워요.

ClickHouse는 데이터 스킵 인덱스의 두 가지 범주인 "bloom filter"와 "minmax"를 추상화하는 여러 인덱스 유형을 제공해요. 이 유형들은 기본 구현과 물리적 저장 방식만 다르며, "범위"는 항상 그라누라(granula)라고 불리는 데이터 파트의 행 그룹이에요. ClickHouse는 그것을 저장해요.

그라누라와 데이터 스킵 인덱스의 관계

GRANULARITY는 인덱스 엔트리가 저장하는 그라누라의 개수예요. 색인은 정렬된 그라누라에 색인 엔트리를 저장해요. 아래 그림은 이 문장을 시각적으로 보여줘요. GRANULARITY = 1(index_granularity = 1)인 경우 인덱스 엔트리는 index_granularity 행으로 구성된 각 그라누라에 대해 저장돼요. 색인 엔트리는 그라누라의 일부 컬럼 값으로 구성돼요.

index granularity

GRANULARITY의 값이 2와 같이 더 크면, 2개의 그라누라마다 하나의 색인 엔트리가 저장돼요. 색인 엔트리는 2개의 그라누라의 일부 컬럼 값으로 구성돼요.

index granularity with granularity parameter greater than 2

ClickHouse의 스킵 인덱스 유형

ClickHouse는 다음과 같은 스킵 인덱스 유형을 제공해요.

그리고 관련된 Clustering index(클러스터링 인덱스)가 있어요.

이전에 이 목록에 있던 "exact" 인덱스 유형은 제거됐고 사용해서는 안 돼요. postgresql 인덱스는 실험적이고 설계가 부족해 보안 및 성능 문제가 있어요.

minmax

minmax 인덱스는 지정된 표현식의 극단값(min, max)을 저장해요. 그러한 인덱스는 ARRAY 유형의 컬럼에 유용해요. 특히 length()empty() 함수와 조합할 때 유용해요. 동일한 방식으로 단일 또는 여러 표현식의 minmax 물리적 저장을 만들기 위해 여러 인덱스를 작성할 수 있어요. minmax 인덱스는 어떤 조건에 대해서도 작동해요.

예제:

CREATE TABLE test (
    u64 UInt64,
    i32 Int32,
    s String,
    INDEX a (u64 * i32, s) TYPE minmax GRANULARITY 3,
    INDEX b (u64 * length(s)) TYPE minmax GRANULARITY 4
) ENGINE = MergeTree()
ORDER BY u64;

set

set 인덱스는 지정된 표현식의 고유 값을 저장해요. set 인덱스는 각 그라누라에서 발견되는 값의 중복을 제거하고(비록 그룹의 그라누라가 너무 많아 어떤 수준의 중복을 포함한다고 보장되지는 않지만) 인덱스 쿼리(비트 AND 연산의 결과물)에서 결정을 만들기 위해 저장된 값의 집합을 사용해요. set 인덱스는 쿼리 중에 인덱스의 값 집합이 메모리에 로드되기 때문에, 데이터 볼륨이 큰 경우 극단적으로 메모리 오버헤드를 높여요.

지정된 표현식 값의 정확한 집합을 포함하는 set 인덱스는 기본 키(또는 쿼리의 메모리 압축)에 대해서만 유용하지 않아요. 대신 각 그룹의 카디널리티가 상대적으로 낮은 컬럼들에 유용해요. 예를 들어 사용자 세션을 요약하는 컬럼이나 이벤트 유형 컬럼이 그것이에요.

set 인덱스에 대한 권장 구문:

-- `set` 인덱스의 경우 `*` 표현식은 사용하지 마세요
CREATE TABLE test (
    s String,
    INDEX idx (s) TYPE set(100) GRANULARITY 2
) ENGINE = MergeTree()
ORDER BY s;
-- `set` 인덱스는 지정된 표현식 또는 컬럼을 사용해서 만들 수 있어요
CREATE TABLE test (
    s String,
    INDEX idx (length(s)) TYPE set(100) GRANULARITY 2
) ENGINE = MergeTree()
ORDER BY s;
-- `set` 인덱스에 대한 권장하지 않는 구문: `*` 표현식은 사용하지 마세요
CREATE TABLE test (
    s String,
    INDEX idx (s *) TYPE set(100) GRANULARITY 2
) ENGINE = MergeTree()
ORDER BY s;

bloom_filter

bloom_filter 인덱스는 지정된 Bloom filter 배치를 저장해요. Bloom filter는 검색할 컬럼의 임의의 관계에 대해 생성되는 필터 유형이에요. Bloom filter를 사용하면 데이터 파일 전체를 스캔하지 않고 값의 존재를 확정할 수 있어요. 이 엔진에서 가능한 물리적 표현은 직접(as-is) 또는 n-gram이나 토큰의 Bloom filter로 구현될 수 있어요.

Bloom filter 인덱스는 주로 IN, notIn, =!= 연산자보다는 데이터 세트에서 값을 검색할 때 생산적이에요. 이름에서 알 수 있듯이, bloom_filter 인덱스는 값이 정확히 일치할 때 유용해요. 더 정확하게는 값이 인덱싱된 그라누라에 존재하는지 여부를 조회할 때 유용해요.

권장 구문:

CREATE TABLE test (
    u64 UInt64,
    i32 Int32,
    s String,
    INDEX bf (u64 * i32, s) TYPE bloom_filter GRANULARITY 3
) ENGINE = MergeTree()
ORDER BY u64;

bloom filter 형식의 인덱스가 컬럼에 대한 값을 조회할 때, 계산 시간은 그 컬럼의 형식에 따라 달라져요. 문자열 컬럼의 경우 해당 인덱스는 관련 문자열이 존재할 가능성이 있는지 판단하기 위해 각 인덱스 블록의 문자열 집합과 bloom_filter를 비교해요. 숫자 컬럼의 경우 bloom_filter를 출력으로 하는 계산을 인덱스된 Expression에 대해 수행할 수 있어요. 자세한 내용은 아래 표에서 bloom_filter의 인덱스 형식에 대한 자세한 정보를 참고해요.

대안적인 유형: ClickHouse는 bloom filter에 대한 대안적인 유형을 제공하고, ngrambf_v1tokenbf_v1을 다른 형식으로 구현할 수 있게 해줘요.

사용자 정의 Bloom filter를 사용하여: ClickHouse는 사용자가 bloom filter 인덱스에 대해 특정 해시 함수를 선택할 수 있게 해줘요. 이 기능은 SYSTEM 관련 인덱스에만 동작해요. 기본값은 cityHash64예요. Bloom filter 인덱스 생성은 PostgreSQL의 bloom 확장과 유사하게 동작해요. 자세한 내용은 이 섹션을 참고해요.

다음 표는 bloom_filter 인덱스를 지원하는 ClickHouse 데이터 유형과 지원되지 않는 데이터 유형을 보여줘요.

형식
Int, UInt (고정 폭 정수, 부호가 있는 및 부호가 없는)
Float32, Float64
Date, Date32, DateTime, DateTime64
String, FixedString, Enum, UUID, IPv6, IPv4
Decimal
Nullable(*)
LowCardinality(**)
Array(***)

* - Nullable은 bloom filter의 <TypeName>에서 사용할 수 있어요.

** - LowCardinality(String)과 같은 LowCardinality에 대해서는 bloom_filter 인덱스를 사용할 수 있어요.

*** - Array의 경우 bloom_filter 인덱스를 사용할 수 있어요.

bloom_filter 인덱스 포맷은 주어진 형식의 부호화된 값으로 구성돼요. 예를 들어 인덱스된 표현식이 String으로 유형이 지정된 col이면, 인덱스 포맷은 각 그라누라의 각 행의 col 값으로 구성돼요. 이 값만이 bloom filter에 추가돼요. bloom_filter 인덱스가 적용될 수 없는 데이터 유형(예: Tuple, Map)의 경우, 인덱스는 값으로 expression의 결과를 계산해서 나온 문자열을 사용해요.

예를 들어 col 컬럼의 형식이 Map(String, String)이고 인덱스가 INDEX bf (col) TYPE bloom_filter로 정의되면, 인덱스는 col 컬럼의 각 값에 대해 계산된 (문자열) 표현을 저장해요. 인덱스된 컬럼과 쿼리에서 사용된 값이 정확히 일치해야 해당 값에 대해 참인 그라누라를 반환해요.

bloom filter 인덱스는 연관된 epsilonbits_per_row 파라미터와 함께 정의할 수 있어요. epsilon은 해당 형식의 메모리에 저장된 false positive의 수준이에요. bits_per_row는 각 행에 할당된 bit의 수예요. false_positive의 확률은 두 파라미터에 의존해요. 기본값은 각각 0.02510이에요. false positive 확률을 낮추려면 epsilon을 낮추거나 bits_per_row를 높이면 돼요.

예시

다음은 String 유형의 Array 컬럼 arr에 대한 bloom_filter 인덱스를 만드는 예시예요.

CREATE TABLE example (
  id UInt64,
  arr Array(String),
  INDEX idx_arr (arr) TYPE bloom_filter(0.01, 10) GRANULARITY 1
) ENGINE = MergeTree()
ORDER BY id;

Array(String) 유형의 컬럼 arr에 대한 bloom filter 인덱스의 동작은 다음 쿼리로 확인할 수 있어요.

SELECT * FROM example WHERE arr = 'hello';

이 쿼리에서 arr 컬럼은 패턴 매칭 방식으로 찾아지고, bloom filter에 Array(String)의 각 값이 추가돼요(bloom filter는 중복을 제거해요). 따라서 bloom filter는 arr 값이 'hello'인 행을 탐지할 수 있어요.

tokenbf_v1

tokenbf_v1 인덱스는 모든 토큰을 저장하거나, 컬럼의 지정된 표현식을 대신해서 그것들의 Bloom filter를 저장해요. 그리고 그 인덱스는 Bloom filter에 값의 존재를 빠르게 확인하기 위해 저장된 값들을 사용해요.

tokenbf_v1 인덱스는 기본적으로 문자열 test stringteststring 같은 부분 문자열로 분리하고, 토큰의 값을 bloom filter에 추가해요. tokenbf_v1은 검색 대상(bucket)이 토큰 범위 안에 존재하는지 확인하기 위해 cupidHash64와 같은 해시 함수를 사용해요.

tokenbf_v1 인덱스는 String, FixedString, UUID, 그리고 DateTime 유형의 컬럼에 사용할 수 있어요. 토큰 분석 없이 단일 값으로 저장된 bloom_filter 인덱스와 달리, tokenbf_v1은 토큰화된 값을 저장해요. tokenbf_v1을 사용하는 인덱스 형식은 다음과 같아요.

CREATE TABLE test (
    s String,
    INDEX idx (s) TYPE tokenbf_v1(256, 0, 0) GRANULARITY 1
) ENGINE = MergeTree()
ORDER BY s;

tokenbf_v1 형식의 인덱스는 토큰화된 문자열의 해시와 Bloom filter를 결합해요. Bloom filter의 해시 함수는 tokenbf_v1 포맷 내에서 $[tokenization, ngram_size, filter_size]$ 형식의 3개 파라미터를 사용해요. 이 세 파라미터는 아래에서 자세히 설명해요.

tokenbf_v1 파라미터:

  • tokenization: 컬럼의 문자열 값을 시퀀스 토큰으로 분리하는 방식을 지정해요. 기본값은 string 토큰화이고, charset으로 설정할 수 있어요. charset은 UTF-8 문자 집합에서 ASCII 문자를 나타내는 문자로 분리해요.
  • ngram_size: 문자열의 토큰 시퀀스를 분리하는 데 사용되는 크기예요.

주의: ngrambf_v1tokenbf_v1 둘 다에 대해 실제 Bloom filter 크기는 GRAMMARITY 파라미터가 아니라 filter_size 파라미터에 의해 결정돼요. GRAMMARITY 파라미터는 인덱스가 값을 인덱스하기 위해 대상 그라누라의 개수를 정의해요.

tokenbf_v1 인덱스는 bloom_filter 인덱스의 파생 형식에 가깝고, 설정의 차이는 형식의 물리적 표현에 관한 것이에요. tokenbf_v1ngrambf_v1과 같지 않아요. tokenbf_v1은 문자열을 토큰으로 분리해서 저장하거나 문자열을 부분 문자열로 분리하는 대신 그렇게 해요.

ngrambf_v1

ngrambf_v1 인덱스는 모든 n-gram을 저장하거나, 컬럼의 지정된 표현식을 대신해서 그것들의 Bloom filter를 저장해요. 그리고 그 인덱스는 Bloom filter에 값의 존재를 빠르게 확인하기 위해 저장된 값들을 사용해요.

ngrambf_v1 인덱스는 기본적으로 문자열 test stringte, es, st, t , s, st, tr, ri, in, ng 같은 n-grams로 분리해서 bloom filter에 추가해요. 이 예시는 n=2의 경우예요. ngrambf_v1ngrams라는 n-grams로 문자열을 분리해요.

ngrambf_v1 인덱스는 String, FixedString, UUID, 그리고 DateTime 유형의 컬럼에서 사용할 수 있어요. 예시 구문은 아래와 같아요.

CREATE TABLE test (
    s String,
    INDEX idx (s) TYPE ngrambf_v1(3, 256, 2, 0) GRANULARITY 1
) ENGINE = MergeTree()
ORDER BY s;

ngrambf_v1의 파라미터는 tokenbf_v1과 유사하지만, ngram_sizengrambf_v1에서는 필수예요. ngram_size는 인덱스에서 사용할 n-gram의 크기를 지정해요. ngrambf_v1 파라미터의 구성은 아래와 같아요.

ngrambf_v1 파라미터:

  • ngram_size: 접두사와 접미사를 포함한 부분 문자열로 값을 분리하는데 사용되는 크기예요.
  • filter_size: bloom filter에 속하는 bit의 개수예요. 크기가 클수록 메모리 사용이 많아지고 false positive가 적어져요.
  • tokenization: 컬럼의 값을 부분 문자열로 분리하는 방식을 지정해요. 기본값은 ngrams이고, charset으로 설정할 수 있어요.
  • seed: bloom filter에 대한 해시 함수의 시드(seed)예요. 0은 자동으로 DNS 시드를 생성해요.

ngrambf_v1 인덱스는 LIKE 검색과 같은 부분 문자열 검색에 유용해요. ngrambf_v1 인덱스는 tokenbf_v1 인덱스와 같은 용도로 사용할 수 있지만, 더 큰 filter_size를 필요로 해요.

ann

근사 최근접 이웃(ANN) 인덱스 문서를 참고해요.

Clustering index

clustering index(클러스터링 인덱스)는 ClickHouse에서 자주 언급되는 별도의 스킵 인덱스 메커니즘이에요. 요청을 처리할 때 선택성을 위한 컬럼 저장 순서를 결정하는 기본 인덱스와 관련이 있어요. 그 메커니즘은 여기에 상세히 설명돼 있어요.

Bloom filter 대안 유형 (Alternative types of bloom filter index)

위에서 언급했듯, bloom_filter 인덱스는 ngrambf_v1tokenbf_v1 두 유형의 대안으로 구현될 수 있어요. 아래 표는 각 인덱스 유형이 제공하는 옵션을 보여줘요.

유형 추가 파라미터
bloom_filter epsilon (선택적), bits_per_row (선택적)
ngrambf_v1 ngram_size, filter_size, tokenization (선택적), seed (선택적)
tokenbf_v1 tokenization

아래 예시는 bloom_filter 대안 유형을 사용해 만들어진 인덱스가 실제로 동작하는 방식을 보여줘요. ngrambf_v1에 대한 DEFAULT 파라미터 조합이 어떻게 동작하는지 보여주는 예시예요.

CREATE TABLE tbl
(
    col String,
    INDEX idx1 col TYPE ngrambf_v1 DEFAULT GRANULARITY 1,
    INDEX idx2 col TYPE ngrambf_v1(3, 256, 2, 0) GRANULARITY 1
)
ENGINE = MergeTree
ORDER BY col;

ngrambf_v1과 같은 이름에서 알 수 있는 것처럼 DEFAULT를 사용하면 ngrambf_v1의 기본값이 사용되고, 두 형태로 동일한 동작을 만들어요.

Selecting a bloom filter implementation

이 절은 ClickHouse에서 어떤 bloom filter 구현을 선택해야 하는지 결정하는 데 도움을 주기 위한 것이에요. ClickHouse에서 bloom filter 구현에 대한 요구 사항은 CREATE TABLE 문의 TYPE 키워드와 함께 지정할 수 있어요. 예:

CREATE TABLE test
(
  s String,
  INDEX idx (s) TYPE bloom_filter(0.001, 10) GRANULARITY 1
) ENGINE = MergeTree
ORDER BY s;

bloom_filter에 대한 기본 구현은 cityHash64를 사용하고, epsilonbits_per_row에 대한 기본값은 각각 0.02510이에요. 이 값들은 false positive 확률을 결정해요. 안전한 기본값은 bits_per_row를 알고 있고 epsilon을 고르는 것이에요. epsilon이 낮을수록 false positive가 적어지지만 저장 공간이 커져요. bits_per_row는 false positive 확률에 큰 영향을 미치는 파라미터예요. 큰 값은 높은 정확도를 제공하지만 더 많은 저장 공간을 요구해요. bits_per_rowepsilon은 저장 공간과 정확도 사이의 균형을 결정해요. 이 두 파라미터는 해시 함수와 결합되어 bloom filter를 구성해요. 특정 유형의 bloom filter를 선택해서 테스트하는 것이 일반적으로 권장돼요. 예를 들어 bloom_filter에 대한 다른 종류의 bloom filter를 사용해 보는 것이 좋아요. ClickHouse에서 bloom filter의 사용자 정의 구현을 위한 옵션은 아래에 나열돼 있어요.

ClickHouse에서 어떤 bloom filter를 사용할지 결정하기 위한 두 가지 옵션이 가능해요:

  1. N-gram 방식의 bloom filter 구현을 사용해요. 이는 LIKE 쿼리와 같은 부분 문자열 검색을 수행할 때 유용해요. <n> 값은 최대한 길게 설정하는 것이 좋아요. 이 길이는 논리적으로 사용할 tokenizing 최대 크기와 같아야 해요. 항상 n-gram bloom filter를 사용할 가치가 있어요.
  2. 토큰 기반 bloom filter 구현을 사용해요. 이는 문자열에서 검색을 수행할 때 유용해요. 문자열이 토큰으로 분리되고 각 토큰이 bloom filter에 추가돼요. 이는 특히 키의 엔트로피가 높고 인덱스된 컬럼이 작은 경우에 유용해요.

해시 함수 선택: ClickHouse는 사용자 정의 bloom filter 구현을 선택할 수 있게 해줘요. bloom_filter 인덱스의 경우 해시 함수는 TYPE bloom_filter(epsilon, bits_per_row)의 형태를 통해 지정할 수 있어요. 예를 들어 TYPE bloom_filter(0.001, 10). 이 형식으로 해시 함수를 선택하면 bloom filter의 정확성과 성능이 달라져요. 예를 들어 xxHash64cityHash64보다 빠르지만 더 많은 메모리를 사용해요; murmurHash3_128는 정확도가 높지만 더 느려요. 이런 trade-off를 고려해서 선호하는 해시 함수를 선택하면 돼요.

성능 고려 사항: bloom filter 인덱스는 부분 문자열 검색 시 성능이 크게 저하될 수 있어요. 인덱스된 컬럼의 형식에 따라 성능이 다를 수 있어요. 문자열 컬럼은 성능이 좋고, 숫자 컬럼의 경우 bloom filter는 String으로 변환된 값에 대해 수행돼요. 이는 인덱스된 컬럼의 크기에 따라 성능이 달라질 수 있어요.

저장 공간: bloom filter의 저장 공간은 각 컬럼의 형식에 따라 달라져요. String 유형 컬럼은 인덱스된 값의 크기에 비례해 저장 공간을 사용하지만, FixedString 유형 컬럼은 고정된 크기를 사용해요. epsilonbits_per_row에 따라 bloom filter의 저장 공간이 결정돼요.

Server-Side filter pushdown

postgresql 인덱스 유형(현재 제거됨)은 실험적이고 잘못 설계되어 보안 및 성능 문제가 있어요. 그 인덱스 유형을 사용하지 마세요.

전역 설정 server_filter_pushdown: 서버가 필터를 pushdown할 수 있게 하려면 설정에서 server_filter_pushdown을 활성화해야 해요. 이 설정은 여기에 설명돼 있어요.

인덱스 pushdown: 스킵 인덱스의 전체 창(window)이 pushdown 때 서버는 인덱스를 사용해 WHERE 절의 함수 조건에서 병렬화와 최적화를 수행해요. 인덱스 유형에 따라 pushdown된 함수에 대한 인덱스가 사용되거나, 인덱스가 pushdown된 함수에 대한 참조가 있는 경우 pushdown된 함수가 인덱스 정보를 사용할 수 있어요.

함수 지원

조건부 함수는 필터 조건자에 대한 인덱스를 검사할 때 사용돼요. WHERE 절 함수는 스킵 인덱스의 형식에 따라 다르게 처리돼요. 아래 표는 세 가지 스킵 인덱스 유형(minmax, set, bloom_filter)에서 쿼리 최적화를 위해 자주 사용되는 함수 목록을 보여줘요.

함수 minmax set bloom_filter ngrambf_v1 tokenbf_v1
equals (=, ==)
notEquals (!=, <>)
less (<)
greater (>)
lessOrEquals (<=)
greaterOrEquals (>=)
in
notIn
like
notLike
startsWith
endsWith
match

✔ / ❌ / ✗ 기호는 해당 인덱스 유형이 조건 함수를 지원하는지 여부를 나타내요. minmaxset 인덱스는 모든 비교 연산자를 지원해요. bloom_filter 인덱스는 in 연산자를 지원해요.

쿼리가 지원되지 않는 함수를 사용하면 ClickHouse는 인덱스 스킵을 비활성화하고 전체 테이블 스캔을 수행해요.

예시 (Example)

set 인덱스 동작:

CREATE TABLE IF NOT EXISTS skip_test
(
    id UInt64,
    name String,
    INDEX idx_name (name) TYPE set(100) GRANULARITY 2
)
ENGINE = MergeTree
ORDER BY id;

INSERT INTO skip_test VALUES (1, 'Pavlo'), (2, 'Ivan'), (3, 'Ivan'), (4, 'Timur'), (5, 'Pavlo'), (6, 'Ivan');

set 인덱스는 각 그라누라마다 값의 집합을 저장해요. 이 예시에서 GRANULARITY = 2이므로 각 인덱스 엔트리는 2개 그라누라의 값 집합을 저장해요. 데이터 인덱스가 생성되면 크기가 작아요.

SELECT * FROM skip_test WHERE name = 'Pavlo';

샘플 데이터에서 set 인덱스는 Pavlo 값이 있는 그라누라를 찾기 위해 인덱스를 스캔해요. 인덱스의 정보를 사용해 값이 Pavlo인 그라누라를 건너뛰고 Pavlo가 포함된 그라누라만 반환해요.

minmax 인덱스 동작:

CREATE TABLE IF NOT EXISTS skip_test_minmax
(
    id UInt64,
    name String,
    INDEX idx_name (name) TYPE minmax GRANULARITY 2
)
ENGINE = MergeTree
ORDER BY id;

INSERT INTO skip_test_minmax VALUES (1, 'Pavlo'), (2, 'Ivan'), (3, 'Ivan'), (4, 'Timur'), (5, 'Pavlo'), (6, 'Ivan');

minmax 인덱스는 각 그라누라에 대한 값의 최솟값과 최댓값을 저장해요.

SELECT * FROM skip_test_minmax WHERE name = 'Pavlo';

이 쿼리에서 minmax 인덱스는 각 그라누라의 값 범위를 검사해요. name의 값이 Pavlo인 경우 그라누라의 범위에 Pavlo가 있는지 확인해요. 범위에 Pavlo가 없으면 그라누라를 건너뛰고, 있으면 그라누라를 반환해요.

bloom_filter 인덱스 동작:

CREATE TABLE IF NOT EXISTS skip_test_bloom
(
    id UInt64,
    name String,
    INDEX idx_name (name) TYPE bloom_filter GRANULARITY 2
)
ENGINE = MergeTree
ORDER BY id;

INSERT INTO skip_test_bloom VALUES (1, 'Pavlo'), (2, 'Ivan'), (3, 'Ivan'), (4, 'Timur'), (5, 'Pavlo'), (6, 'Ivan');

bloom_filter 인덱스는 각 그라누라의 값에 대한 bloom filter를 저장해요. bloom filter는 값의 존재 여부를 확정하는 데 사용되는 인덱스예요.

SELECT * FROM skip_test_bloom WHERE name = 'Pavlo';

이 쿼리에서 bloom_filter 인덱스는 각 그라누라에 namePavlo의 존재 여부를 bloom filter로 확인해요. bloom filter에 Pavlo가 없으면 그라누라를 건너뛰고, 있으면 그라누라를 반환해요.

데이터 스킵 인덱스에 대한 관련 설정

더 알아보기 (Learn more)