시작하기 전에
nyc_taxi.trips_small_inferred 테이블을 사용합니다. 아직 테이블을 생성하고 데이터를 로드하지 않았다면 다음을 수행하십시오:
예시 데이터셋 설정
예시 데이터셋 설정
원본 Parquet 파일의 크기는 약 5.8 GB입니다. 네트워크 환경과 사용 가능한 리소스에 따라 로드하는 데 몇 분 정도 걸릴 수 있습니다.
프로세스 개요
- 기준선을 설정하기 위해 추론된 스키마를 대상으로 독립적인 워크로드 쿼리 3개를 실행합니다.
- 더 정확한 컬럼 타입을 사용해 테이블을 생성하고, 동일한 데이터를 로드한 후 쿼리를 다시 실행합니다.
- 동일하게 최적화된 스키마와 순서 지정 키를 사용해 다른 테이블을 생성한 후 쿼리를 다시 실행합니다.
기준 워크로드 정의
이러한 설정을 사용하면 테스트 중 반복 실행 결과를 비교할 수 있습니다. 측정이 끝나면 이전 값으로 복원하십시오.
system.query_log에서 이러한 값을 가져오는 방법을 포함한 전체 측정 워크플로는 반복 가능한 기준 설정를 참조하십시오.
계산된 이동 속도 필터링
특정 날짜 범위의 운행 집계
승객 수로 필터링
세 쿼리 모두 테이블의 전체 행 수에 가까운 약 3억 2,900만 행을 읽습니다. 따라서 워크로드는 두 가지 측면에서 개선할 수 있습니다. 먼저 선택한 컬럼의 처리 비용을 줄이고, 필터가 허용하는 경우 선택되는 행 수를 줄입니다.
스키마 최적화
불필요한 널 허용 컬럼 피하기
Nullable 컬럼은 값 외에 널 마스크도 저장합니다. 널 값과 타입의 기본값을 구분해야 하는 경우에는 Nullable을 사용하되, 값이 항상 존재하는 컬럼에는 사용하지 마십시오.
예시 스키마에서 사용된 컬럼의 널 값 개수를 계산합니다:
ratecode_id, mta_tax, payment_type뿐입니다. 최적화된 스키마에서는 해당 컬럼에만 Nullable을 유지하고, 나머지 컬럼에서는 제거합니다.
반복 값에 LowCardinality 사용
LowCardinality는 딕셔너리 인코딩을 사용하며, 반복 값이 많은 컬럼의 저장 공간 사용량과 처리 비용을 줄일 수 있습니다. 적용하기 전에 고유 값의 수를 확인하십시오:
LowCardinality 적용을 고려할 만하지만, 워크로드에 미치는 효과는 반드시 측정해야 합니다. 약 10,000개의 고유 값은 적용 후보를 찾는 데 유용한 출발점일 뿐, 고정된 기준은 아닙니다.
더 정밀한 데이터 타입 선택
Int64 또는 Float64를 대체하기 전에 숫자 컬럼의 최솟값과 최댓값을 확인하십시오:
UInt8 범위에 들어가지만, passenger_count는 최대값인 255에 이릅니다. 이 예시에서는 trip_distance에 Float32를 사용하고 금액 값에는 Decimal32를 사용합니다. 이 데이터셋의 모든 값은 대상 범위에 들어가며, 워크로드가 집계 결과를 비교하므로 이 예시에서는 낮아진 부동 소수점 정밀도와 센트 단위의 금액 정밀도를 허용합니다. 정확한 원본 값이 필요한 경우에는 더 넓은 원본 타입을 유지하십시오. 예시 쿼리에는 초 미만 정밀도가 필요하지 않으므로, 예시에서는 동일한 UTC 시간대의 추론된 DateTime64 컬럼을 DateTime으로 대체합니다.
이러한 선택은 이 데이터셋에만 적용됩니다. 동일한 변경 사항을 적용하기 전에 프로덕션 데이터의 범위, 정밀도, NULL 허용 여부 요구 사항을 확인하십시오.
스키마 변경 사항 적용
nyc_taxi.trips_small_inferred를 nyc_taxi.trips_small_no_pk로 바꾼 후 세 쿼리를 모두 다시 실행합니다. 원래 예시에서는 다음과 같은 대표 결과가 나왔습니다.
쿼리가 읽는 행 수는 동일하지만, 최적화된 스키마는 해당 행이 나타내는 데이터 양을 줄입니다. 따라서 선택되는 데이터를 변경하지 않고도 쿼리 실행 시간과 최대 메모리 사용량이 개선됩니다.
두 테이블의 디스크상 크기를 비교합니다.
순서 지정 키 최적화
MergeTree 제품군에서 순서 지정 키는 행이 디스크에 정렬되는 방식을 결정합니다. ClickHouse는 이 순서를 기반으로 희소 프라이머리 인덱스를 구축하여 쿼리 필터 조건을 충족할 수 없는 그래뉼을 건너뜁니다. 많은 트랜잭션 데이터베이스의 프라이머리 키와 달리 고유성을 보장하지는 않습니다.
순서 지정 키는 중요한 반복 쿼리에서 사용하는 필터를 반영해야 합니다. 컬럼 순서도 중요합니다. 쿼리가 유용한 접두사로 필터링할 때 키의 효과가 가장 큽니다. 카디널리티가 낮은 컬럼은 자주 필터링된다면 효과적인 선행 항목이 될 수 있으며, 시간 기반 워크로드에서는 시간 구성 요소도 유용한 경우가 많습니다. 자세한 선택 지침은 프라이머리 키 선택을 참조하십시오.
이 예시에서는 (passenger_count, pickup_datetime, dropoff_datetime)를 사용합니다. passenger_count는 고유값이 적고 승객 수 필터에 사용되며, pickup_datetime는 날짜 범위 집계에 사용됩니다. pickup_datetime가 첫 번째 컬럼은 아니지만, 선행 컬럼에 조건이 없더라도 ClickHouse는 뒤쪽 키 컬럼의 값을 사용해 데이터를 제외할 수 있습니다. 일반적으로 순서 지정 키의 유용한 접두사로 필터링하면 더 효과적으로 프루닝할 수 있습니다.
순서 지정 키 변경 적용
nyc_taxi.trips_small_pk로 바꾼 후, 세 쿼리를 모두 다시 실행하십시오.
결과 비교
스키마 최적화는 저장 공간을 줄이고 선택한 값을 더 적은 비용으로 처리할 수 있게 합니다. 날짜 범위 집계에서는 ClickHouse가 날짜 범위 밖의 그래뉼을 건너뛸 수 있으므로 순서 지정 키가 가장 큰 추가 개선 효과를 제공합니다. 승객 수 필터도 첫 번째 키 컬럼을 기준으로 필터링하므로 더 적은 행을 읽습니다. 계산 속도 필터는 순서 지정 키의 유용한 접두사가 아닌
pickup_datetime, dropoff_datetime, trip_distance를 기반으로 하므로 여전히 전체 테이블을 읽습니다.
EXPLAIN indexes = 1을 사용하여 날짜 범위 집계를 확인합니다:
ClickHouse 25.9 이상에서는 이러한 설정을 통해
EXPLAIN이 사용된 인덱스와 제외된 파트 및 그래뉼을 보고하도록 합니다.워크로드에 메서드 적용하기
- 기준 기간, 읽은 행 수와 바이트 수, 피크 메모리를 기록합니다.
- 선택한 컬럼에 불필요하게 큰 범위이거나 지나치게 허용적인 타입이 사용되었는지 확인합니다.
- 데이터 레이아웃은 변경하지 않고 스키마 변경을 적용한 후 측정합니다.
- 중요한 반복 쿼리에서 사용하는 필터를 기반으로 순서 지정 키를 테스트합니다.
EXPLAIN indexes = 1로 선택되는 데이터를 비교한 다음, 비교 가능한 조건에서 기준 쿼리를 다시 실행합니다.