소개
기본 동작
- 인덱스 이름. 인덱스 이름은 각 파티션에 인덱스 파일을 생성하는 데 사용됩니다. 또한 인덱스를 삭제하거나 구체화할 때 매개변수로 필요합니다.
- 인덱스 표현식. 인덱스 표현식은 인덱스에 저장될 값의 집합을 계산하는 데 사용됩니다. 컬럼, 단순 연산자, 그리고/또는 인덱스 유형에 따라 허용되는 일부 함수의 조합일 수 있습니다.
- TYPE. 인덱스 유형은 각 인덱스 블록의 읽기 및 평가를 생략할 수 있는지를 판단하는 계산 방식을 제어합니다.
- GRANULARITY. 각 인덱싱된 블록은 GRANULARITY개의 그래뉼로 구성됩니다. 예를 들어, 프라이머리 테이블 인덱스의 세분화 수준이 8192행이고 인덱스 세분화 수준이 4이면, 각 인덱싱된 “block”은 32768행이 됩니다.
skp_idx_{index_name}.idx, 정렬된 표현식 값을 포함합니다skp_idx_{index_name}.mrk2, 연결된 데이터 컬럼 파일에 대한 해당 오프셋을 포함합니다.
my_value
컬럼의 1억 개 값을 모두 스캔합니다:
my_value가 125인 4,096개 행이 어떻게 읽혀 선택되었는지, 그리고 그 뒤의 행들은
디스크에서 읽지 않고 어떻게 건너뛰었는지 확인할 수 있습니다:
쿼리를 실행할 때 trace를 활성화하면 스킵 인덱스 사용에 대한 자세한 정보를 확인할 수 있습니다. clickhouse-client에서
send_logs_level을 설정하십시오:
스킵 인덱스 타입
minmax
set
text
hasAnyToken, hasAllTokens와 같은 검색 함수에서 더 나은 성능을 제공할 뿐만 아니라, 일반적으로 사용되는 모든 텍스트 검색 함수도 최적화하므로 전문 검색 쿼리에는 텍스트 인덱스를 사용하는 것이 권장됩니다.
자세한 내용은 여기의 텍스트 인덱스 문서를 참조하십시오.
블룸 필터 타입
true가 될 가능성이 있는 경우에 사용해야 합니다. 그렇지 않으면 유효한 데이터가 건너뛰어질 수 있습니다.
블룸 필터는 많은 수의 개별 값을 검사하는 작업을 더 효율적으로 처리할 수 있으므로, 검사할 값이 많이 생성되는 조건식에 적합할 수 있습니다. 특히 블룸 필터 인덱스는 배열에 적용할 수 있으며, 이 경우 배열의 모든 값을 검사합니다. 또한 mapKeys 또는 mapValues 함수를 사용해 키 또는 값을 배열로 변환하면 맵에도 적용할 수 있습니다.
블룸 필터를 기반으로 하는 데이터 스키핑 인덱스 타입은 세 가지가 있습니다.
- 기본 bloom_filter는 허용되는 “거짓 양성” 비율을 나타내는 0과 1 사이의 선택적 매개변수 하나를 받습니다(지정하지 않으면 .025를 사용합니다).
-
특수한 tokenbf_v1 (Deprecated)). 이 인덱스는 사용되는 블룸 필터를 튜닝하기 위한 세 가지 매개변수를 받습니다. (1) 바이트 단위의 필터 크기(필터가 클수록 거짓 양성은 줄어들지만 저장 공간 사용량이 늘어남), (2) 적용할 해시 함수의 수(이 역시 많을수록 거짓 양성이 줄어듦), (3) 블룸 필터 해시 함수의 시드입니다. 이러한 매개변수가 블룸 필터 동작에 어떤 영향을 미치는지에 대한 자세한 내용은 여기의 계산기를 참고하십시오.
이 인덱스는 String, FixedString, Map 데이터 타입에서만 동작합니다. 입력 표현식은 영숫자가 아닌 문자를 기준으로 구분된 문자 시퀀스로 분할됩니다. 예를 들어 컬럼 값이
This is a candidate for a "full text" search이면Thisisacandidateforfulltextsearch토큰을 포함하게 됩니다. 이 인덱스는 LIKE, EQUALS, IN, hasToken() 및 이와 유사한, 긴 문자열 내에서 단어와 기타 값을 검색하는 용도로 설계되었습니다. 예를 들어 자유 형식의 애플리케이션 로그 라인이 들어 있는 컬럼에서 소수의 클래스 이름이나 라인 번호를 검색하는 데 사용할 수 있습니다. -
특수한 ngrambf_v1 (Deprecated). 이 인덱스는 token 인덱스와 동일하게 동작합니다. 블룸 필터 설정 앞에 인덱싱할 ngram 크기를 나타내는 매개변수 하나를 추가로 받습니다. ngram은 임의의 문자로 이루어진 길이
n의 문자열이므로,A short string이라는 문자열은 ngram 크기가 4일 때 다음과 같이 인덱싱됩니다.
전문 검색 워크로드에는 더 이상 권장되지 않는 tokenbf_v1 또는 ngrambf_v1 인덱스보다 전용 text index(전문 검색용 Text index 참고)를 사용하는 것이 좋습니다. text index는 진정한 역인덱스(inverted index)를 제공하므로, 토큰 기반 블룸 필터 인덱스보다 검색 성능이 더 뛰어나고 동작이 더 예측 가능하며 유연성과 성능도 더 우수합니다.
스킵 인덱스 함수
- 데이터가 삽입될 때 인덱스가 함수형 표현식으로 정의되어 있고, 해당 표현식의 결과가 인덱스 파일에 저장되는 경우
- 쿼리를 처리할 때 저장된 인덱스 값에 표현식을 적용하여 블록을 제외할지 여부를 판단하는 경우
스킵 인덱스 설정
- use_skip_indexes (0 또는 1, 기본값 1). 모든 쿼리가 스킵 인덱스를 효율적으로 사용할 수 있는 것은 아닙니다. 특정 필터 조건이 대부분의 그래뉼을 포함할 가능성이 높다면 데이터 스키핑 인덱스를 적용해도 불필요한 비용만 발생하며, 경우에 따라 그 비용이 상당할 수 있습니다. 어떤 스킵 인덱스도 효과를 내기 어려운 쿼리에는 이 값을 0으로 설정하십시오.
- force_data_skipping_indices (쉼표로 구분된 인덱스 이름 목록). 이 설정은 일부 유형의 비효율적인 쿼리를 방지하는 데 사용할 수 있습니다. 스킵 인덱스를 사용하지 않으면 테이블 쿼리 비용이 지나치게 커지는 경우, 하나 이상의 인덱스 이름과 함께 이 설정을 사용하면 나열된 인덱스를 사용하지 않는 모든 쿼리에 대해 예외가 반환됩니다. 이렇게 하면 잘못 작성된 쿼리가 서버 리소스를 소모하는 것을 방지할 수 있습니다.
스킵 인덱스 모범 사례
timestamp이고, visitor_id에 인덱스가 있다고 가정하겠습니다. 다음 쿼리를 살펴보겠습니다:
visitor_id 컬럼의 32768개 값은 모두 검사되며,
스킵 인덱스의 유형과 관계없이 동일합니다.
따라서 ClickHouse 쿼리 속도를 높이기 위해 키
컬럼에 인덱스를 단순히 추가하려는 자연스러운 생각은 대개 올바르지 않습니다. 이 고급 기능은 프라이머리 키 수정(How to Pick a Primary Key 참조), 프로젝션 사용, 또는 materialized view 사용과 같은 다른 대안을 먼저 검토한 뒤에만 사용해야 합니다. 데이터 스키핑 인덱스가 적합한 경우에도, 인덱스와 테이블 모두에 대해
세심한 튜닝이 필요한 경우가 많습니다.
대부분의 경우 유용한 스킵 인덱스를 사용하려면 프라이머리 키와 대상 비프라이머리 컬럼/표현식 사이에 강한 상관관계가 있어야 합니다.
상관관계가 없다면(위 그림과 같이), 수천 개 값으로 이루어진
블록 안의 행 중 적어도 하나가 필터링 조건을 만족할 가능성이 높아 스킵되는 블록은 거의 없습니다. 반대로 프라이머리 키의 값 범위(예: 시간대)가
잠재적인 인덱스 컬럼의 값(예: 텔레비전 시청자 연령)과 강하게 연관되어 있다면, minmax 유형의 인덱스가
유용할 가능성이 큽니다. 또한 데이터를 삽입할 때 이 상관관계를 높일 수 있다는 점에도 유의하십시오. 예를 들어 정렬/ORDER BY 키에
추가 컬럼을 포함하거나, 프라이머리 키와 연관된 값이 삽입 시 그룹화되도록 배칭 삽입할 수 있습니다. 예를
들어 프라이머리 키가 많은 수의 사이트 이벤트를 포함하는 타임스탬프라 하더라도, 특정 site_id에 대한 모든 이벤트를
수집 프로세스에서 함께 그룹화해 삽입할 수 있습니다. 그러면 소수의 site ids만 포함하는 그래뉼이 많이 생성되므로,
특정 site_id 값으로 검색할 때 많은
블록을 스킵할 수 있습니다.
스킵 인덱스의 또 다른 좋은 후보는 높은 카디널리티를 가지며 개별 값이 데이터에서 비교적 희소한 표현식입니다. 한 가지 예로,
API 요청의 오류 코드를 추적하는 관측성 플랫폼을 들 수 있습니다. 특정 오류 코드는 데이터에서는 드물지만, 검색에서는 특히
중요할 수 있습니다. error_code 컬럼에 set 스킵 인덱스를 사용하면 오류를 포함하지 않는 대다수의 블록을
건너뛸 수 있으므로 오류 중심 쿼리의 성능을 크게 향상할 수 있습니다.
마지막으로, 가장 중요한 모범 사례는 테스트, 또 테스트, 그리고 다시 테스트하는 것입니다. 다시 말해, 문서 검색을 위한 b-tree 보조 인덱스나 inverted index와는 달리,
데이터 스키핑 인덱스의 동작은 쉽게 예측되지 않습니다. 이를 테이블에 추가하면 데이터 수집과,
여러 이유로 인덱스의 이점을 얻지 못하는 쿼리 모두에 의미 있는 비용이 발생합니다. 따라서 항상 실제 환경과 유사한 데이터로 테스트해야 하며,
테스트에는 유형, 세분화 수준 크기 및 기타 매개변수의 변형도 포함되어야 합니다. 실제로 테스트해 보면 단순한
사고 실험만으로는 분명히 드러나지 않는 패턴과 함정을 발견하는 경우가 많습니다.