Skip to main content

하위 호환되지 않는 변경 사항

쿼리, 함수 및 구문 변경 사항

  • 본문이 단일 Distributed 테이블에 대한 단순 SELECT인 뷰는 이제 외부 쿼리 전체가 세그먼트로 푸시다운됩니다(새 설정 optimize_trivial_view_pushdown_to_distributed, 기본적으로 활성화됨). 이에 따라 이러한 뷰의 관찰 가능한 동작이 달라집니다. 뷰 참조에 지정한 FINAL과 SAMPLE은 이제 무시되지 않고 세그먼트 로컬 테이블로 전달되며, 단일 세그먼트 클러스터에서는 extremes가 보고되지 않습니다. 이전 동작으로 되돌리려면 optimize_trivial_view_pushdown_to_distributed = 0으로 설정하십시오. #101791 (simonmichal).
  • 경량 UPDATE 패치 파트는 이제 (sorting_key..., _block_number, _block_offset) 기준으로 정렬된 새로운 v2 온디스크 포맷을 사용하며, 새로운 머지 알고리즘으로 적용됩니다. 최대 메모리 사용량은 전체 패치가 아니라 정렬 키가 동일한 가장 큰 구간 크기로 제한되며, 머지 경계를 넘는 업데이트도 더 이상 인메모리 Join 적용 방식으로 대체되지 않습니다. 이전 포맷의 패치 파트도 계속 읽을 수 있습니다. 26.8 이전 버전에서 롤링 업그레이드를 진행하는 동안에는 모든 레플리카의 업그레이드가 완료될 때까지 patch_parts_version = 'v1'을 유지하거나 compatibility 설정을 사용하십시오. #103182 (CurtizJ).
  • AggregatingMergeTree는 이제 정렬 키에 속하지도 않고 집계 상태 측정값(AggregateFunction/SimpleAggregateFunction)도 아닌 컬럼이 포함된 스키마를 테이블 생성 시점에 거부합니다. 이러한 컬럼은 백그라운드 머지 중에 경고 없이 임의의 값 하나로 합쳐지므로, 해당 컬럼으로 GROUP BY하거나 필터링하는 쿼리가 잘못된 결과를 반환합니다. 이전 동작으로 되돌리려면 allow_dimensions_outside_sorting_key = 1로 설정하십시오. #108087 (alexey-milovidov).
  • ClickHouse는 이제 동기 및 비동기 삽입 모두에 항상 통합 삽입 중복 제거 해시를 사용하며, 기존의 삽입별 중복 제거 동작은 제거되었습니다. 서버 설정 insert_deduplication_version은 마이그레이션 보호 장치로 유지됩니다. 이 설정이 레거시 값(old_separate_hashes 또는 compatible_double_hashes)으로 지정되어 있으면 서버가 시작되지 않습니다. 레거시 값을 사용하던 버전에서 업그레이드하려면 먼저 compatible_double_hashes를 지원하는 릴리스(레거시 해시와 통합 해시를 모두 기록함)를 실행하십시오. 복제된 테이블(Replicated Table)은 최소 replicated_deduplication_window_seconds(기본값 1시간) 동안 실행하십시오. 기본 윈도우는 해당 기간 동안 모든 삽입의 통합 해시를 보관하며, 이는 삽입 재시도 루프에 충분한 것으로 간주됩니다. non_replicated_deduplication_window > 0인 복제되지 않은 테이블에서는 이 윈도우가 시간이 아닌 개수 기준이므로, 최소한 그 개수만큼 삽입이 이루어질 때까지 compatible_double_hashes로 실행하십시오. 그런 다음 이 버전으로 업그레이드하기 전에 설정을 제거하거나 new_unified_hash로 설정하십시오. #108361 (CheSema).
  • use_legacy_to_time 설정의 기본값이 이제 0으로 변경되어, toTime은 날짜와 시간을 고정된 날짜로 변환하는 대신 값을 Time 데이터 타입으로 변환합니다. 기존 동작은 toTimeWithFixedDate 함수를 사용하거나 use_legacy_to_time = 1로 설정하여 계속 사용할 수 있습니다. #108729 (alexey-milovidov).
  • Naive Bayes 모델(naiveBayesClassifier에서 사용)은 이제 기존의 서버 측 구성(직렬화된 .bin 모델 파일을 참조하는 XML 구성 파일) 대신 NAIVE_BAYES 레이아웃을 사용하는 딕셔너리로 구성되며, 로드 시점에 클래스별로 사전 집계된 n-그램 개수를 담은 테이블로부터 빌드됩니다. 기존 방식은 더 이상 지원되지 않으므로 기존 모델은 딕셔너리로 다시 생성해야 합니다. naiveBayesClassifier와 함께 사용할 수 있는 새로운 함수 3개가 추가되었습니다. naiveBayesClassifierWithProb는 예측된 클래스를 해당 확률과 함께 반환하고, naiveBayesClassifierWithAllProbs는 모든 클래스를 각각의 확률과 함께 반환하며, naiveBayesNgrams는 딕셔너리와 동일한 방식으로 텍스트를 n-그램으로 토큰화하므로 레이블이 지정된 원시 텍스트에서 학습 데이터를 구축하는 데 활용할 수 있습니다. 또한 여러 성능 최적화가 적용되었습니다. 9.7 MiB 크기의 코드 포인트 트라이그램 언어 모델을 기준으로 메모리 사용량은 약 49배 감소했고(1.84 GiB에서 38 MiB로), 로드 속도와 분류 속도는 각각 약 11배 빨라졌습니다. #108773 (nihalzp).
  • max_insert_threads 설정의 기본값이 1(병렬 처리 없음)에서 auto로 변경되었습니다. auto는 서버에서 사용 가능한 CPU 코어 수로 결정되며, 메모리 압력이 있을 때는 max_insert_threads_min_free_memory_per_thread에 따라 줄어듭니다. 이에 따라 INSERT SELECT가 기본적으로 병렬 처리되며, 대상 쓰기 경로를 안전하게 분산할 수 있는 경우에는 조건을 충족하는 일반 INSERT의 쓰기 측도 병렬 처리될 수 있습니다. 이로 인해 생성되는 파트 수와 삽입되는 행의 순서가 달라질 수 있습니다. 이전 동작으로 되돌리려면 max_insert_threads를 1로 설정하거나 compatibility를 26.8 미만의 버전으로 설정하십시오. #109000 (alexey-milovidov). #109006 (alexey-milovidov).
  • 이제 CSV에서 bare Tuple을 읽을 때 모든 위치에서 원소마다 하나의 필드를 사용합니다. 따라서 최상위 원소의 필드에 있는 \N은 해당 원소의 값으로 처리되며, 여기에 input_format_null_as_default가 적용됩니다. 이전에는 맨 앞의 \N을 컬럼 전체가 null인 것으로 해석하여 행을 컬럼 기본값으로 대체했고, 그 결과 나머지 원소 셀의 파싱이 실패했습니다. 이 변경은 bare Tuple 전체에 대해 단일 필드만 제공하는 행과는 하위 호환되지 않습니다. 이러한 행은 이제 나머지 원소만큼 필드가 부족하므로 거부됩니다. 또한 원소가 하나뿐인 Tuple은 어느 방식이든 필드 수가 같기 때문에, 오류 없이 컬럼 DEFAULT 대신 원소 기본값이 반환됩니다. 이러한 필드를 이전처럼 컬럼 전체로 읽으려면 input_format_csv_deserialize_separate_columns_into_tuple = 0으로 설정하십시오. #109744 (groeneai).
  • CREATE USER 및 ALTER USER에 VALID UNTIL의 축약형인 VALID FOR <interval> 절이 추가되었습니다. 만료 시각은 쿼리 실행 시점의 현재 시각에 지정된 인터벌을 더해 계산되며, VALID UNTIL 형식으로 저장됩니다. 2106년 이후의 만료 시각도 정확히 표현할 수 있도록 system.users 테이블의 valid_until 컬럼 유형이 Array(DateTime)에서 Array(DateTime64(0))로 변경되었습니다. 이 컬럼을 읽는 도구는 새 유형을 처리할 수 있어야 합니다. #110171 (alexey-milovidov).
  • 이제 EXPLAIN SYNTAX는 줄마다 하나의 레코드를 반환하는 대신, 재포맷된 쿼리를 (줄바꿈이 포함된) 단일 String 레코드로 반환합니다. 따라서 출력이 그대로 활용할 수 있는 단일 행이 됩니다(예: SELECT count() FROM (EXPLAIN SYNTAX ...)는 1을 반환합니다). 이 동작은 기본값이 1인 새로운 single_record 옵션으로 제어되며, 기존처럼 줄마다 하나의 레코드를 출력하려면 single_record = 0으로 설정하십시오. 다른 EXPLAIN 종류(PLAN/PIPELINE/AST)는 기존과 같이 줄 단위 트리 출력을 유지합니다. #110479 (alexey-milovidov).
  • hasColumnInTable 함수는 더 이상 임의의 원격 서버에서 컬럼을 확인하기 위한 선택적 hostname, username, password 인수를 받지 않습니다. 이제 hasColumnInTable(database, table, column) 형식만 남아 있습니다. 제거된 원격 모드는 보안상 문제가 있었습니다. 모든 사용자가 임의의 호스트로 외부 연결을 일으킬 수 있었고, 자격 증명이 쿼리 로그에 노출되었으며, 어떠한 권한으로도 제한되지 않았습니다. #110881 (alexey-milovidov).
  • PostgreSQL 및 MaterializedPostgreSQL 데이터베이스 엔진이 이제 PostgreSQL 테이블 엔진, postgresql 테이블 함수, DDL로 생성된 딕셔너리와 마찬가지로 서버의 remote_url_allow_hosts 구성을 준수합니다. 이 정책은 CREATE DATABASE와 사용자가 직접 실행한 ATTACH DATABASE에 적용됩니다. 서버에 remote_url_allow_hosts가 구성되어 있으면, 허용 목록에 없는 호스트를 가리키는 PostgreSQL 또는 MaterializedPostgreSQL 데이터베이스를 생성하거나 ATTACH하려고 할 때 UNACCEPTABLE_URL 오류와 함께 거부됩니다. 기존 데이터베이스는 서버 시작 시 계속 로드되므로, 업그레이드 후 서버가 부팅되지 않는 상황은 발생하지 않습니다. #111135 (alexey-milovidov).
  • Arrow 및 ArrowStream 포맷용 Apache Arrow 라이브러리 기반 리더와 writer를 제거했습니다. 26.7부터 기본값이었던 ClickHouse 네이티브 구현이 이제 유일한 구현입니다. input_format_arrow_use_native_reader 및 output_format_arrow_use_native_writer 설정은 더 이상 사용되지 않습니다. 이 설정들은 여전히 지정할 수 있지만 아무런 효과가 없으므로, Apache Arrow 구현을 강제하려고 이를 0으로 설정한 쿼리도 이제 네이티브 구현을 사용합니다. #111996 (alexey-milovidov).
  • MySQL 소스의 TLS 자격 증명(ssl_ca, ssl_cert, ssl_key)은 서버가 자체 권한으로 해당 파일을 열기 때문에, 더 이상 SQL에서 파일 경로로 지정할 수 없습니다. 이는 CREATE NAMED COLLECTION으로 생성한 명명된 컬렉션, 쿼리 인수, CREATE DICTIONARY 쿼리 모두에 해당합니다. 서버 구성 파일에서는 경로를 계속 사용할 수 있습니다. 그 밖의 경우에는 새로 추가된 ssl_ca_pem, ssl_cert_pem, ssl_key_pem 매개변수에 인증서 또는 키의 내용을 전달하십시오. 이 매개변수는 비밀번호와 마찬가지로 로그와 SHOW 쿼리에서 마스킹됩니다. #112070 (alexey-milovidov).
  • disable_insertion_and_mutation은 이제 외부 스토리지에 대한 직접 쓰기는 허용하면서 Kafka, RabbitMQ, NATS 테이블의 백그라운드 소비를 차단합니다. 차단된 Kafka2, NATS, RabbitMQ 테이블은 직접 SELECT를 실행해도 컨슈머를 초기화하지 않습니다. 최근 도입된 message_queue_disable_insertion 설정을 변경하려면 이제 서버를 재시작해야 합니다. #113660 (cwurm).
  • AggregateFunction 컬럼에 대한 윈도우 PARTITION BY 또는 ORDER BY는 이제 기존 최상위 ORDER BY와 마찬가지로 ILLEGAL_COLUMN 오류와 함께 거부됩니다. 이전에는 이러한 쿼리를 적어도 하나의 분석기가 허용했으며, 윈도우 PARTITION BY는 max_threads 값에 따라 파티션 결과가 달라졌습니다. 이 제한은 Array, Tuple, Map, Variant 또는 SimpleAggregateFunction에 중첩된 상태에도 적용됩니다. 일반 타입에 대한 SimpleAggregateFunction, QBit, 그리고 상태에 대한 GROUP BY 및 DISTINCT는 영향을 받지 않습니다. #113878 (groeneai).
  • SYSTEM ... CACHE ON CLUSTER 명령의 접근 권한 검사를 수정했습니다. 이 명령들은 개별 명령의 권한 대신 SYSTEM DROP CACHE 권한 그룹을 요구했기 때문에, 세분화된 단일 캐시 권한만 가진 사용자는 실행이 거부되었고, 반대로 그룹 권한을 가진 사용자는 SYSTEM SYNC FILESYSTEM CACHE 권한 없이도 SYSTEM SYNC FILESYSTEM CACHE ON CLUSTER를 실행할 수 있었습니다. #114042 (groeneai).
  • NATS 테이블 엔진은 이제 새로운 nats_credentials 설정을 통해 자격 증명을 인라인으로 지정할 수 있으며(.creds 파일과 동일한 payload), SQL에서는 더 이상 nats_credential_file을 지정할 수 없습니다. 이 경로는 서버 파일 시스템에 있는 파일을 가리키고 서버는 자체 권한으로 해당 파일을 열기 때문에, 서버 설정 파일에 정의된 명명된 컬렉션이나 서버 구성의 nats.credential_file로만 지정할 수 있습니다. 운영자가 <nats_credential_file overridable="false">로 고정하지 않았다면, 쿼리에서 이렇게 구성된 경로를 인라인 nats_credentials로 대체할 수 있습니다. 이 제한이 도입되기 전에 생성된 테이블은 업그레이드 후에도 정상적으로 동작합니다. #114644 (alexey-milovidov).

데이터 타입 및 포맷 변경 사항

  • 객체 스토리지에 저장되는 백업, 즉 S3(...)/AzureBlobStorage(...)를 직접 지정한 대상과 S3 또는 Azure 기반 Disk(...) 대상에서는 BACKUP과 RESTORE 모두 zip/zipx 백업 아카이브 포맷을 허용하지 않습니다. Zip은 중앙 디렉터리를 읽으려면 탐색(seek)이 필요한데, 객체 스토리지에서는 이 작업이 매우 느립니다. 대신 tar.gz와 같은 tar 기반 포맷을 사용하십시오. #101770 (Onyx2406).
  • DateTime64의 지원 범위를 [1900-01-01, 2299-12-31]에서 [0000-01-01, 9999-12-31]로 확장했습니다. 이전 범위를 벗어나는 값은 이제 경계값으로 고정되지 않고 cctz를 통해 올바르게 계산됩니다. 정밀도가 8 또는 9이면 틱이 Int64로 저장되므로 범위가 여전히 더 좁습니다(나노초 정밀도에서는 최댓값이 여전히 2262-04-11입니다). 이전 버전과의 호환성: 이전에 범위를 벗어나는 날짜-시간을 사용하면서 기존 범위 내의 매우 특수한 포화(saturation) 규칙에 의존했다면, 이제 결과가 더 정확하게 바뀐다는 점에 유의하십시오. #107907 (alexey-milovidov).
  • JSONEachRow 및 유사한 포맷에서 DateTime64/DateTime 컬럼에 대한 따옴표 없는 JSON 숫자는 이제 Values 포맷, CAST, toDateTime64와 마찬가지로 Unix 타임스탬프(epoch 이후 경과한 초)로 해석되며, 초 미만 정밀도도 선택적으로 지원합니다. 이전에는 소수부가 있는 숫자(예: 1703363853.035)는 CANNOT_PARSE_INPUT_ASSERTION_FAILED 오류로 거부되었고, 정수만 있는 숫자(예: 1703363853)는 DateTime64의 스케일된 원시 값으로 읽혀 1970-... 타임스탬프가 생성되었습니다. 이는 DateTime64 컬럼에 입력되는 따옴표 없는 정수에 대한 하위 호환되지 않는 변경 사항입니다. 따옴표로 묶인 문자열과 ClickHouse 자체의 JSON 출력(항상 따옴표로 묶임)은 영향을 받지 않습니다. #108091 (alexey-milovidov).
  • 실험적 기능인 ALP 코덱이 이제 Float32 스케일링 연산을 Float64로 수행하므로, 십진 데이터에서 발생하던 예외가 사라지고 압축률이 크게 향상됩니다. #111627 (rienath).
  • Int64 마이크로초 범위를 초과하는 시간 간격 설정(밀리초/초) 값을 거부합니다 #112757 (azat).
  • 이제 비동기 메트릭에 Map 데이터 타입을 사용할 수 있으며, CPU 코어별 및 장치별 메트릭은 단일 키-값 메트릭으로 통합되었습니다. 예를 들어 OSUserTimeCPU0, OSUserTimeCPU1, …은 CPU 코어 번호를 값에 매핑하는 맵을 갖는 단일 OSUserTimeCPU 메트릭이 되었습니다(다른 OS*TimeCPU* 메트릭, CPUFrequencyMHz_*, Temperature*, EDAC*, Block*_*, Network(Receive|Send)*_*, Disk*_*, *BlobsQueueEstimate, AsyncLogging*QueueSize도 마찬가지입니다). system.asynchronous_metrics에는 새로운 key_values Map(LowCardinality(String), Float64) 컬럼이 추가되었고(이러한 메트릭의 value 컬럼은 NaN입니다), system.asynchronous_metric_log는 새로운 key 컬럼을 사용해 키마다 하나의 행으로 기록합니다. Prometheus 엔드포인트는 이러한 메트릭을 레이블과 함께 내보내며(예: ClickHouseAsyncMetrics_BlockReadBytes{device="sda"}), Graphite MetricsTransmitter는 <prefix>.<Metric>.<key> 형태로 전송합니다. 모니터링 시스템에서 기존 메트릭 이름을 읽는다면 asynchronous_metrics_key_values_mode를 legacy_names로 설정해 기존 이름을 유지하거나, 마이그레이션 기간에는 both로 설정하십시오. 이 서버 설정은 재시작 없이 SYSTEM RELOAD CONFIG로 적용할 수 있습니다. #115333 (alexey-milovidov). #116791 (alexey-milovidov).
  • 이제 객체 스토리지 디스크는 기본적으로 네이티브 메타데이터 스토리지 트랜잭션을 사용하여 메타데이터 업데이트의 일관성이 향상되었습니다. #89658 (Michicosun).

설정 및 구성 변경 사항

  • 오래전에 사용 중단 예정으로 지정되었던 함수 snowflakeToDateTime, snowflakeToDateTime64, dateTimeToSnowflake, dateTime64ToSnowflake를 제거했습니다. 이 함수들은 이미 v24.6에서 사용 중단 예정으로 지정되었으므로, 대신 snowflakeIDToDateTime, snowflakeIDToDateTime64, dateTimeToSnowflakeID, dateTime64ToSnowflakeID를 사용하십시오. 이 함수들을 다시 활성화하는 데 사용되던 설정 allow_deprecated_snowflake_conversion_functions는 이제 더 이상 사용되지 않으며 아무런 효과가 없습니다. #108711 (alexey-milovidov).
  • Date32의 지원 범위를 [1900-01-01, 2299-12-31]에서 [0000-01-01, 9999-12-31]로 확장하여 DateTime64와 동일하게 맞췄습니다. 이제 파싱 및 변환 시 값을 이전 경계로 경고 없이 잘라내지 않고 확장된 범위를 그대로 허용합니다. 이전 버전과의 호환성 관련 참고 사항: 숫자 변환 toDate32(N)에서 [120530, 2932896] 범위의 값은 이제 1970년 초의 Unix 타임스탬프가 아니라 일 번호(2300-01-01부터 9999-12-31까지의 날짜)로 해석됩니다. 이는 일 번호 범위에 속하는 숫자를 일 번호로 간주한다는 규칙에 따른 것입니다. 0000-01-01의 일 번호보다 작은 숫자와 9999-12-31 이후의 타임스탬프는 새 경계값으로 고정(saturate)됩니다. #111534 (alexey-milovidov).

기타 하위 호환되지 않는 변경 사항

  • arrayIntersect와 arraySymmetricDifference는 더 이상 한 인수 안에서 반복된 값을 여러 인수에 나타난 것처럼 취급하지 않습니다. 따라서 이전 동작에 의존하던 쿼리는 이제 다른 결과를 반환할 수 있습니다. arrayIntersect([1], [2], [1, 1])는 [1] 대신 []를 반환하고, arrayIntersect([1, 2], [2], [1, 1, 2])는 [1, 2] 대신 [2]를 반환하며, arraySymmetricDifference([1], [2], [1, 1])는 [2] 대신 [2, 1]을 반환합니다. arraySymmetricDifference는 인수가 2개만 있어도 이러한 차이가 나타납니다. arraySymmetricDifference([1], [2, 2])는 [1] 대신 [2, 1]을 반환합니다. 이제 어떤 값은 그 앞의 모든 인수에 존재했던 경우에만 해당 인수에서 집계되므로, 결과에는 모든 인수에 공통으로 존재하는 값만 정확히 포함됩니다. 이 변경의 일환으로 arrayIntersect는 모든 인수가 아닌 가장 작은 인수로 해시 테이블을 구성하므로, 인수 간 크기 차이가 클 때 최대 1.85배 빨라지고 메모리 사용량은 3분의 1 줄어듭니다. arrayUnion은 영향을 받지 않습니다. #113021 (alexey-milovidov).
  • minmax 컬럼 통계(column statistics) 유형이 사용 중단 예정으로 지정되었습니다. #108680 (hanfei1991).
  • SYSTEM PREWARM PRIMARY INDEX CACHE ... ON CLUSTER의 액세스 검사에서 SYSTEM PREWARM PRIMARY INDEX CACHE 대신 SYSTEM PREWARM MARK CACHE 권한을 잘못 요구하던 문제를 수정했습니다. #109198 (Algunenano).
  • SYSTEM STOP/START CLEANUP 및 SYSTEM STOP/START VIRTUAL PARTS UPDATE ON CLUSTER에서 SYSTEM CLEANUP / SYSTEM VIRTUAL PARTS UPDATE 대신 SYSTEM PULLING REPLICATION LOG 권한을 요구하던 문제를 수정했습니다. #110289 (groeneai).
  • / 글롭(임의 개수의 디렉터리)이 이제 같은 디렉터리에도 일치합니다. 이전에는 글롭 패턴의 /를 별도로 처리하지 않았기 때문에 data/**/file.txt가 data/file.txt(디렉터리 깊이 0)와 일치하지 않았습니다. #97676 (alexey-milovidov).

새 기능

함수 및 데이터 타입

  • AST를 JSON으로 직렬화 및 역직렬화하는 parseQueryToJSON 및 formatQueryFromJSON 함수와, enable_json_ast_dialect로 활성화되는 Experimental clickhouse_json 방언을 추가했습니다. #100412 (alexey-milovidov). #113480 (fm4v).
  • stem 함수에 지정할 수 있는 모든 스테머 언어를 보여주는 시스템 테이블 system.stemmers를 추가했습니다. #100611 (Ergus).
  • toTimeZone의 문법적 설탕(syntactic sugar)으로 표준 SQL AT TIME ZONE 및 AT LOCAL 후위 연산자를 지원합니다. 이제 expr AT TIME ZONE zone 표현식은 toTimeZone(expr, zone)과 동일하며, expr AT LOCAL은 toTimeZone(expr, timeZone())과 동일합니다. #106092 (lvzhipin03).
  • 이제 URL 테이블 엔진과 url 테이블 함수는 URL 스킴에 따라 적절한 백엔드로 요청을 전달합니다. file://은 File 엔진, s3:///gs:///gcs:///oss://는 S3, az:///azure:///abfss:///abfs://는 AzureBlobStorage, hdfs://는 HDFS가 처리하며, http(s)://는 기존과 같이 URL 엔진이 처리합니다. url_base 설정은 스킴별 전달 이전에 적용됩니다. 기본 url_scheme_mappers로 해석되는 S3 스킴만 전달되며, 그 밖의 S3 호환 벤더 스킴(cos, obs, …)은 전달되지 않으므로 s3 엔진/함수를 직접 사용해야 합니다. #106093 (alexey-milovidov).
  • QBit 컬럼과 기준 벡터 간의 근사 내적을 계산하는 dotProductTransposed 함수(별칭 scalarProductTransposed)를 추가했습니다. 이 함수는 기존 L2DistanceTransposed 및 cosineDistanceTransposed 함수를 보완합니다. #108100 (alexey-milovidov).
  • QBit 데이터 타입에 선택적 stride 매개변수(QBit(T, dimension, stride))를 추가했습니다. 이 매개변수를 사용하면 차원 그룹이 별도의 스트림에 저장되므로, 벡터 검색 시 앞쪽 차원만 효율적으로 읽을 수 있습니다(예: Matryoshka 임베딩). 전치(transposed) 거리 함수는 일부 차원만 읽을 수 있도록 선택적인 네 번째 인수 used_dims를 받습니다. #108103 (alexey-milovidov).
  • QBit 데이터 타입에서 Int8 타입을 지원하므로, 양자화된 8비트 정수 벡터를 저장하고 전치 거리 기반 벡터 검색(L2DistanceTransposed, cosineDistanceTransposed)을 수행할 수 있습니다. #108105 (alexey-milovidov).
  • 새 함수 randomHadamardTransform(vector[, seed[, output_dims]])를 추가했습니다. float 벡터에 대한 결정적(deterministic) 랜덤 Hadamard 변환으로, 노름을 보존하는 직교 회전입니다. 양자화 전에 임베딩을 전처리하는 데 유용하며, (잘라낸 경우) Johnson–Lindenstrauss / subsampled-randomized-Hadamard 랜덤 투영으로도 활용할 수 있습니다. #108227 (alexey-milovidov).
  • JSON 값에 대해 RFC 7396 방식의 merge-patch 집계를 수행하는 집계 함수 mergedJSONPatch를 구현했습니다. 상태 머지와 AggregatingMergeTree에서의 사용도 지원합니다. 타임스탬프나 다른 정렬 컬럼을 정렬 키로 사용해 JSON 컬럼을 집계하면 최신 상태를 계산할 수 있습니다. #108349 (larryluogit).
  • String 및 NULL 입력에 대해 시드 42를 사용하여 Spark 호환 xxHash64 값을 계산하고 Int64를 반환하는 xxHash64Spark 함수를 추가했습니다. #108436 (lalitium).
  • n에서 인덱스 offset(1-indexed)부터 시작하여 length개의 자릿수를 갖는 숫자를 반환하는 digits(n, offset[, length]) 함수를 추가했습니다. length를 지정하지 않으면 offset부터 끝까지의 숫자를 반환합니다. #109012 (1000ms).
  • 숫자의 제곱을 계산하는 sqr 산술 함수를 추가했습니다. #109061 (lalitium).
  • quantizeBFloat16ToInt8 Lloyd-Max 코드로 구성된 QBit(Int8)에서 동작하며 저장된 코드를 즉석에서 역양자화하는 양자화 전치 거리 함수 cosineDistanceTransposedQuantized, L2DistanceTransposedQuantized, dotProductTransposedQuantized를 추가했습니다. 부동소수점 참조 벡터는 전체 정밀도 쿼리로 취급되어 Float32 정밀도로 비교되며(Float64 쿼리는 Float32로 축소됨), Array(Int8) 참조 벡터는 그 자체도 역양자화되어 대칭적인 양자화 대 양자화 거리를 계산합니다. #109405 (alexey-milovidov).
  • 계층형 딕셔너리(hierarchical dictionary)에서 키의 최상위 조상(루트)을 반환하는 새 함수 dictGetRoot를 추가했습니다. 이 함수는 dictGetHierarchy(dict_name, key)[-1]을 간편하게 대체할 수 있습니다. #109459 (alexey-milovidov).
  • MergeTree 테이블의 (파트, 컬럼, 서브스트림)별로 각 코덱을 사용하는 압축 블록 수를 보여 주는 mergeTreeCodecBlockCounts(database, table) 테이블 함수를 추가했습니다. #109623 (rienath).
  • 배열, 맵, JSON에 대해 has의 부정 연산을 수행하는 notHas 함수를 추가했습니다. haystack이 상수 배열이면 optimize_rewrite_has_to_in(기본 활성화)에 의해 notHas(constant_array, x)가 x NOT IN constant_array로 재작성됩니다. 따라서 set 조회 방식으로 실행되며, NOT IN과 마찬가지로 프라이머리 키 인덱스를 활용한 프루닝이 가능합니다. #109926 (nihalzp).
  • Array(Point)로 저장되는 MultiPoint 지리 데이터 타입을 추가하고 Geometry 타입에 포함했습니다. #109951 (davidmenggx).
  • 이제 arrayElement(vec[n] 연산자)와 arraySlice 함수를 QBit 데이터 타입에도 사용할 수 있습니다. qbit[n]은 n번째 벡터 원소를 전체 정밀도로 반환하고, arraySlice(qbit, offset, length)는 일부 차원에 대한 프로젝션을 반환합니다. 두 함수 모두 필요한 stride 그룹의 비트 평면만 읽으며, stride 그룹 경계에 맞춰 정렬된 슬라이스는 저장된 스트림을 복사하지 않고 그대로 재사용합니다. #109953 (Utkal059).
  • 텍스트 인덱스와 tokens 함수에서 사용할 수 있는 splitByRegexp 토크나이저를 추가했습니다. 이 토크나이저는 정규식을 구분자로 사용하여 입력을 토큰으로 분할합니다. 예를 들어 tokenizer = splitByRegexp('[^\p{L}\p{N}#+]+')를 사용하면 다른 토크나이저에서는 분리되어 버리는 C++나 C#처럼 특수 문자가 포함된 토큰을 그대로 보존할 수 있습니다. #110002 (Ergus).
  • 두 지오메트리가 교차하는지 여부를 반환하는 geometryIntersectCartesian 및 geometryIntersectSpherical 함수를 추가했습니다. polygonsIntersectCartesian/polygonsIntersectSpherical과 달리 공통 Geometry 타입을 포함한 모든 지오메트리 데이터 타입(Point, LineString, MultiLineString, Ring, Polygon, MultiPolygon)을 인수로 받을 수 있으며, 두 인수의 타입이 서로 달라도 됩니다. #110062 (alexey-milovidov).
  • 네이티브 ORC 리더가 이제 ORC의 uniontype을 지원하며, 이를 ClickHouse Variant 타입으로 매핑합니다(이전에는 이러한 컬럼이 Unsupported ORC type 오류와 함께 거부되었습니다). #110078 (alexey-milovidov).
  • 네이티브 ORC 출력 포맷에서 이제 ClickHouse Variant 타입을 ORC uniontype으로 매핑하여 기록할 수 있습니다(이전에는 ILLEGAL_COLUMN 오류가 발생했습니다). #110085 (alexey-milovidov).
  • 새 설정 framing_output_format으로 선택할 수 있는 프레이밍 포맷을 추가했습니다. 프레이밍 포맷은 쿼리 응답을 구성하는 여러 부분(데이터 청크, totals 및 extremes, 진행 상황 패킷, 프로파일 이벤트, 서버 로그, 예외)을 하나의 HTTP 응답 스트림으로 다중화합니다. 구현된 프레이밍 포맷은 None(기본값, 기존과 동일하게 동작), EventStream(HTTP server-sent events), JSONEachPacketBase64, JSONEachPacketString(패킷마다 JSON 객체 하나를 사용하며, 데이터는 base64로 인코딩되거나 문자열로 표현됨)입니다. #110127 (alexey-milovidov).
  • 공개 데이터셋을 포함한 Google BigQuery 테이블을 읽고 쓸 수 있는 bigquery 테이블 함수와 BigQuery 테이블 엔진을 추가했습니다. 테이블 구조는 BigQuery 테이블 스키마로부터 자동으로 추론됩니다. 인증 방식으로는 OAuth 액세스 토큰, JSON 포맷의 서비스 계정 키, 리프레시 토큰을 사용하는 OAuth 클라이언트를 지원합니다. #110166 (alexey-milovidov).
  • LLM 제공자를 사용하여 텍스트에서 개인 식별 정보(PII)를 감지하고 마스킹하는 새 함수 aiRedact를 추가했습니다. 마스킹할 카테고리(예: ['email', 'name'])를 지정하거나, 빈 배열을 전달하여 기본 PII 카테고리 집합을 사용할 수 있습니다. 감지된 값은 토큰(기본값 [REDACTED])으로 대체됩니다. #110464 (davidmenggx).
  • LLM을 사용하여 텍스트가 자연어 조건을 만족하는지 평가하고 UInt8을 반환하는 aiFilter 함수를 추가했습니다. 이 함수는 WHERE, PREWHERE, JOIN ... ON에서 사용할 수 있습니다. #110594 (ylw510).
  • PostgreSQL 테이블 엔진, postgresql 테이블 함수, PostgreSQL 및 MaterializedPostgreSQL 데이터베이스 엔진, PostgreSQL 딕셔너리에서 PostgreSQL에 대한 TLS/SSL 연결을 지원합니다. sslmode와 함께 인증서 및 키를 리터럴 내용(sslrootcert_pem, sslcert_pem, sslkey_pem, 비밀번호처럼 마스킹됨) 또는 경로(sslrootcert, sslcert, sslkey, 서버 설정 파일에 정의된 named collection에서만 허용됨)로 지정할 수 있습니다. #110615 (alexey-milovidov).
  • 이제 postgresql 테이블 함수와 PostgreSQL 테이블 엔진을 사용하여 PostgreSQL 프로토콜로 다른 ClickHouse 서버에 연결할 수 있습니다(테이블 이름을 지정한 경우에 한하며, query(...) 변형은 아직 지원되지 않습니다). 또한 PostgreSQL 호환 함수 format_type 및 current_setting을 추가했습니다. #110760 (alexey-milovidov).
  • 임베딩 모델을 사용하여 두 텍스트 간의 의미적 유사도를 계산하는 새 함수 aiSimilarity가 추가되었습니다. [-1, 1] 범위의 Nullable(Float32) 값을 반환하며, 1은 두 텍스트가 동일함을 의미합니다. 피연산자가 NULL이거나 비어 있는 경우, 또는 임베딩 생성에 실패한 경우에는 NULL을 반환합니다. #110777 (davidmenggx).
  • Remote 및 RemoteSecure 데이터베이스 엔진이 추가되었습니다. 이 엔진은 SELECT 및 INSERT 쿼리를 원격 ClickHouse 서버로 전달하여, 해당 서버에 있는 데이터베이스의 테이블에 실시간으로 접근할 수 있게 합니다. MySQL 및 PostgreSQL 데이터베이스 엔진의 ClickHouse 간 연결 버전이라고 할 수 있습니다. #110975 (alexey-milovidov).
  • GoogleSQL의 파이프 구문과 유사하게, SQL 쿼리에서 파이프 연산자를 지원합니다(예: FROM t |> WHERE x > 1 |> AGGREGATE count() AS c GROUP BY y |> ORDER BY c DESC |> LIMIT 10). 모든 SELECT 쿼리 뒤에 |> 연산자를 연이어 붙일 수 있으며, 각 연산자는 앞의 쿼리를 서브쿼리로 감쌉니다. 따라서 생성되는 AST는 중첩 서브쿼리로 작성한 동등한 쿼리의 AST와 동일합니다. 또한 FROM 절로 시작하는 쿼리에서는 이제 SELECT 절을 생략할 수 있으며, 생략하면 SELECT *로 처리됩니다. #111151 (alexey-milovidov).
  • 유한하고 음이 아닌 숫자 값의 지니 계수를 계산하는 집계 함수 gini가 추가되었습니다. 그룹별 집계와 분산 집계도 지원합니다. #112280 (amirreza1307). #114643 (groeneai).
  • PNG 출력 형식에서 애니메이션 PNG를 지원합니다. t 컬럼이 있으면 쿼리 결과가 애니메이션으로 변환되며, t의 시간 척도는 output_format_image_time_multiplier_seconds 및 output_format_image_time_divisor_seconds로 설정합니다. output_format_image_streaming_animation을 사용하면 프레임을 메모리에 버퍼링하지 않고 쿼리가 생성하는 즉시 출력합니다. #112846 (alexey-milovidov).
  • system.mutations에 뮤테이션 완료 시각을 기록하는 finish_time 컬럼이 추가되었습니다. 완료되지 않은 뮤테이션과 완료 시각을 알 수 없는 뮤테이션은 0으로 표시됩니다. #113474 (nikitamikhaylov).
  • system.metric_log에 새로운 bucketed 스키마 유형이 추가되었습니다. 이 유형은 128개의 버킷으로 나누는 버킷 방식 Map 직렬화를 사용해 모든 메트릭을 단일 Map(Enum16(...), Int64) 컬럼에 저장하며, 호환성을 위해 메트릭별 ALIAS 컬럼도 제공합니다. 이에 따라 테이블이 수천 개가 아닌 몇 개의 컬럼으로만 구성되고, 0 값은 저장되지 않으며, 단일 메트릭을 읽을 때는 128개 버킷 중 하나만 읽습니다. 또한 이제 Enum 키를 가진 Map을 enum 값의 문자열 이름으로 인덱싱할 수 있습니다(예: map['name']). #115380 (alexey-milovidov).
  • tokens 함수와 MergeTree 텍스트 인덱스에서 사용할 수 있는 chinese 토크나이저가 추가되었습니다. 이 토크나이저는 딕셔너리와 은닉 마르코프 모델(Hidden Markov Model)을 사용해 중국어 텍스트를 단어 단위로 분할하며(알고리즘은 jieba 기반), coarse_grained(기본값)와 fine_grained 두 가지 세분화 수준을 제공합니다. #89945 (amosbird).
  • 각 그룹의 행을 지정한 출력 형식으로 포맷하여 문자열로 반환하는 groupFormat 집계 함수가 추가되었습니다. #93201 (wandersofb).
  • 집계 함수 조합자 -Tuple을 추가했습니다. 이 조합자는 기반 집계 함수를 Tuple 컬럼의 각 원소에 개별적으로 적용하고, 원소 이름을 유지한 채 그 결과를 Tuple로 반환합니다. 예를 들어 t = (a, b)일 때 sumTuple(t)는 (sum(a), sum(b))를 반환합니다. 인수가 여러 개인 집계 함수는 인수마다 튜플을 하나씩 받으며, 각 튜플의 원소는 위치별로 짝지어집니다. 예를 들어 corrTuple((a1, a2), (b1, b2))는 (corr(a1, b1), corr(a2, b2))를 반환합니다. 배열에 사용하는 -ForEach와 달리 원소마다 타입이 달라도 되며, 원소별 결과 타입과 이름도 그대로 유지됩니다. #98190 (RinChanNOWWW).

SQL 및 쿼리 기능

  • 프로젝션(projection) 정의에서 WHERE 절을 지원합니다. WHERE가 있는 프로젝션은 조건식을 만족하는 행만 구체화하며, 쿼리의 WHERE 조건이 프로젝션의 WHERE 조건을 함의하는 경우 옵티마이저가 비용 기반으로 해당 프로젝션을 사용할 수 있습니다. #102347 (SBALAVIGNESH123).
  • HTTP 인터페이스에서 URL 경로를 통해 테이블과 데이터베이스에 접근하는 방법(예: `/database/table.format.gz?filter=a>0`)을 추가했습니다. 또한 서로 조합할 수 있고 기존 `query` URL 매개변수와도 함께 사용할 수 있는 새로운 설정(`http_allow_database_as_path`, `http_allow_table_as_file`, `http_allow_filters_as_path`, `http_allow_filters_as_unrecognized_url_parameters`, `select`, `order`, `sort`, `filter`, `page`, `compression`, `format`, `input_format`, `output_format`, `default_format`, `database`)도 추가했습니다. #105249 (alexey-milovidov).
  • remote 및 remoteSecure 테이블 함수의 영구 버전인 Remote 및 RemoteSecure 테이블 엔진을 추가했습니다. 이제 CREATE TABLE ... AS remote(...)뿐만 아니라 CREATE TABLE ... ENGINE = Remote('addresses', db, table, ...)도 사용할 수 있습니다. #106189 (alexey-milovidov).
  • 쿼리 성능 분석을 위한 EXPLAIN ANALYZE를 추가했습니다. 쿼리를 실제로 실행한 뒤, 측정된 실행 메트릭을 익숙한 쿼리 플랜 형식으로 표시합니다. #106586 (Fgrtue). #110668 (Fgrtue).
  • 엔진에 관계없이 사용할 수 있는 SYSTEM STOP, SYSTEM START, SYSTEM PAUSE, SYSTEM CANCEL, SYSTEM REFRESH 명령어와 서버 전체에 적용되는 ... ALL BACKGROUND 형식을 추가했습니다. 이를 통해 Kafka, RabbitMQ, NATS, S3Queue/AzureQueue 테이블과 갱신 가능 구체화 뷰의 백그라운드 활동을 하나의 통합된 인터페이스로 제어할 수 있습니다. 갱신 가능 구체화 뷰에서는 기존 SYSTEM ... VIEW 명령어의 별칭으로 동작합니다. NATS에서 이러한 제어를 지원하면서, 이제 JetStream 테이블은 삽입이 성공한 후에만 메시지에 확인 응답을 보냅니다(at-least-once). 이전에는 메시지가 전달되는 시점에 자동으로 확인 응답되어 삽입이 실패하면 유실될 수 있었습니다. 새로운 nats_wait_for_flush_interval 설정(기본값 false, 기존의 저지연 동작 유지)을 사용하면 큐가 비는 즉시 플러시하지 않고 플러시 인터벌 동안 소비 주기를 계속 유지할 수 있습니다. 새로운 nats_commit_on_select 설정을 사용하면 JetStream 테이블에 직접 SELECT를 실행할 때 읽은 메시지를 소비(확인 응답)합니다. #107476 (NIKTONIKTO717).
  • mysql, postgresql, sqlite 테이블 함수와 테이블 엔진에서 테이블 이름 대신 사용자 쿼리를 지정하여 외부 데이터베이스에 그대로 전달할 수 있습니다. 쿼리는 서브쿼리 (SELECT ...) 또는 query('SELECT ...') 형식으로 작성합니다. 결과 테이블의 구조는 쿼리 결과를 바탕으로 추론되며, 이러한 테이블은 읽기 전용입니다. #107740 (alexey-milovidov).
  • QueryRunner 테이블 엔진을 도입했습니다. QueryRunner 테이블에 삽입된 레코드는 엔진이 실행할 쿼리를 나타냅니다. 이 엔진은 비동기 쿼리 실행, 생성된 쿼리의 일괄 실행, 원격 클러스터로의 쿼리 전달, 벤치마크, 퍼징(fuzzing), 섀도 트래픽을 이용한 테스트 등에 사용할 수 있습니다. #107888 (mstetsyuk).
  • 윈도우 함수(window functions)에서 GROUPS 프레임 모드(SQL:2011)를 지원합니다. 예: any(price) OVER (PARTITION BY symbol ORDER BY ts GROUPS BETWEEN CURRENT ROW AND 1 FOLLOWING). GROUPS 프레임에서는 경계를 피어 그룹(peer group), 즉 ORDER BY 키 값이 같은 행들의 집합 단위로 셉니다. 따라서 N PRECEDING/N FOLLOWING은 물리적인 행 수(ROWS)나 ORDER BY 값의 거리(RANGE)가 아니라, 현재 행이 속한 피어 그룹의 앞/뒤에 있는 N개의 피어 그룹을 의미합니다. #108653 (nihalzp).
  • 일반 CREATE MATERIALIZED VIEW ... POPULATE가 이제 로컬 범위에서 원자적으로 동작합니다. 소스 테이블에 짧은 배타적 잠금을 건 상태에서 뷰의 신규 삽입 구독과 기존 데이터의 스냅샷 생성을 함께 수행하므로, 데이터 채우기(population) 도중 같은 서버를 통해 동시에 삽입된 행이 더 이상 누락되거나 중복되지 않습니다(새로운 설정 materialized_views_populate_atomically, 기본적으로 활성화됨). 이 보장은 로컬 삽입 경로에만 적용되며, 다른 레플리카로 들어오거나 분산 쓰기 경로를 거치는 삽입은 대상에서 제외됩니다. 또한 고정된 스냅샷을 제공할 수 있는 소스(MergeTree 엔진 계열 및 Memory)가 필요합니다. 그 외의 소스와 CREATE OR REPLACE / REPLACE, 그리고 Replicated 데이터베이스에서 생성된 뷰는 기존의 비원자적 채우기 방식을 그대로 사용합니다. 이제 POPULATE를 TO와 함께 사용하여 대상 테이블을 백필할 수도 있습니다. #108715 (alexey-milovidov).
  • ALTER USER, ALTER ROLE, ALTER SETTINGS PROFILE에서 이제 MODIFY SETTING name = value의 별칭으로 SET name = value를 사용할 수 있습니다. 이 구문은 전체 설정 목록을 교체하는 단독 SETTINGS 절과 달리 나머지 설정은 유지한 채 개별 설정만 변경합니다. 따라서 사용자의 다른 설정을 실수로 지워버릴 위험이 줄어듭니다. #108722 (groeneai).
  • 기존 제약 조건의 표현식을 즉시 변경할 수 있는 ALTER TABLE ... MODIFY CONSTRAINT [IF EXISTS] name CHECK expr를 지원합니다. #108768 (alexey-milovidov).
  • ON 절에 조인 대상 테이블 간 부등호 비교(<, <=, >, >=)가 두 개 포함된 조인을 위해 정렬 기반 IEJoin 알고리즘을 추가했습니다. join_algorithm 설정에 ie_join을 추가하면 활성화됩니다. 지원되는 종류는 ALL INNER/LEFT/RIGHT/FULL JOIN 및 SEMI/ANTILEFT/RIGHT JOIN입니다. 이전에는 이러한 쿼리가 필터가 적용된 CROSS JOIN(INNER만 해당)으로 실행되어 대용량 테이블에서 훨씬 느렸습니다. #109920 (vdimir).
  • 새로운 시스템 테이블 system.user_query_log를 추가했습니다. 이 테이블을 사용하면 쿼리 로그 테이블에 대한 접근 권한이 없어도 각 사용자가 자신의 쿼리 로그 레코드를 조회할 수 있습니다. 최초 구현과 아이디어는 Yue Ni(@niyue)가 제공했습니다. #110156 (alexey-milovidov).
  • 새로운 설정 run_query_in_background를 추가했습니다. 서버는 쿼리를 수락하면 즉시 빈 결과를 반환하고, 연결 상태와 관계없이 쿼리를 끝까지 실행합니다. 결과는 폐기됩니다. 쿼리는 system.processes 및 system.query_log에서 query_id로 추적하십시오. 연결이 끊어져도 중단되어서는 안 되는 INSERT ... SELECT, CREATE TABLE … AS SELECT, CREATE MATERIALIZED VIEW … POPULATE와 같은 장시간 실행 쿼리용 설정입니다. #112816 (mstetsyuk).
  • ALTER TABLE … MODIFY PROJECTION을 지원하여 기존 프로젝션(projection)을 재구성하지 않고도 프로젝션 수준 설정(예: index_granularity)을 변경할 수 있습니다. 새 설정은 머지 과정에서 지연 적용됩니다. #113343 (diegomestre2).
  • 데이터 레이크용 S3 테이블 엔진 카탈로그(catalog)가 이제 기존 테이블 쿼리뿐 아니라 INSERT도 지원합니다. #113505 (scanhex12).
  • Iceberg 카탈로그가 이제 catalog_type = 'horizon'을 통해 Snowflake Horizon Catalog를 지원하므로, Snowflake에서 관리하는 Iceberg 테이블을 읽고 쓸 수 있습니다. #114547 (melvynator).
  • skip_unavailable_shards가 활성화된 경우 원격 세그먼트(shard)에서 발생한 예외 중 어떤 예외를 별도 알림 없이 무시할지 제어하는 skip_unavailable_shards_mode 설정을 추가했습니다(Distributed 엔진 설정으로도 사용 가능). 이를 통해 분산 환경에서 쿼리 동작을 더욱 세밀하게 제어할 수 있습니다. #79091 (byte-sourcerer).

저장소, 데이터 레이크, 객체 스토리지

  • Puffin 파일 포맷(https://iceberg.apache.org/puffin-spec/) 지원을 추가했습니다. 이제 file, url, s3 등의 테이블 함수에서 이 포맷을 사용할 수 있습니다. #103936 (scanhex12).
  • MergeTree 테이블에 “패킹” 데이터 파트 저장 방식을 추가했습니다. 이 방식은 스트림마다 파일을 따로 두지 않고 파트의 모든 파일을 단일 아카이브(data.packed)에 저장합니다. min_bytes_for_full_part_storage, min_rows_for_full_part_storage, min_level_for_full_part_storage 설정으로 제어하며 기본값은 비활성화입니다. 호환성 참고 사항: 테이블에 패킹 파트가 한 번이라도 기록되면 이전 버전의 서버에서는 이를 읽을 수 없습니다. 따라서 이 포맷을 활성화하면 서버를 다운그레이드할 수 없습니다. #108118 (Algunenano).
  • NATS 테이블 엔진에 nats_credentials 설정을 추가했습니다. 이제 사용자가 NATS 자격 증명을 문자열(.creds 파일의 payload와 동일)로 직접 지정할 수 있습니다. #110733 (addshore).

데이터 포맷 및 수집

  • Apache Hive LazySimpleSerDe 텍스트 형식으로 데이터를 기록하는 HiveText 출력 형식을 추가했습니다. 필드는 \x01로 구분하고, 행은 새로운 format_hive_text_rows_delimiter 설정(기본값 \n)으로 구분하며, 중첩된 Array, Map, Tuple 값에는 Hive의 구분자 목록을 사용합니다. 이 출력은 Hive의 기본 LazySimpleSerDe를 대상으로 하므로, 중첩된 값이나 사용자 정의 행 구분 기호에 대해서는 ClickHouse의 HiveText 입력과 대칭을 이루지 않습니다. #107582 (alexey-milovidov).
  • 행마다 feature 하나를 담는 GeoJSON FeatureCollection 문서를 기록하는 GeoJSON 출력 형식을 추가했습니다. 새로운 format_geojson_validate_geometry 설정(기본 활성화)은 읽기 및 쓰기 시 GeoJSON 도형을 검사합니다. 또한 GeoJSON 입력 형식은 이제 id를 Nullable(String)으로 추론하므로, 누락되었거나 null인 ID와 빈 문자열을 구분할 수 있습니다. #108065 (nihalzp).

설정, 액세스 및 관측성

  • HTTP 인터페이스의 /docs 경로에서 사용할 수 있는 내장 문서 검색 페이지를 추가했습니다. 이 페이지에서는 system.documentation 테이블을 즉시 검색할 수 있으며, 참고 문서를 구문 강조, 수식, 상호 링크와 함께 렌더링합니다. #108345 (alexey-milovidov).
  • 텍스트 인덱스와 tokens/hasAnyTokens/hasAllTokens 함수에서 사용할 수 있도록 MeCab 형태소 분석기 기반의 일본어 토크나이저를 추가했습니다. 딕셔너리는 서버 구성에 지정된 위치에서 런타임에 로드되며, 사용 전에 SHA-256 체크섬으로 검증됩니다. #111420 (Ergus).
  • use_split_cache가 활성화된 경우 시스템 캐시에 저장할 파일을 지정하는 새로운 파일 시스템 캐시 설정 system_cache_extensions를 추가했습니다. #111575 (kirillgarbar).
  • 레플리카가 뮤테이션을 로컬에서 직접 실행하지 않고 다른 레플리카로부터 뮤테이션이 적용된 파트를 다운로드할 수 있게 하는 always_fetch_mutated_part 설정을 추가했습니다. #113020 (rorylshanks).

기타 새 기능

  • 음수 LIMIT에서 WITH TIES를 지원합니다. #100930 (nihalzp).
  • 복원 대상을 세밀하게 제어할 수 있도록 restore_table_data, restore_access_entities, restore_functions 복원 설정을 추가했습니다. 이 설정을 사용하면 범주별로 structure_only를 재정의할 수 있습니다. 예를 들어 structure_only=true, restore_access_entities=true로 지정하면 테이블 데이터를 제외하고 테이블 정의와 액세스 엔터티만 복원합니다. #102402 (fm4v).
  • 이제 딕셔너리 정의에서 dictionary_lazy_load를 사용하여 딕셔너리마다 지연 로딩 여부를 개별적으로 구성할 수 있으며, 이 값은 전역 dictionaries_lazy_load 서버 설정보다 우선합니다. 따라서 일부 딕셔너리는 지연 로딩하고 나머지는 즉시 로딩할 수 있습니다. #108314 (mstetsyuk).
  • 배열 첨자 연산자에서 정수 배열을 인덱스로 사용할 수 있습니다. arr[indexes]는 지정된 모든 위치의 요소를 반환하며, arrayMap(i -> arr[i], indexes)와 동일하게 동작합니다. #108371 (ucasfl).
  • WGS84 지리 좌표와 UTM 및 MGRS 좌표계 간 변환을 위한 geoToUTM, UTMToGeo, geoToMGRS, MGRSToGeo 함수를 추가했습니다. #108939 (alexey-milovidov).
  • 딕셔너리 정의를 삭제하지 않고 딕셔너리가 사용하는 메모리를 해제하는 SYSTEM UNLOAD DICTIONARY 및 SYSTEM UNLOAD DICTIONARIES 명령을 추가했습니다. 딕셔너리는 다음에 액세스할 때 지연 방식으로 다시 로드됩니다. #109639 (Manerone).
  • 텍스트 인덱스와 tokens, hasAnyTokens, hasAllTokens 함수에서 사용할 수 있는 새로운 icu 토크나이저를 추가했습니다. 이 토크나이저는 로케일을 고려한 유니코드 단어 분할(중국어, 일본어, 태국어 등을 위한 딕셔너리 기반 분할 포함)을 제공합니다. #109940 (Ergus).
  • 새로운 코덱 ZXC를 추가했습니다. 압축은 느리지만 압축 해제가 매우 빠른 비대칭 LZ 코덱이며, 압축률은 LZ4와 ZSTD의 중간 수준입니다. #110620 (alexey-milovidov).
  • s3, s3Cluster, gcs, oss 테이블 함수와 S3 테이블 엔진에서 상대 URL을 S3 기본 URL 기준으로 해석할 수 있도록 s3_base 설정을 추가했습니다. 또한 테이블 이름을 선택적 기본 URL 기준의 URL로 해석하여 적절한 백엔드로 전달하는 URL 데이터베이스 엔진을 추가했습니다. #111512 (alexey-milovidov).
  • HTTP 인덱스 페이지(HTML 또는 일반 텍스트 형식의 디렉터리 목록)를 조회하고 일치하는 URL을 추출하는 방식으로 url() 및 URL 엔진에서 와일드카드 확장을 지원합니다. 와일드카드는 URL 경로 부분을 기준으로 매칭되며, 인덱스 페이지 크기와 읽을 수 있는 디렉터리 수에는 제한이 있습니다. #95181 (niyue).
  • kafka_sasl_mechanism에 지원 값으로 AWS_MSK_IAM을 추가했습니다. 이제 ClickHouse는 SASL/SCRAM 자격 증명을 관리할 필요 없이 IAM 역할을 사용해 Amazon MSK에 인증할 수 있습니다. #96100 (kalavt).
  • 토큰화 후 토큰을 변환하는 후처리기를 텍스트 인덱스에 추가했습니다. #98939 (Ergus).

실험적 기능

쿼리 계획 및 실행

  • 실행형 사용자 정의 함수를 위한 “드라이버”가 추가되었습니다. <user_defined_executable_function_drivers_config>에 선언된 드라이버는 CREATE FUNCTION name ARGUMENTS (...) RETURNS T ENGINE = DriverName(...) AS '...code...' 구문에서 사용할 수 있으며, 함수 생성 시점에 사용자 코드 조각을 컴파일하거나 기타 방식으로 처리하여 실행 가능한 실행형 UDF를 생성합니다. 생성된 구성은 <dynamic_user_defined_executable_functions_path>에 저장되고, 원본 쿼리는 ATTACH FUNCTION 형태로 보존되므로 서버를 재시작해도 함수가 유지됩니다. 개념 증명(proof-of-concept)용 c_function_body 드라이버는 executable_pool 모드로 샌드박스화된 Docker 컨테이너 내에서 C 함수 본문을 컴파일하고 실행합니다. #105131 (alexey-milovidov).
  • 이제 /api/v1/query 및 /api/v1/query_range에 대한 Prometheus Query API 요청이 read_rows 및 read_bytes 메트릭과 함께 system.query_log에 기록됩니다. #106611 (JTCunning).
  • make_distributed_plan이 활성화되어 있으면 MergeTree 계열 테이블의 SELECT ... FINAL에 대해 분산 쿼리 계획 기반 읽기를 지원합니다. #108148 (davenger).
  • MergeTree 쿼리에 Experimental 기능인 계획 기반 병렬 레플리카 실행을 추가했습니다. #108504 (devcrafter).
  • 상수 표현식을 평가해 쿼리 문자열을 만들고, 그 결과인 단일 SELECT 쿼리를 실행하는 Experimental 테이블 함수 eval을 추가했습니다. 이 기능은 기본적으로 비활성화되어 있으며 allow_experimental_eval_table_function 설정으로 활성화할 수 있습니다. 작성자: Yue Ni #110132 (alexey-milovidov).
  • 계획 기반 병렬 레플리카(parallel_replicas_plan_based): 이제 로컬/원격 경계가 일반 쿼리 계획에 대한 계획 수준 최적화를 통해 결정되며, UNION이 포함된 뷰에 대한 쿼리는 parallel_replicas_allow_view_over_mergetree 없이도 병렬화됩니다. 또한 IN (subquery)를 사용하는 쿼리는 이제 실패하지 않고 로컬 계획으로 대체되어 실행됩니다. #111063 (devcrafter). #112443 (devcrafter).
  • Experimental AI 함수의 보안을 강화했습니다. 원격 호스트에 대한 안전하지 않은(http) 엔드포인트를 기본적으로 차단하고(새 설정 ai_function_allow_insecure_endpoint), 쿼리당 외부 API 호출 수를 기본적으로 제한하며(ai_function_max_api_calls_per_query의 기본값이 이제 1000), 로그에 기록되는 제공자 오류 응답에서 민감한 내용을 정제합니다. #111286 (george-larionov).
  • 이제 계획 기반 병렬 레플리카(parallel_replicas_plan_based)가 조건을 충족하는 JOIN(INNER, LEFT, RIGHT, SEMI/ANTI 포함)을 분산 처리합니다. 조인 전체가 하나의 분산 계획 조각에서 실행되며, 한쪽은 레플리카 간에 조정되고 다른 쪽은 브로드캐스트됩니다. #112268 (devcrafter).
  • 분산 쿼리(make_distributed_plan = 1)가 취소되면 단순히 QUERY_WAS_CANCELLED를 반환하는 대신 취소를 유발한 오류를 보고합니다. 이전에는 실패한 worker 작업의 실제 오류를 서버 로그에서만 확인할 수 있었습니다. #112590 (davenger).
  • IN (subquery)를 JOIN으로 재작성하지 않고도 이를 포함한 쿼리 계획의 분산 실행을 지원합니다. 집합은 이니시에이터에서 한 번만 생성되며, 그 값은 worker 작업과 함께 전달됩니다. 강제로 적용되던 rewrite_in_to_join 재정의는 제거되었으며, 재작성은 명시적 설정을 통해 계속 사용할 수 있습니다. #113826 (davenger).
  • 분산 계획 쿼리(make_distributed_plan)는 이제 LIMIT이 충족되면 전체 결과를 계산한 뒤 버리는 대신 업스트림 스테이지를 중지합니다. #114806 (davenger).
  • PromQL 쿼리가 범위 선택자 안에서 offset을 사용할 때(예: rate(m[2m] offset 5m)) 발생하던 Illegal type Decimal(18, 0) of argument of function toIntervalNanosecond 오류를 수정했습니다. #114997 (nikitamikhaylov).
  • Cascades 최적화기(make_distributed_plan = 1, enable_cascades_optimizer = 1)로 생성된 분산 계획에서 GROUPING SETS 집계를 지원합니다. #115426 (davenger).
  • 이제 TimeSeries 테이블에서 “최근 샘플” 테이블을 유지할 수 있습니다. 새 엔진 설정 recent_samples_ttl_seconds가 0이 아니면 엔진은 TTL이 적용된 samples 테이블 사본(recent_samples_partition_by 기준으로 파티션되며 기본값은 일 단위)을 생성하고 삽입할 때마다 이 사본에도 기록합니다. 시간 범위가 TTL 기간 안에 들어오는 PromQL 쿼리는 자동으로 이 테이블에서 읽으므로, 대용량 테이블에서 알림/레코딩 규칙과 짧은 범위의 대시보드가 몇 배 빨라집니다. 이 테이블을 우선 사용하는 동작은 새 쿼리 수준 설정 time_series_prefer_recent_samples_table로 비활성화할 수 있습니다. #115441 (nikitamikhaylov).
  • 분산 쿼리 계획(make_distributed_plan)은 이제 LIMIT이 충족되면 유휴 상태의 업스트림 스테이지를 즉시 중지합니다. 유휴 상태의 exchange 싱크는 NoMoreDataNeeded가 도착하는 즉시 이를 읽고, 유휴 상태의 exchange 소스는 출력이 닫힌 것을 감지하여 중지 신호를 업스트림으로 전달합니다. 이전에는 이러한 스테이지가 아무도 사용하지 않는 데이터를 계속 읽고 계산했습니다. #115690 (davenger).
  • 이제 parallel_replicas_plan_based가 활성화되어 있으면 자동 병렬 레플리카 기능이 런타임 통계를 수집하여 지원되는 쿼리에 병렬 레플리카를 활성화할 수 있습니다. #115788 (devcrafter).
  • 분산 쿼리 계획을 위한 Experimental Cascades 비용 기반 최적화기를 추가했습니다. make_distributed_plan = 1과 함께 enable_cascades_optimizer = 1을 설정하면 활성화됩니다. 이 최적화기는 예상 비용을 기준으로 조인 전략(셔플, 브로드캐스트, 복제, 로컬), 집계 방식(2단계, 셔플, 로컬), 2단계 분산 top-N, 읽기 방식(병렬, 복제)을 선택하며, 필요에 따라 exchange 연산자를 삽입합니다. #86353 (davenger).

저장소, 데이터 레이크 및 인덱스

  • 역직렬화된 Paimon 메타데이터 파일(manifest 목록 및 매니페스트)을 위한 인메모리 SLRU 캐시를 추가했습니다. use_paimon_metadata_files_cache 설정으로 활성화하면 동일한 Paimon 테이블에 쿼리를 반복 실행할 때 객체 스토리지에서 메타데이터를 다시 다운로드하거나 다시 파싱하지 않습니다. #104657 (Binnn-MX).
  • 이제 Experimental ReaderExecutor(use_reader_executor, 기본값은 비활성화)가 원격 소스 연결을 열어 둔 채 순차 읽기에서 재사용할 수 있어, 스캔 시 객체 스토리지 요청 수가 줄어듭니다. #107735 (CheSema).
  • Experimental ReaderExecutor 읽기 경로(use_reader_executor, 기본값은 비활성화)에 read-through 방식의 파일 시스템 캐시를 추가했습니다. #110029 (CheSema).
  • Experimental MergeTree 설정 allow_experimental_adaptive_codec_selection을 추가했습니다. 이 설정을 활성화하면 머지 및 뮤테이션 시 기본 코덱을 사용하는 컬럼에 대해 블록마다 출력 크기가 가장 작은 코덱을 선택합니다. #111834 (rienath).
  • Experimental ReaderExecutor 읽기 경로(use_reader_executor, 기본값은 비활성화)에 사용자 공간 페이지 캐시 계층을 추가했습니다. 이제 캐시 미스가 발생하면 실행기가 사용자 공간 페이지 캐시를 채우고, 이후 읽기는 이 캐시에서 zero-copy 방식으로 처리합니다. #114890 (CheSema).
  • 이제 OPTIMIZE TABLE ... MANIFEST로 Iceberg manifest 파일 컴팩션을 수행하여 메타데이터 파일 수를 줄일 수 있습니다. 이 기능은 allow_experimental_iceberg_compaction 설정을 활성화해야 사용할 수 있습니다. #98178 (SmitaRKulkarni).

함수, 포맷 및 AI

  • Experimental: 프레디케이트가 컬럼을 기본값과 기본값이 아닌 값으로 정확히 분할하는 경우, SELECT count(*) FROM t WHERE col <op> default(col) 쿼리를 데이터 스캔 없이 serialization.json에 저장된 컬럼별 희소성 통계만으로 처리합니다. #105890 (Algunenano).
  • Experimental Quantize(...) 벡터 코덱 계열과, 양자화된 보조 스트림을 활용하는 선택적(opt-in) 2단계 근사 벡터 검색 재작성 기능을 추가했습니다. #108565 (shankar-iyer).
  • Float32/Float64 컬럼(및 이들의 배열)용 Experimental SZ3 오차 한정 손실 압축 코덱을 다시 도입했습니다. 이 코덱을 사용하려면 allow_experimental_codecs를 활성화해야 합니다. #108788 (alexey-milovidov).
  • Experimental SZ3('ALGO_LORENZO_REG', ...) 코덱으로 압축된 데이터를 읽을 때 CORRUPTED_DATA 오류가 발생하던 문제를 수정했으며, Experimental SZ3 코덱으로 유한하지 않은 부동소수점 값(NaN 및 무한대)을 압축할 때 발생하던 정의되지 않은 동작을 방지했습니다. #110762 (alexey-milovidov).
  • PromQL: 이제 날짜/시간 함수(hour(), minute(), month(), year(), day_of_week(), day_of_month(), day_of_year(), days_in_month())를 인수 없이 호출할 수 있으며, 이 경우 Prometheus와 마찬가지로 vector(time())이 기본값으로 사용됩니다. #111869 (valerypetrov).
  • PromQL: vector(1) + vector(2), topk(1, vector(1)), label_replace(vector(1), ...), on()을 사용하는 이항 연산자 등 태그가 없는 instant vector에 대한 연산이 타입 오류로 실패하던 문제를 수정했습니다. #111872 (valerypetrov).
  • PromQL: deriv 함수를 구현하면서, 밀리초 해상도의 타임스탬프에서 이 함수의 기반이 되는 집계 함수가 실제보다 1000배 작은 값을 반환하던 버그를 수정했습니다. #112360 (valerypetrov).
  • parallel_replicas_plan_based가 활성화된 경우 ORDER BY 쿼리에 순서 기반 읽기(read-in-order) 최적화를 적용합니다. 이제 정렬 작업이 레플리카로 전달된 후 initiator에서 병합되므로, 각 레플리카는 정렬 키 순서대로 데이터를 읽습니다. 또한 이 설정이 활성화된 상태에서 기본 키가 아닌 컬럼에 ORDER BY를 사용할 때 발생하던 Unknown function __topKFilter 오류도 수정했습니다. #114315 (devcrafter).
  • 데이터 파트를 다시 로드한 후(예: ATTACH 또는 서버 재시작 후) 발생하던 벡터 검색 읽기 문제를 수정했습니다. 이제 파트에서 Quantized 코덱 서브컬럼이 유실되지 않으므로, 검색 시 전체 정밀도 컬럼으로 폴백하지 않고 양자화된 서브컬럼을 읽습니다. #114763 (shankar-iyer).
  • Experimental TimeSeries 테이블 엔진은 더 이상 samples 내부 테이블에서 자동 생성되는 value 컬럼에 Gorilla 코덱을 적용하지 않으며, 이제 해당 컬럼의 기본 코덱은 CODEC(ZSTD(1))입니다. 명시적으로 선언된 컬럼은 사용자가 지정한 코덱을 그대로 유지합니다. timestamp 컬럼의 기본값(CODEC(DoubleDelta, ZSTD(1)))은 변경되지 않습니다. #112110 (nikitamikhaylov). #114790 (nikitamikhaylov).
  • make_distributed_plan = 1로 실행되는 쿼리에서 ROLLUP, CUBE, GROUPING SETS 및 grouping 함수를 지원합니다. #114950 (davenger).
  • Experimental ALP 코덱에 Real Doubles(RD) 변형과 선택적 인수 ALP(AUTO|STD|RD)를 추가했습니다. 이제 인수 없이 ALP를 사용하면 항상 STD를 사용하지 않고, 기존 STD 방식과 RD 중 하나를 자동으로 선택합니다. #99654 (nazarii-piontko).

기타 실험적 기능

  • kafka_partition_shard_num 및 kafka_shard_count 설정을 통해 StorageKafka2에 정적 파티션-세그먼트 선호도(affinity)를 추가했습니다. 이를 통해 여러 ClickHouse 세그먼트가 Kafka 파티션 중 서로 겹치지 않는 부분 집합을 결정적으로 소비할 수 있습니다. #108886 (JingYanchao).
  • 이제 onelake_client_id 및 onelake_client_secret 대신 onelake_bearer_token 설정으로 미리 발급받은 bearer 토큰을 사용하여 OneLake에 인증할 수 있습니다. 따라서 수명이 긴 클라이언트 시크릿을 공유할 필요가 없습니다. 토큰은 갱신되지 않으므로 만료되면 데이터베이스를 다시 생성해야 합니다. #109104 (asya-ch).
  • packed_skip_index_max_bytes를 통해 skp_idx.packed에 패킹된 스킵 인덱스의 data_uncompressed_bytes 값을 수정했습니다. 기존에는 압축되지 않은 크기로 압축된 크기가 보고되었으며, 이로 인해 distributed_index_analysis가 활성화되지 않는 경우도 있었습니다. #109272 (Algunenano).
  • Experimental Prometheus remote-write v1 HTTP 핸들러에 Zstandard 압축 지원을 추가했습니다. #110907 (JTCunning).
  • PromQL: clamp, clamp_min, clamp_max, round 함수를 구현했습니다. #111870 (valerypetrov).
  • PromQL: 분위수 수준이 [0, 1] 범위를 벗어나면 quantile이 이제 오류를 발생시키지 않고 Prometheus와 동일하게 -Inf/+Inf/NaN을 반환합니다. 또한 histogram_quantile은 Prometheus와 동일하게 le 레이블이 없거나 파싱할 수 없는 입력 시리즈를 무시합니다. #111871 (valerypetrov).
  • PromQL: changes() 및 resets() 함수를 구현했습니다. #112352 (valerypetrov).
  • Prometheus remote-write 엔드포인트를 통해 들어오는 insert 통계와 쿼리가 올바르게 수집되도록 수정했습니다. #112825 (JTCunning).
  • PromQL: 제수가 무한대인 나머지 연산에서 유한한 값이 그대로 유지되도록 수정했습니다. #113746 (fallintoplace).
  • 일반 따옴표로 묶인 PromQL 문자열에 포함된 리터럴 줄 바꿈을 거부하도록 변경했습니다. #114381 (fallintoplace).
  • Experimental 기능인 make_distributed_plan 및 enable_cascades_optimizer가 활성화된 상태에서 distributed_plan_workers_num 값이 매우 크면 서버가 std::length_error와 함께 비정상 종료되던 문제를 수정했습니다. 이제 이러한 노드 수는 INVALID_SETTING_VALUE 오류와 함께 거부됩니다. #115398 (groeneai).
  • TimeSeries 테이블용 Prometheus HTTP API의 /api/v1/series 엔드포인트를 구현했습니다. match[] 시리즈 셀렉터(값을 반복 지정하면 합집합으로 처리), 선택적 start/end 시간 범위, 선택적 limit 매개변수를 지원합니다. #115676 (nikitamikhaylov).

성능 개선

JOIN 및 집계 성능

  • TopK 동적 필터링(ORDER BY ... LIMIT n)을 거치는 쿼리에서도 쿼리 조건 캐시를 사용할 수 있도록 했습니다. QCC 엔트리는 TopK 계획 매개변수별로 분할되므로 동일한 쿼리는 캐시된 WHERE 필터 결과를 재사용하고, LIMIT, 정렬 컬럼 또는 정렬 방향이 다르면 새 엔트리가 생성됩니다. #104478 (alexey-milovidov).
  • GROUP BY 키가 ORDER BY 키 및 테이블 정렬 키와 일치하면 LIMIT을 순차 집계(aggregation-in-order)로 푸시하여 조기 종료할 수 있도록 했습니다. 이를 통해 읽는 행 수가 크게 줄어듭니다. #104859 (thevar1able).
  • allow_aggregate_partitions_independently를 기본으로 활성화했습니다. GROUP BY 키가 파티션 키에 적합하면 ClickHouse는 각 파티션을 독립적으로 집계하고 전역 병합 단계를 생략할 수 있습니다. 파티션 구성상 이 최적화가 불리한 경우(파티션이 너무 적거나 너무 많거나, 파티션 크기가 크게 편중된 경우)에는 런타임 휴리스틱이 자동으로 최적화를 건너뜁니다. #105128 (alexey-milovidov).
  • read_in_order_use_virtual_row를 기본으로 활성화했습니다. 파트가 많은 테이블을 프라이머리 키 순서로 읽을 때(예: ORDER BY primary_key LIMIT n) 실제로 결과에 기여할 수 있는 파트만 읽으므로(병렬 읽기를 유지하기 위해 최대 max_threads개 파트를 사전 읽기하는 구간 포함) 최대 메모리 활용량이 크게 줄어듭니다. #106215 (alexey-milovidov).
  • JOIN의 메모리 사용량을 줄이고 성능을 개선했습니다. 이제 해시 조인의 오른쪽은 8바이트 크기의 간결한 인덱스 기반 행 참조를 사용하므로, 모든 키 타입에서 ALL 조인의 해시 테이블 엔트리가 ANY 조인만큼 작아집니다. UInt64 및 String 키(고유 키와 중복 키 모두)로 1억~3억 행 테이블을 INNER 및 ANY 조인하는 대규모 parallel_hash 조인 쿼리로 벤치마크한 결과, 쿼리 중앙값 기준 약 12% 빨라지고 최대 메모리 사용량이 약 15% 줄었으며 느려진 쿼리는 없었습니다. 가장 크게 개선된 것은 UInt64 키에 대한 INNER 조인입니다(중앙값 기준 약 21% 빨라지고 메모리 38% 감소). #107189 (harikrishnan94).
  • dpsub 조인 순서 열거 알고리즘을 추가했습니다. dpsize보다 적은 최적화 오버헤드로 최적의 조인 계획을 생성하며, inner 이외의 조인도 지원합니다. #107351 (fkastrati).
  • 전체 쿼리 메모리 대신 집계 상태 전용 메모리 트래커를 연결하여, 메모리 사용량이 적은 단일 수준 집계가 2단계 집계로 전환되지 않도록 했습니다. #107490 (m-selmi).
  • 집계 해시 테이블 크기 통계 캐시 키를 AST 대신 쿼리 계획에서 계산하도록 변경하여, 집계 쿼리 분석 시 전체 쿼리 AST를 생성하지 않도록 했습니다. #107643 (novikd).
  • 첫 번째 쿼리 실행에서 수집한 런타임 통계를 바탕으로, 첫 실행에서 사용한 hash 조인을 이후 실행에서 parallel_hash로 전환할 수 있도록 했습니다. #108125 (m-selmi).
  • 런타임 조인 통계의 해시 테이블 크기를 활용하여 이후 쿼리 실행 시 조인 런타임 필터의 크기를 최적화합니다. 새로운 설정 join_runtime_filter_size_from_hash_table_stats로 제어할 수 있습니다. #108313 (m-selmi).
  • 파티션된 MergeTree 테이블에 대한 DISTINCT 쿼리에서 각 파티션의 행을 하나의 스트림 안에 유지하도록 하여 속도를 높이고 메모리 사용량을 줄였습니다. 이에 따라 동일한 키 집합이 여러 preliminary DISTINCT에 중복으로 나타나지 않고, 각 스트림의 preliminary DISTINCT가 서로 겹치지 않는 키 집합을 처리합니다. 이 최적화는 파티션 표현식이 DISTINCT 컬럼에 대한 결정적 함수일 때 적용되며, 파티션 수와 편중도를 기준으로 한 비용 휴리스틱에 따라 적용 여부가 결정됩니다(force_distinct_partitions_independently 설정으로 전환할 수 있으며, 기본값은 비활성화입니다). 이러한 파티션별 비중첩 속성은 Expression, Filter, ARRAY JOIN 단계를 거쳐 최종 DISTINCT, LIMIT BY, GROUP BY 소비자까지 전파되므로, 이들 단계에서도 머지를 건너뛸 수 있습니다. 새로 추가된 allow_distinct_partitions_independently 설정(기본값은 활성화)으로 제어하며, max_number_of_partitions_for_independent_distinct 설정으로 휴리스틱을 조정할 수 있습니다. #108326 (nihalzp).
  • 이제 ON 절에 비동등 조건자가 함께 포함되어 있어도 동등 키를 기반으로 런타임 필터를 생성합니다. 따라서 동등 조인과 비동등 조인이 혼합된 경우 해시 조인에 유입되는 행 수가 줄어듭니다. LEFT ANTI JOIN은 영향을 받지 않습니다. #108579 (29antonioac).
  • 집계 및 조인 해시 테이블의 소프트웨어 프리페치 임계값을 4 * L2 cache size에서 L2 cache size로 낮추어, 해시 테이블이 L2에 들어가지 않게 되는 시점부터 프리페치가 활성화되도록 했습니다. 이를 통해 보고된 L2 크기가 큰 플랫폼(예: L2가 2 MiB인 aarch64)에서 중간 크기 해시 테이블(~1-8 MiB)을 사용하는 GROUP BY 및 JOIN의 성능 저하 문제를 해결했습니다. #108655 (groeneai).
  • 윈도우 함수 성능을 개선했습니다. SELECT *를 포함하는, 컬럼이 많은 테이블에 대한 윈도우 쿼리가 이제 훨씬 적은 메모리로 더 빠르게 실행됩니다. quantile*, uniq*, groupArray 등의 윈도우 집계가 OVER () 및 OVER (ORDER BY ... RANGE ...)에서 더 빨라졌습니다. cume_dist 함수도 더 빨라졌으며, PARTITION BY 또는 ORDER BY를 사용하는 윈도우는 반복 값이 많은 컬럼에서 성능이 향상되었습니다. #108688 (nihalzp).
  • 집계 함수가 없는 집계 쿼리는 이제 (지원되는 키 타입에 한해) HashMap 대신 HashSet 기반 방식을 사용합니다. 최대 1.8배의 속도 향상이 확인되었습니다. #108862 (nickitat).
  • parallel_hash 조인 알고리즘에서 잠금 경합으로 발생하는 오버헤드를 줄였습니다. #108938 (m-selmi).
  • 새로운 join_algorithm 값인 parallel_full_sorting_merge를 추가했습니다. 해시 호환 동등 조인에서 full sorting merge join을 조인 키의 해시 기준으로 분할하여, 모든 스레드에서 실행되는 독립적인 세그먼트별 merge join으로 처리합니다. merge join의 낮은 스트리밍 방식 메모리 사용량을 유지하면서 병렬 처리가 가능합니다(벤치마크 결과 parallel_hash 대비 약 2.4배 빠르고 메모리 사용량은 약 3.3배 적음). ASOF 조인은 단일 full_sorting_merge로 대체됩니다. 해시 비호환 키 타입(부동 소수점, JSON, Object, Dynamic)은 해시 분산 재작성만 건너뛰며, query_plan_join_shard_by_pk_ranges가 활성화된 경우에는 소스 단계에서 기본 키 범위 기준으로 분할될 수 있습니다. 결과는 정렬되지 않습니다. #109005 (alexey-milovidov).
  • 이제 테이블의 현재 활성 크기와 기록되는 블록 크기의 합이 새로운 materialize_statistics_on_insert_max_table_size 설정 값(기본값 25 GiB) 이하이면, INSERT 시 기본적으로 컬럼 통계(Column Statistics)가 구체화됩니다. 이 검사는 기록되는 블록 단위로 수행되므로, 빈 테이블에 처음 대량 적재하는 경우에도 각 블록마다 통계가 구체화될 수 있습니다. 이를 통해 비용 기반 조인 최적화기는 새로 적재된 차원 테이블에 대해 정확한 추정치를 얻고 비정상적인 조인 순서를 피할 수 있습니다(예: TPC-H Q5와 Q8이 스케일 팩터 40에서 더 이상 시간 초과되지 않습니다). 반면 이미 데이터가 축적된 대규모 팩트 테이블은 기존처럼 머지 중에 통계를 구체화합니다. #109454 (alexey-milovidov).
  • 키 없이 집계하는 경우 집계 함수 uniqCombined를 최적화했습니다. #109794 (CurtizJ).
  • 집계 함수 uniqHLL12와 uniqCombined를 최적화했습니다. #109831 (CurtizJ).
  • parallel_hash 조인 알고리즘에서 조인되지 않은 행의 처리를 병렬화하는 경우를 두 가지 추가했습니다. 잔여 필터가 있는 경우와 조인 키가 작은 경우(단일 수준 해시 맵)입니다. #110008 (m-selmi).
  • 프레디케이트가 윈도우의 PARTITION BY 컬럼만 참조하는 경우, 필터를 윈도 함수 아래로 푸시다운합니다. 윈도우 뒤에 작성된 이러한 프레디케이트(윈도우가 적용된 서브쿼리를 감싸는 외부 WHERE 또는 QUALIFY의 결합 조건)가 이제 스토리지까지 전달되어 프라이머리 키/파티션 프루닝, 스킵 인덱스, 프로젝션을 활용할 수 있습니다. 예를 들어 SELECT ... row_number() OVER (PARTITION BY key ORDER BY ts) AS rn ... QUALIFY rn = 1 AND key = 'x'는 더 이상 테이블 전체를 읽어 윈도우 연산을 수행하지 않습니다. #110114 (groeneai).
  • join_use_nulls = 1인 경우, 외부 조인의 양쪽 컬럼을 모두 참조하는 null 거부 WHERE(예: WHERE l.k = 42 AND r.k = 42)가 있으면 이제 join_use_nulls = 0일 때와 마찬가지로 조인을 INNER(또는 LEFT/RIGHT)로 변환하고 프라이머리 키를 프루닝합니다. 이전에는 이 경우 변환이 생략되어 두 테이블을 모두 전체 스캔했습니다. #110121 (groeneai).
  • 키 없는 집계에서 함수 uniq, uniqExact, uniqHLL12를 최적화했습니다. #110150 (CurtizJ).
  • ON 조건이 상수 false인 JOIN(예: ON 1 = 2, ON NULL, 또는 a.t = 'A' AND a.t = 'B'처럼 false로 평가되는 조건)은 더 이상 결과에 기여하지 않는 쪽을 읽지 않습니다. 새로운 쿼리 계획 최적화를 통해 행을 생성할 수 없는 입력 쪽을 빈 소스로 대체합니다. 이 동작은 query_plan_short_circuit_constant_false_join 설정(기본적으로 활성화)으로 제어합니다. #110234 (groeneai).
  • 단일 수준 집계 해시 테이블의 최종 머지를 병렬화했습니다. 키 공간을 서로 겹치지 않는 해시 파티션으로 분할하고 각 스레드가 이를 독립적으로 머지합니다(enable_parallel_single_level_merge 설정, 기본적으로 활성화). 스레드별 해시 테이블이 2단계 임계값 미만으로 유지되지만 머지가 실행 시간의 대부분을 차지하던 GROUP BY 쿼리의 속도가 향상됩니다. #110395 (nihalzp).
  • 단일 String 집계 키에 더 작은 해시 테이블 표현을 사용하도록 개선하여 문자열 비중이 높은 GROUP BY 워크로드의 성능을 향상했습니다. 새 enable_packed_string_keys_in_aggregation 설정은 기본적으로 활성화되어 있습니다. 이 설정을 비활성화하거나 compatibility를 26.8 미만으로 설정하면 기존 StringHashTable 경로로 되돌아가며, 11바이트보다 길고 카디널리티(cardinality)가 매우 낮은 키에서는 이 경로가 더 빠를 수 있습니다. #110573 (harikrishnan94). #112089 (harikrishnan94).
  • 희소(sparse) 시나리오에서 full sorting merge join 성능을 최대 1.5~3배 향상했습니다. #111200 (vdimir).
  • probe 측과 build 측의 조인 키 타입이 서로 다른 경우(예: 널 허용(Nullable) probe 키와 널 비허용 build 키)에도 join_runtime_filter_from_fixed_hash_table을 활성화합니다. #111244 (m-selmi).
  • 오른쪽 입력에 NULL 조인 키가 있거나 ON 표현식으로 필터링된 행이 있을 때 null 맵을 다시 구성하지 않도록 하여, parallel_hash 알고리즘을 사용하는 RIGHT 및 FULL 조인의 성능을 향상했습니다. #111258 (m-selmi).
  • 병렬 GROUP BY를 위한 새로운 적응형 알고리즘을 도입했습니다(enable_adaptive_aggregator 설정으로 제어하며 기본적으로 활성화됨). 각 스레드는 자체 해시 테이블에 키가 adaptive_aggregator_freeze_threshold개에 도달할 때까지 집계한 후 해당 테이블을 고정합니다. 따라서 자주 등장하는 키는 별도의 조정 없이 캐시에 상주하는 작은 테이블을 계속 갱신하고, 드물게 등장하는 키는 해시에 따라 버킷별 백로그로 라우팅되어 버킷 단위 병렬 머지 과정에서 정확히 한 번만 집계됩니다. #111459 (nihalzp).
  • 값마다 ColumnDynamic을 재구성하지 않도록 하여, 공유 데이터에 저장된 JSON/Object 컬럼 값의 행 단위 해싱 속도를 높였습니다(예: JSON 컬럼에 대한 uniq/uniqExact, 해시 기반 GROUP BY/DISTINCT 키에서 사용). 해시 값은 변경되지 않습니다. #111501 (valerypetrov).
  • ON 절에 여러 개의 OR 분리항이 있는 RIGHT 및 FULL 해시 JOIN과, 잔여(부등) 조건이 있는 RIGHT/FULL JOIN의 성능을 향상했습니다. #111590 (m-selmi).
  • 이제 해시 조인에 자동 디스크 스필 임계값이 구성된 경우(26.5부터 기본값)에도 JOIN을 통한 순서대로 읽기(read in order)가 동작합니다. 이 최적화가 적용되면 왼쪽 입력의 순서를 유지하기 위해 조인이 메모리에 머무릅니다. 이러한 조인을 read-in-order에 사용하지 않고 자유롭게 스필할 수 있던 이전 동작으로 되돌리려면 query_plan_read_in_order_through_spilling_join = 0을 설정하십시오. 아울러 순서대로 읽는 LEFT JOIN에 대한 ORDER BY ... LIMIT가 더 이상 읽을 예정인 행 수를 전체 테이블 크기로 보고하지 않으므로, 조기에 종료되는 읽기가 read_overflow_mode = 'throw' 설정에서 max_rows_to_read 제한에 걸리지 않습니다. #111973 (alexey-milovidov).
  • 머지 중 TTL ... GROUP BY 집계에 대해 연속 키 최적화를 다시 활성화했습니다. 기존에는 aggregator 생성 시 min_hit_rate_to_use_consecutive_keys_optimization([0, 1] 범위의 적중률, 기본값 0.5)가 들어가야 할 자리에 min_chunk_bytes_for_parallel_parsing(바이트 임계값, 기본값 10 MiB)이 전달되어, 해당 경로에서 이 최적화가 항상 비활성화되어 있었습니다. 결과에는 영향이 없습니다. #112314 (groeneai).
  • 쿼리 계획(query plan)을 직렬화할 때 ARRAY JOIN의 지연 컬럼 복제가 더 이상 누락되지 않습니다. 이전에는 serialize_query_plan = 1이면 원격 계획 조각을 실행하는 노드가 enable_lazy_columns_replication을 무시하고 복제된 모든 사본을 항상 구체화했습니다. 이 설정은 기본적으로 활성화되어 있는데도 그러했습니다. #112330 (groeneai).
  • WHERE 등식 조건의 피연산자 타입이 서로 다르더라도 Int32와 Nullable(Int32)처럼 공통 상위 타입(common supertype)이 있으면, 이제 해당 조건이 JOIN 조건으로 병합됩니다. 이에 따라 CROSS 조인을 INNER 조인으로 변환할 수 있습니다. #112630 (m-selmi).
  • 요소가 공유 데이터에 JSON 값을 담고 있는 Array를 복제할 때 재할당이 이차적으로 발생하던 문제를 수정했습니다. 집계 함수에 상수 Array(JSON)을 전달하는 경우가 대표적인 예입니다. 이러한 쿼리에서는 복사되는 바이트 수가 행 수의 제곱에 비례하여 증가했습니다. #112897 (groeneai).
  • MergeTree 기본 키 또는 파티션 키에 대한 범위 조건자의 경계 값을 단일 행 상수 측과의 JOIN ON 절로 전달하는 경우(예: SELECT count() FROM t JOIN bounds ON t.d >= bounds.lo AND t.d <= bounds.hi) 파트 및 그래뉼 프루닝이 다시 적용됩니다. 이러한 쿼리는 25.2부터 모든 파트를 읽었으며, 프루닝을 되살리는 데 쓰이던 query_plan_use_logical_join_step 설정마저 26.5에서 더 이상 사용되지 않게 되어 프루닝을 복구할 방법이 없었습니다. #112957 (groeneai).
  • 구조가 서로 다른 여러 테이블을 대상으로 하는 Merge 테이블과 JOIN할 때 쿼리 계획 수립에 삼차 복잡도가 발생하던 문제를 수정했습니다. 이전에는 이러한 쿼리가 max_execution_time이나 KILL QUERY에도 응답하지 않고 쿼리 계획 수립에만 수 분을 소요할 수 있었습니다. #113140 (alexey-milovidov).
  • GROUP BY 키가 없는 집계가 실행될 때마다 정작 사용되지도 않는 해시 테이블 크기 캐시 키를 계산하려고, 상수 폴딩된 리터럴의 전체 내용을 포함한 입력 계획 하위 트리 전체를 직렬화하던 성능 회귀를 수정했습니다. SELECT quantileMerge(arrayJoin(arrayMap(x -> state, range(5000000))))와 같은 쿼리는 실행할 때마다 쿼리 계획 최적화에 약 63ms가 걸렸으나, 이제는 0.15ms면 충분합니다. #113333 (groeneai).
  • PromQL 집계 연산자 topk, bottomk, limitk를 평가할 때, 모든 시리즈를 단일 행으로 모아 O(time_steps * series^2)의 중간 메모리를 사용하는 대신 선택 상태가 O(time_steps * k)인 스트리밍 계획을 사용합니다. 이전에 MEMORY_LIMIT_EXCEEDED로 실패하던 고카디널리티(high-cardinality) 메트릭 쿼리가 이제 제한된 메모리 안에서 실행되며, 평가도 단일 스레드가 아닌 병렬로 수행됩니다. #113656 (nikitamikhaylov).
  • timeSeries*ToGrid 집계 함수 내부의 버킷별 해시 맵을 정렬된 평면 샘플 배열로 대체했습니다. 이에 따라 입력이 순서대로 들어오는 경우(대부분이 이에 해당) 샘플 수집이 O(1) 추가 연산으로 처리되며, 최종 처리 단계의 버킷별 복사 및 정렬 과정이 사라졌습니다. #113681 (nikitamikhaylov).
  • 여러 계획 단계가 공유하는 PromQL 하위 표현식(topk/bottomk/limitk 피연산자, or의 좌변)을 두 번이 아닌 한 번만 평가합니다. 이를 위해 PromQL에서 생성되는 SQL이 이제 공유 서브쿼리를 구체화합니다. 그 결과 Samples table을 중복으로 스캔하지 않게 되어, rate에 대한 topk가 콜드 상태에서 약 2배 빨라지고 kubernetes-mixin 규칙 쿼리의 성능은 10–29% 향상됩니다. #113772 (nikitamikhaylov).
  • 이제 ORDER BY <column> LIMIT n(TopK) 최적화를 사용하는 쿼리에서 쿼리 조건 캐시가 기본적으로 활성화됩니다. 사용하지 않으려면 use_query_condition_cache_for_top_k = 0으로 설정하십시오. #111492 #114539 (alexey-milovidov).
  • 병합 전에 스레드별 집계 상태를 단일 수준에서 2단계 수준으로 변환하는 작업을 병렬화합니다. 이를 통해 코어 수가 매우 많은 머신에서 무거운 집계 상태(예: COUNT(DISTINCT ...), ClickBench Q10/Q11)를 사용하는 짧은 GROUP BY 쿼리가 2~3배 느려지던 성능 저하 문제가 해결됩니다. 이 문제는 26.7 개발 빌드에서 집계 메모리 계산을 정확하게 개선하면서 발생했습니다. #114691 (alexey-milovidov).
  • 파티션된 MergeTree 테이블에서 윈도우 함수의 속도를 향상합니다. 각 파티션을 자체 스트림으로 읽고 파티션별로 윈도우를 평가하므로, 일반적으로 윈도우 정렬 전에 모든 행을 스레드 간에 재분배하는 해시 분산 단계를 건너뜁니다. 이 최적화는 테이블의 파티션 표현식이 윈도우 PARTITION BY 컬럼의 결정론적 함수일 때 적용되며, 파티션별 GROUP BY / DISTINCT와 동일한 비용 휴리스틱(max_threads 대비 충분한 파티션 수, 지배적인 파티션 없음)에 따라 적용 여부가 결정됩니다. 새 설정 allow_window_partitions_independently(기본적으로 활성화됨), force_window_partitions_independently, max_number_of_partitions_for_independent_window로 제어합니다. #114783 (nihalzp).
  • timeSeries*ToGrid 집계 함수의 속도를 향상합니다. 이제 샘플별 버킷 계산에서 Int128 나눗셈을 사용하지 않으며, 같은 버킷에 속한 연속 샘플은 해시 맵 조회를 건너뜁니다. #114889 (nikitamikhaylov).
  • timeSeries*ToGrid 집계 함수의 샘플을 같은 그리드 버킷에 속하는 연속 샘플 단위로 묶어 처리하여, 정렬된 시계열 데이터에서 timeSeriesRateToGrid 및 관련 함수의 샘플 수집 단계 속도를 1.2~2배 향상합니다. #115041 (nikitamikhaylov).
  • GROUP BY 키가 없는 집계는 더 이상 단일 행 출력을 max_threads개의 스트림으로 분산하지 않습니다. 따라서 이러한 집계 뒤에 실행 계획이 이어지는 쿼리는 병렬성을 잃지 않으면서도 훨씬 작은 파이프라인(생성, 스케줄링, 프로파일링할 프로세서 수 감소)으로 실행됩니다. #115170 (nikitamikhaylov).
  • PromQL 인스턴트 쿼리의 평가 속도가 향상되었습니다. timeSeries*ToGrid 집계 함수는 단일 지점 그리드에 벡터화된 샘플 분류 경로를 사용하며, timeSeriesIdToGroup은 결과 컬럼을 직접 채웁니다. #115267 (nikitamikhaylov).
  • ON 절에 OR로 연결된 여러 등식이 있는 JOIN은 더 이상 쿼리에서 선택하지 않는 오른쪽 키 컬럼을 구체화하지 않습니다. #115465 (nickitat).
  • 오른쪽에서 동일한 조인 키가 여러 번 반복될 때 ANY, SEMI, ANTI 조인의 해시 테이블 빌드 속도를 향상합니다. 이제 조인 시 오른쪽의 행마다 메모리에서 join_any_take_last_row 설정을 다시 읽지 않습니다. #115820 (nickitat).
  • String, FixedString, LowCardinality 키에 대해 집계 함수 없이 수행하는 GROUP BY의 속도를 향상합니다. 이제 사용되지 않는 플레이스홀더를 모든 행마다 해시 테이블에 다시 쓰지 않고, 새 키를 추가하는 행에서만 씁니다. #115834 (nickitat).
  • 상수 폴딩된 대용량 리터럴(literal)에 대한 키 기반 집계에서 메모리 사용량과 쿼리 계획 최적화 시간을 줄였습니다. 집계 해시 테이블 통계 캐시 키를 메모리에 먼저 누적하지 않고 직렬화와 동시에 해시하도록 변경했습니다. 이에 따라 대용량 리터럴이 포함된 계획이 최적화 중에 해당 리터럴의 사본을 더 이상 보유하지 않습니다. 80 MB 리터럴 기준으로 최대 메모리(Peak memory) 사용량은 약 250 MB 줄고 최적화 시간은 약 2.5배 단축됩니다. 계산되는 키 값은 이전과 동일합니다. #115847 (groeneai).
  • 집계 중에 크기가 제한된 힙을 유지하면서 결과에 포함될 수 없는 그룹을 프루닝하도록 하여 GROUP BY ... ORDER BY ... LIMIT 및 GROUP BY ... LIMIT 쿼리를 최적화했습니다. 이를 통해 고카디널리티(high-cardinality) 그룹화에서 메모리 사용량과 실행 시간이 크게 줄어듭니다. 이 기능은 enable_group_by_top_k_optimization 설정으로 제어합니다. Dmitriy Terenichev의 초기 구현을 기반으로 합니다. #96630 (thevar1able).

쿼리 최적화 및 실행

  • 병렬 레플리카(Parallel Replicas)를 사용한 순차 읽기(in-order reading)에서도 이제 로컬 읽기와 동일하게 테이블을 max_threads개의 파트로 분할하는 로직을 사용하므로 병렬성이 향상되었습니다. #101434 (nickitat).
  • Parquet 리더에 row group 및 페이지 수준의 GeoParquet 공간 프루닝을 추가했습니다. row group 프루닝은 경계 상자(bounding box)가 쿼리 지오메트리와 겹치지 않는 row group 전체를 건너뜁니다. 페이지 수준 프루닝은 covering.bbox 컬럼 인덱스를 사용하여 row group 내에서 관련 없는 페이지를 건너뜁니다. 또한 IFunctionBase::isSpatialPredicate()를 통해 공간 프레디케이트 푸시다운을 일반화하고, Parquet 행을 읽는 동안 공간 프레디케이트를 평가하는 GeoFilter를 추가했습니다. #104435 (bacek).
  • use_constant_folding_in_index_analysis 설정을 추가했습니다(기본값은 비활성화). 이 설정을 활성화하면 MergeTree 기본 키(primary key), MinMax 및 스킵 인덱스 분석 시 파티션 수준의 상수를 파트별로 필터 프레디케이트에 폴딩하므로, 분기가 파티션 값에 따라 달라지는 필터의 프루닝 효율이 개선됩니다. 예를 들어 PARTITION BY a와 함께 사용하는 (a = 1 AND b >= 1) OR (a = 2 AND b > 10) 같은 필터가 이에 해당합니다. #104582 (Michicosun).
  • vector_search_with_rescoring을 사용하는 벡터 검색 쿼리에서, 쿼리 파이프라인의 정확한 거리 계산 이전에 정확한 행 위치 지정을 적용합니다. #105591 (skuznetsov).
  • 데이터 크기를 줄이는 함수(length, lengthUTF8, empty, notEmpty)를 Sorting 및 Filter 단계 아래로 푸시다운하는 쿼리 계획 최적화를 추가했습니다. 이 최적화는 폭이 넓은 String / FixedString 인수를 고정 크기의 결과로 대체하므로, 해당 값이 정렬 과정에서 버퍼링되거나 필터 과정에서 복사되지 않습니다. 새 설정 query_plan_push_down_volume_reducing_functions로 제어하며, 기본적으로 활성화되어 있습니다. #106199 (fastio).
  • 각 캐시 파일의 크기를 파일 이름(<offset>_<size>)에 인코딩하여 파일마다 stat을 호출하지 않도록 함으로써, 시작 시 파일시스템 캐시 로딩 속도를 높였습니다. 이전 버전에서 작성된 캐시 파일도 계속 로딩할 수 있습니다. #107415 (alexey-milovidov).
  • 기본 키 필터와 함께 사용하는 텍스트 검색 쿼리의 성능을 개선했습니다. #108114 (CurtizJ).
  • 상수 폴리곤을 사용하는 pointInPolygon 함수의 성능을 개선했습니다. 이제 전처리된 폴리곤 캐시가 원시 상수 인수를 키로 사용하므로, 상수 폴리곤을 입력 블록마다 다시 파싱하지 않고 (캐시 미스 시) 한 번만 파싱합니다. #108184 (groeneai).
  • 해당 기능이 비활성화된 경우(기본값인 predicate_statistics_sample_rate = 0) MergeTree 읽기 경로에서 system.predicate_statistics_log 선택도 카운터를 유지하지 않도록 했습니다. 이로써 모든 읽기에서 그래뉼별 원자적 업데이트와 O(rows) 필터 popcount가 제거되어, 특히 aarch64에서 두드러졌던 성능 저하가 해소되었습니다. #108190 (groeneai).
  • 일반 MergeTree 머지에서 배치 정렬 큐를 선택적으로 사용할 수 있도록 merge_use_batch_sorting_queueMergeTree 설정을 추가했습니다. 정렬 머지 비용이 큰 머지 워크로드에서 CPU 시간과 실제 소요 시간을 줄여 줍니다. #108468 (rorylshanks).
  • 동일한 WITH 별칭을 참조하거나 동일한 하위 표현식이 여러 번 반복되는 표현식(예: 깊게 중첩된 if/multiIf 체인)에 대해, actions DAG를 구성할 때 공유 하위 표현식을 다시 빌드하지 않도록 하여 analyzer의 쿼리 계획 수립 속도를 높였습니다. #108523 (novikd).
  • 비교 연산으로 이루어진 AND 체인이 많거나 매우 큰 쿼리의 쿼리 분석 속도를 개선했습니다. 이제 optimize_and_compare_chain 최적화는 쿼리 트리의 상당 부분을 해시하는 대신 작업 예산(새로운 설정 optimize_and_compare_chain_max_hash_work)으로 제한되며, lambda 해석 시 재귀 방지를 위해 lambda 본문 해시를 다시 계산하지 않습니다. #108757 (alexey-milovidov).
  • 필터 전용 후처리기(if(..., '', token))는 이제 원시 토큰으로 그래뉼을 빌드하고 빌드 시점에 빈 값을 제거합니다. 따라서 일반 경로에서 발생하던 항목별 머티리얼라이즈와 ActionsDAG 실행이 필요하지 않습니다. #109049 (ahmadov).
  • 분산 쿼리 계획의 ShuffleSendStep에서 단일 스레드 병목을 제거했습니다. 이제 각 업스트림 스트림은 전체 프래그먼트를 하나의 ScatterByPartitionTransform으로 모으는 대신, 대상 버킷별로 행을 독립적으로 분배합니다. #109206 (davenger).
  • 컬럼 수가 많은 쿼리에서 표현식 평가의 CPU 오버헤드를 줄였습니다(예: stride가 작은 QBit 컬럼에 대한 벡터 검색에서 각 벡터가 수백 개의 비트 플레인 서브컬럼으로 확장되어 모두 하나의 *DistanceTransposed 호출에 전달되는 경우). #109380 (alexey-milovidov).
  • 프레디케이트가 LIMIT BY 키 컬럼만 참조하고, 해당 절이 비어 있지 않은 그룹마다 최소 1개의 행을 유지하는 경우(n >= 1이고 OFFSET 0인 LIMIT n BY) 필터를 LIMIT BY 아래로 푸시합니다. 이에 따라 LIMIT BY 서브쿼리를 감싸는 외부 WHERE로 작성된 프레디케이트가 전체 테이블을 읽고 그룹별 top-N을 먼저 적용하는 대신 스토리지까지 전달되어 프라이머리 키 프루닝, 스킵 인덱스, 프로젝션을 활용할 수 있습니다. OFFSET, LIMIT 0 BY 또는 음수 LIMIT BY 형태의 예외 동작은 변경되지 않습니다. #110116 (groeneai).
  • 프라이머리 키 인덱스 분석에서 하이퍼렉탱글 검사마다 발생하던 힙 할당을 제거하여, 쿼리 형태에 따라 마크 필터링 속도가 5~26% 향상되었습니다. #110153 (raimannma).
  • Parquet 필터 푸시다운(행 그룹 프루닝 및 컬럼 인덱스)이 이제 DateTime64 변형 간, Decimal 변형 간, 그리고 Float32/Float64 간 변환을 지원합니다. #110457 (al13n321).
  • sparseGrams 토크나이저를 사용하는 텍스트 및 블룸 필터 기반 스킵 인덱스의 빌드를 최적화했습니다. #110541 (UnamedRus).
  • PREWHERE 조건 순서를 정할 때 I/O 비용과 선택도를 함께 고려합니다. 이를 통해 https://github.com/ClickHouse/ClickHouse/pull/101275 이후 일부 경우에 발생하던 PREWHERE 실행 성능 저하를 수정했습니다. https://github.com/ClickHouse/ClickHouse/issues/110462 의 일부입니다. #110695 (Avogar).
  • 후처리기 IN/NOT IN 필터에 정의된 토큰의 해시 연산을 줄였습니다. #111690 (ahmadov).
  • enable_lazy_columns_replication이 활성화된 경우, 상수가 아닌 패턴을 사용하는 mapContainsKeyLike, mapContainsValueLike, mapExtractKeyLike, mapExtractValueLike 함수의 메모리 사용량과 실행 시간이 줄었습니다. 이제 캡처 시점에 맵 항목마다 패턴을 미리 복사하지 않고 내부 lambda 실행 시점까지 복사를 미루며, 복사본도 더 빨리 해제됩니다. 따라서 사용량이 최대인 시점에 존재하는 확장된 패턴 복사본이 하나 줄어듭니다. #111749 (diegomestre2).
  • 디스크 저장 관련 기능 2가지를 기본으로 활성화하고 베타로 승격했습니다. 1) packed_skip_index_max_bytes = '1M': 최대 1 MiB 크기의 스킵 인덱스 서브스트림을 이제 파트마다 하나의 skp_idx.packed 아카이브에 기록하므로, 객체 스토리지의 객체 수와 쓰기 요청이 줄어듭니다. 호환성: 새로 기록되는 파트에만 적용되며, 이 파트는 이전 버전에서도 완전히 읽을 수 있습니다. 26.6 이전 버전은 패킹된 인덱스를 프루닝에 사용하지 않을 뿐입니다(머티리얼라이즈되지 않은 것으로 간주됨). 기존처럼 파일별로 분리된 레이아웃을 유지하려면 packed_skip_index_max_bytes = 0으로 설정하십시오. 2) compute_exact_num_defaults_for_sparse_columns 및 optimize_trivial_count_with_sparsity_filter: 컬럼별 정확한 num_defaults 카운터를 저장해 두고, 프레디케이트가 행을 기본값과 비기본값으로 나누는 경우 이를 활용하여 데이터 스캔 없이 SELECT count() FROM t WHERE <pred>의 결과를 반환합니다. 호환성: serialization.json의 exact_num_defaults 플래그는 이전 버전에서 무시되므로 다운그레이드 후에도 파트를 완전히 읽을 수 있습니다. count 재작성은 정확한 카운터가 있는 파트에만 적용되므로, 여러 유형의 파트가 섞인 테이블에서도 결과가 정확하게 유지됩니다. #111816 (Algunenano).
  • 추이적 조건(transitive-conditions) 최적화는 이제 전체 필터를 적용할 수 없는 경우 추가 필터를 인덱스 분석에만 사용합니다. 자세한 내용은 optimize_and_compare_chain 설정을 참조하십시오. #112076 (yariks5s).
  • 실험적 TimeSeries 엔진의 Prometheus 쿼리 API(/api/v1/query, /api/v1/query_range)가 이제 단일 스레드가 아닌 병렬로 쿼리를 실행합니다. #112108 (nikitamikhaylov).
  • 상수 벡터에 대한 randomHadamardTransform을 이제 행마다 평가하지 않고 한 번만 평가합니다. 따라서 randomHadamardTransform으로 쿼리 벡터를 회전시킨 후 QBit 컬럼과 비교하는 벡터 검색 쿼리의 속도가 향상됩니다. #112921 (alexey-milovidov).
  • 프라이머리 키 컬럼에 대해 IN (subquery)로 필터링하는 뮤테이션에서, 같은 뮤테이션의 파트 작업 간 Set 공유 기능을 복원했습니다. enable_sharing_sets_for_mutations는 기본으로 활성화되어 있지만, 프라이머리 키 분석용으로 생성된 Set이 공유 캐시에서 제외되면서 파트가 N개인 테이블에서 동일한 Set을 N번 구체화하는 문제가 있었습니다. #112941 (groeneai).
  • 분산 쿼리 계획(make_distributed_plan)에서 ORDER BY ... LIMIT k가 이제 각 레플리카에서 지연 머티리얼라이즈(lazy materialization)를 사용합니다. 크기가 큰 컬럼은 모든 후보 행이 아니라 해당 레플리카의 로컬 상위 k개 행에 대해서만 읽습니다. #113111 (shankar-iyer).
  • uniq_v2 컬럼 통계(column statistics)를 사용할 때 쿼리 계획 수립 속도가 향상되었습니다. 추정 고유값(distinct values) 개수를 이제 캐시하므로, 쿼리 계획 수립 시 쿼리당 여러 번 발생하는 요청마다 매번 다시 계산하지 않습니다. #113357 (groeneai).
  • 이제 Parquet 및 ORC 파일의 Tuple 서브컬럼에서도 필터 푸시다운이 동작합니다. file(), s3(), url()에 대해 WHERE tup.1 = 555555와 같은 프레디케이트를 사용하면, 이제 파일 전체를 읽지 않고 튜플 요소 자체의 통계를 활용하여 행 그룹과 행 인덱스 스트라이드를 프루닝합니다. #113383 (groeneai).
  • TimeSeries 엔진의 PromQL 쿼리 성능이 향상되었습니다. 내부 셀렉터 SQL이 이제 샘플 테이블의 프라이머리 키 컬럼을 (불필요한 캐스트 없이) 직접 읽고, series-id Set보다 타임스탬프 범위를 먼저 검사합니다. 그 결과 셀렉터 비중이 높은 콜드 쿼리가 30~44% 빨라졌습니다. #113768 (nikitamikhaylov).
  • 한 메트릭의 모든 시리즈와 일치하는 PromQL 셀렉터는 이제 인덱스 분석 시 큰 id IN <set> 조건 대신 id에 대한 연속적인 프라이머리 키 범위로 TimeSeries 테이블의 samples 테이블을 필터링합니다. 이는 id 레이아웃이 표준 id 생성기를 사용하는 2개 요소의 튜플일 때 적용됩니다. 이를 통해 셀렉터를 많이 사용하는 PromQL 쿼리에서 가장 큰 비중을 차지하던 단일 스레드 인덱스 분석 비용이 제거됩니다. 620억 개의 샘플이 있는 테이블에서 대시보드 및 규칙 쿼리 유형의 콜드 지연 시간이 최대 45% 감소했으며, 전체 테스트 모음의 콜드 기하 평균은 11% 감소했습니다. #114131 (nikitamikhaylov).
  • Prometheus HTTP API 엔드포인트 /api/v1/query 및 /api/v1/query_range는 이제 prometheusQuery 및 prometheusQueryRange 테이블 함수와 마찬가지로, 여러 플랜 단계에서 공유하는 PromQL 서브쿼리를 한 번만 평가합니다. 이전에는 enable_analyzer = 0으로 요청하거나 프로필에 이 설정이 지정된 사용자가 요청하면, 공유 서브쿼리를 참조하는 단계마다 서브쿼리를 다시 스캔했습니다. #114261 (groeneai).
  • 26.7에서 발생한 회귀 문제를 수정했습니다. DateTime64 컬럼에 toUnixTimestamp(또는 다른 정수 변환)를 적용한 값으로 정렬된 MergeTree 테이블에서, 해당 컬럼에 대한 일반 범위 필터가 프라이머리 키를 사용하지 않아 일치하는 파트의 모든 그래뉼을 읽던 문제입니다. 또한 원본 DateTime64 컬럼으로 정렬된 테이블에서 toInt64(ts) >= c와 같은 필터도 이제 프라이머리 키를 사용합니다. #114413 (alexey-milovidov).
  • 클러스터링된(예: 프라이머리 키로 정렬된) 컬럼에 대해 IN을 실행할 때, 값이 같은 연속된 행에는 이전 행의 결과를 재사용하여 실행 속도를 높였습니다. #114853 (nikitamikhaylov).
  • h3kRing, h3ToChildren, h3PolygonToCells, h3PolygonToCellsWithContainment 함수가 많은 행에 대해 결과를 생성할 때 이차 시간이 소요되던 문제를 수정했습니다. CI 스트레스 테스트에서 196,000개 행에 대한 쿼리가 메모리 복사에만 838초를 소비했으나, 이제는 약 5초면 완료됩니다. #115773 (groeneai).
  • 역방향 딕셔너리 조회를 최적화했습니다. WHERE dictGet(dict, attr, key_expr) = value와 같은 상수 동등 조건자는 이제 IN (SELECT ... FROM dictionary(...)) 서브쿼리로 재작성되지 않고 키 필터(key_expr = const, key_expr IN [...] 또는 WHERE 0)로 직접 상수 폴딩되며, dictGetKeys의 상수 경로는 이제 병렬로 실행됩니다. #91164 (nihalzp).
  • 일반 제외 검색 알고리즘이 각 데이터 파트의 프라이머리 키 인덱스를 분석하는 데 사용하는 단계 수를 제한하는 새 설정 merge_tree_generic_exclusion_search_max_steps를 추가했습니다. 할당량은 남은 키 범위 중 가장 큰 범위부터 사용되므로 할당량이 작더라도 데이터 대부분을 제외할 수 있습니다. 완전히 분석되지 않은 범위는 통째로 읽으므로 쿼리 결과의 정확성은 유지되지만 더 많은 그래뉼을 읽을 수 있습니다. 이 제한은 느슨하게 적용되어, 최대 merge_tree_coarse_index_granularity 단계에 파트가 이미 나뉘어 있는 범위(예: 쿼리 조건 캐시에 의해 나뉜 범위)마다 1단계를 더한 만큼 초과될 수 있습니다. 기본값 0은 단계 수에 제한이 없음을 의미합니다. #92779 (EmeraldShift).
  • 분산 테이블(Distributed Table) 위에 정의된 VIEW에 대해 ORDER BY와 LIMIT를 사용하는 쿼리가 이제 정렬된 스트림 머지 최적화를 사용합니다. 외부 ORDER BY/LIMIT가 단순 뷰의 내부 쿼리로 푸시되므로, 코디네이터에서 전체 정렬을 수행하지 않고 각 샤드가 로컬에서 데이터를 정렬한 뒤 코디네이터가 미리 정렬된 스트림을 머지합니다. #94102 (matanper).

저장소, I/O 및 데이터 레이크 성능

  • 프라이머리 키 컬럼이 파티션 키의 입력 컬럼이기도 한 경우, MergeTree 테이블의 프라이머리 키 분석 시 파티션 minmax 인덱스 범위를 활용하여 더 많은 그래뉼을 프루닝합니다. 예를 들어 ORDER BY (id, event_time) 및 PARTITION BY toYYYYMM(event_time)이 지정된 MergeTree 테이블에서 ClickHouse는 프라이머리 키 인덱스 분석 시 event_time에 대한 파티션 minmax 인덱스를 활용하여 그래뉼 프루닝 여부를 더 정확하게 판단합니다. 이 동작은 새로운 설정 use_partition_minmax_for_primary_key_pruning(기본적으로 활성화됨)으로 제어됩니다. #103480 (UnamedRus).
  • 정렬된 스트림에서 동일한 키 값이 이어지는 구간을 스캔하는 연산자의 속도를 개선했습니다. 대상 연산자는 정렬 순서 기반 DISTINCT, 정렬 순서 기반 LIMIT BY, 정렬 순서 기반 음수 LIMIT BY, full_sorting_merge 및 partial_merge 조인입니다. #106502 (nihalzp).
  • 이제 Parquet v3 리더는 컬럼 청크 전체가 딕셔너리 인코딩된 경우, 등호 및 IN 조건에 대해 min/max 통계와 블룸 필터뿐 아니라 딕셔너리 페이지도 활용하여 행 그룹 전체를 건너뛸 수 있습니다. 이 동작은 새로운 설정 input_format_parquet_dictionary_filter_push_down으로 제어됩니다. #106952 (alexey-milovidov).
  • gzip/zlib/deflate 압축 및 압축 해제에 libdeflate를 사용하도록 변경하여 .gz/HTTP/url/s3 데이터와 Parquet GZIP 코덱의 처리 속도를 개선했습니다(압축은 약 1.15배 빨라지고 압축률도 향상되었으며, 압축 해제는 약 1.4–1.5배 빨라졌습니다). #108074 (alexey-milovidov).
  • 기본 공백 문자를 제거하는 trimLeft/trimRight/trimBoth 함수(및 별칭 ltrim/rtrim/trim)의 속도를 개선했습니다. 공백 제거가 필요 없는 연속된 행은 한 번에 일괄 복사하고, 행별 공백 스캔은 실제로 앞뒤에 공백이 있는 행에 대해서만 수행합니다. #108177 (groeneai).
  • 현재 manifest를 파싱하는 동안 다음 manifest 파일을 미리 가져와 I/O와 CPU 작업이 동시에 진행되도록 하여 Iceberg 테이블 읽기 속도를 개선했습니다. #108543 (asya-ch).
  • 이제 재채점(rescoring)을 사용하는 벡터 검색 쿼리는 동일한 MergeTree 그래뉼의 인접 행까지 무차별 대입 방식으로 재채점하지 않고, 벡터 인덱스 후보 행에 대해서만 정확한 거리를 계산합니다. #108846 (skuznetsov).
  • 코어 수가 많은 서버에서 좁은 컬럼을 대상으로 하는 일반적인 로컬 비정렬 MergeTree 스캔 시 과도한 읽기 스트림과 파이프라인 오버헤드를 줄이기 위해 merge_tree_min_bytes_per_read_stream 설정을 추가했습니다. #109035 (jiebinn).
  • 공유 데이터에 희소 경로가 많은 JSON 컬럼의 직렬화 및 머지 속도를 개선했습니다. 공유 데이터를 경로별 컬럼으로 평탄화할 때 flattenAndBucketSharedDataPaths는 더 이상 행마다 누적된 경로 컬럼 전체를 스캔하지 않으며, 기본값을 한 셀씩 삽입하지도 않습니다. 모든 경로에 대한 행별 스캔을 제거하고, 비어 있는 부분은 일괄로 채웁니다. #109341 (groeneai).
  • 이제 양쪽 피어가 모두 protocol revision 54489 이상이면, 네이티브 프로토콜은 String 컬럼을 값별 varint 길이 접두사 대신 누적 바이트 오프셋으로 이루어진 별도 스트림(Array가 오프셋에 사용하는 것과 동일한 레이아웃)과 그 뒤에 이어지는 연결된 데이터로 전송합니다. 따라서 클라이언트는 버퍼를 정확한 크기로 미리 할당하고 한 번의 대량 복사로 String 컬럼을 읽을 수 있으며, 값별 레이아웃보다 약 4배 빠릅니다. 레이아웃은 protocol revision을 통해 협상되므로 기존 클라이언트와 서버에는 영향이 없습니다. 동일한 레이아웃은 새로운 설정 output_format_native_write_string_with_size_stream / input_format_native_read_string_with_size_stream을 통해 Native 및 Buffers 포맷에서도 사용할 수 있습니다(포맷의 이식성을 유지하기 위해 기본적으로 비활성화되어 있습니다). #110320 (vahid-sohrabloo).
  • 작은 LIMIT과 함께 기본 키 순서(정렬 키의 접두사로 ORDER BY)대로 읽는 FINAL 쿼리는 더 이상 split_intersecting_parts_ranges_into_layers_final을 사용하지 않습니다. #110431 (KochetovNicolai).
  • Iceberg 테이블을 포함하여 객체 스토리지에서 Parquet 파일을 읽을 때 지연 머티리얼라이즈(lazy materialization, late materialization)를 지원합니다. ORDER BY ... LIMIT n 쿼리에서 정렬 및 필터링에 필요하지 않은 컬럼은 LIMIT 적용 후 남은 n개의 행에 대해서만 읽습니다. S3에 있는 200MB Parquet 파일에서 SELECT k, s ... ORDER BY k DESC LIMIT 10은 171MB 대신 3.3MB만 읽습니다(IO 51배 감소, 8배 향상). 새로운 설정 query_plan_optimize_lazy_materialization_for_object_storage로 제어하며(기본적으로 활성화됨), query_plan_optimize_lazy_materialization도 활성화되어 있어야 합니다. #110970 (alexey-milovidov).
  • 삭제 파일이 많은 Iceberg 테이블에 대한 쿼리가 이제 더 빠르게 시작됩니다. ClickHouse는 삭제 매니페스트 파일을 하나씩 처리하지 않고 동시에 읽고 디코딩하므로 저장소 읽기가 병렬로 수행됩니다. 새로운 설정 iceberg_delete_manifest_decode_concurrency(기본값 4)로 동시에 디코딩할 파일 수를 제어할 수 있습니다. #112679 (asya-ch).
  • 행 그룹 및 페이지 프루닝이 가능하도록 UInt128/UInt256/Int128/Int256을 DECIMAL로 Parquet 직렬화하는 선택적 기능을 추가했습니다. #113347 (bobrik).
  • 리더 체인의 단계가 기본 키 또는 스킵 인덱스로 필터링된 범위처럼 조각난 마크 범위를 읽을 때 원격 디스크에서 읽기 요청이 여러 번 중복 발생하던 문제를 수정했습니다. #113584 (CurtizJ).
  • 정렬 키가 모두 상수인 MergeTree 파트를 쓸 때 불필요한 정렬 여부 검사를 건너뜁니다. #113899 (perfloop-agent).
  • ORDER BY ... LIMIT n 쿼리에 대한 지연 머티리얼라이즈가 이제 file 테이블 함수와 File 테이블 엔진으로 읽는 로컬 Parquet 파일에도 적용됩니다. 정렬 및 필터링에 필요하지 않은 컬럼은 LIMIT 적용 후 남은 n개의 행에 대해서만 읽습니다. 두 번의 읽기 사이에 파일이 수정되면, 남은 파일에 대한 두 번째 읽기는 새로운 FILE_CHANGED_DURING_READ 오류를 반환하며 안전하게 실패합니다. 새로운 설정 query_plan_optimize_lazy_materialization_for_file로 제어합니다(기본적으로 활성화됨). 또한 요청된 서브컬럼(예: JSON 컬럼의 서브컬럼)이 지연 읽기 대상일 때 객체 스토리지에 대한 지연 머티리얼라이즈가 Not found column or subcolumn ... in block 오류로 실패하던 문제도 수정했습니다. #114262 (alexey-milovidov).
  • 파티션된 MergeTree 테이블에서 IN (subquery)의 집합 생성 속도를 개선했습니다. 각 파티션의 행을 단일 스트림(single stream) 안에 유지하고 스트림별로 독립적으로 중복을 제거하므로, 이전에는 모든 행을 순차적으로 해싱하던 단일 집합 채우기 변환이 이제 고유한 행만 처리합니다. 이 최적화는 파티션 표현식이 서브쿼리 출력 컬럼의 결정론적 함수일 때 적용됩니다. 가장 큰 파티션의 행 수가 평균 파티션 행 수의 2배를 초과하면 이 최적화는 적용되지 않으며, 새로운 설정 force_creating_set_partitions_independently(기본값: 비활성화)를 사용하면 이 검사를 건너뛸 수 있습니다. 이 동작은 새로운 설정 allow_creating_set_partitions_independently(기본값: 활성화)로 제어합니다. #114645 (nihalzp).
  • 불필요한 백그라운드 작업을 방지하기 위해 TTL이 없는 로테이션된 비복제 MergeTree 시스템 로그 테이블을 table_readonly로 표시합니다. 이제 table_readonlyMergeTree 설정은 기존에 거부하던 삽입, 뮤테이션, OPTIMIZE 외에도 일반 MergeTree 테이블의 모든 백그라운드 작업(일반 머지, TTL(DELETE/MOVE/재압축) 머지 및 재압축 머지, 백그라운드 뮤테이션, 백그라운드 파트 이동)을 중단하며, 데이터를 변경하는 파티션 명령어(ATTACH/MOVE/DROP/DROP DETACHED/FETCH/REPLACE PARTITION 및 해당 테이블을 대상으로 하는 MOVE PARTITION ... TO TABLE)도 거부합니다. 따라서 TTL이 설정된 table_readonly 테이블은 이 설정이 활성화되어 있는 동안 만료된 데이터를 더 이상 회수하지 않습니다. #95079 (matt-metivier).

메모리 및 리소스 효율성

  • UNLOCK SNAPSHOT 실행 시 잠금 해제 경로에서 사용하지 않는 데이터 파트별 메타데이터를 로드하지 않도록 하여 메모리 사용량을 줄였습니다. 이를 통해 파트 수가 매우 많은 스냅샷에서 메모리 부족(out-of-memory)이 발생하지 않도록 했습니다. #111849 (jkartseva).
  • 백업 메타데이터를 읽을 때의 메모리 할당을 줄였습니다. 이제 각 파일 엔트리를 복사하지 않고 인메모리 맵으로 이동(move)합니다. #111718 (jkartseva).

함수, 타입, 포맷 성능

  • Decimal 값을 텍스트로 포맷팅하는 속도가 크게 향상되었습니다. 스케일이 큰 Decimal256은 최대 190배, Decimal64는 약 1.6배 빨라졌습니다. AVX-512 IFMA를 지원하는 프로세서에서는 64비트 정수를 텍스트로 변환하는 속도가 약 1.4배 빨라졌습니다. 또한 소수부에서 발생한 자리올림을 누락하던 toDecimalString의 반올림 문제를 수정했습니다. toDecimalString(toDecimal64('9.995', 3), 2)는 기존에 9.00을 반환했으나 이제 10.00을 반환합니다. #112457 (thevar1able).
  • FixedString 키에 대한 partial_merge 조인 알고리즘의 성능을 개선했습니다. 값마다 비교 함수를 한 번씩 호출하는 대신 연속된 값 구간을 한 번에 비교합니다. #105737 (4ertus2).
  • 이제 HashJoin에서 단일 컬럼의 non-nullable 문자열 LowCardinality 키를 네이티브로 지원합니다. #107264 (nickitat).
  • 패턴과 대체 문자열이 모두 단일 문자일 때(예: replaceRegexpAll(s, ' ', '_')) replaceAll 및 replaceRegexpAll의 성능을 개선했습니다. 이러한 대체는 더 이상 String 레이아웃을 변경하지 않으므로, 일치 항목마다 검색 루프를 실행하지 않고 컬럼을 한 번만 복사한 뒤 일치하는 바이트를 제자리에서 재작성합니다. #108178 (groeneai).
  • 기본값인 best-effort 모드(date_time_input_format = 'best_effort', cast_string_to_date_time_mode = 'best_effort')에서 정규 YYYY-MM-DD hh:mm:ss 날짜-시간 표현의 파싱 속도를 높였습니다. 이로써 해당 기본값이 basic에서 best_effort로 변경되면서 발생했던 파싱 성능 저하를 해소했습니다. #108187 (groeneai).
  • 깊게 중첩된 배열 및 튜플 리터럴을 이차 시간이 아닌 선형 시간에 파싱합니다. #108892 (alexey-milovidov).
  • SECOND, MINUTE, HOUR 인터벌에서 toStartOfInterval 함수(별칭 time_bucket, date_bin)의 속도를 최대 5배 향상했습니다. #109729 (raimannma).
  • 람다 없이 호출하면 숫자 배열(Decimal 및 DateTime64 포함)에 대한 arraySort 및 arrayReverseSort 함수가 몇 배 더 빠르게 동작합니다. #109832 (raimannma).
  • 고정 오프셋 시간대(예: UTC)의 DateTime 및 DateTime64 값에 산술 연산 기반 고속 경로를 적용하여 addDays, addWeeks, subtractDays, subtractWeeks의 속도를 높였습니다. #109836 (raimannma).
  • Delta 코덱의 압축 해제를 벡터화했습니다. 8/16/32비트 데이터 타입의 디코딩이 1.5–5배 빨라져, Delta로 압축된 컬럼의 스캔 속도가 최대 20% 향상되었습니다. #110189 (raimannma).
  • 상수 needle을 사용하는 Enum 컬럼에 대한 문자열 검색 함수(like, position, match, countSubstrings, hasToken 등)의 속도를 높였습니다. 모든 행을 검색하지 않고 고유한 enum 이름만 검색한 뒤, 그 결과를 각 행에 다시 매핑합니다. #110325 (alexey-milovidov).
  • 상수가 아닌 needle을 사용하는 부분 문자열 검색 함수(position, countSubstrings, multiSearch*, replaceAll/replaceOne 및 각각의 대소문자 비구분 변형과 UTF-8 변형)의 성능을 최대 1.5배 향상했습니다. 행 단위 경로에서 단순한 폴백 대신 SIMD 기반 문자열 검색기를 사용하도록 개선했습니다. #110580 (Algunenano).
  • 동적 변형 또는 JSON 경로가 많은 Dynamic 및 Object 컬럼의 스쿼싱(squashing)과 머지 성능을 향상했습니다. #110583 (cv4g).
  • NONE 코덱 사용 시 estimateCompressionRatio의 속도가 빨라졌습니다. #111107 (rienath).
  • 경로가 공유 데이터에 저장된 JSON 컬럼에 대한 정렬 및 기타 비교 기반 연산의 속도를 개선했습니다. 이전에는 값을 비교할 때마다 임시 Dynamic 컬럼을 구체화하고 비교 대상 양쪽 모두에 대해 전체 바이너리 역직렬화를 수행했기 때문에, 이러한 컬럼에 대한 ORDER BY가 비정상적으로 느렸습니다. #111894 (groeneai).
  • 256비트 정수(Int256, UInt256, Decimal256)의 나눗셈에서 이제 시프트-뺄셈 방식의 장제법으로 한 번에 1비트씩 계산하는 대신, 몫을 64비트 limb 단위로 계산합니다. 제수가 64비트 이내이면 128 / 64 나눗셈 루프를 사용하고, 그렇지 않으면 Knuth의 Algorithm D를 사용합니다. 이 변경 사항은 intDiv, modulo, Decimal256 산술 연산 및 이러한 타입의 텍스트 변환에 적용됩니다. #112477 (thevar1able).
  • 바이너리로 인코딩된 타입(Native, input_format_binary_decode_types_in_binary_format을 사용하는 RowBinary)에서 Nested 컬럼을 읽을 때 더 이상 타입을 타입 이름으로 다시 변환한 뒤 재파싱하지 않습니다. 또한 잘못된 형식의 중첩 Tuple 타입 이름은 이제 중첩 깊이에 따라 지수적으로 시간이 걸린 끝에 TOO_SLOW_PARSING으로 실패하는 대신, 구문 오류로 보고됩니다. #112560 (alexey-milovidov).
  • TimeSeries 테이블에 대한 PromQL 쿼리 속도를 개선했습니다. 연속된 행의 시리즈 id가 동일하면 timeSeriesIdToGroup이 이전 행의 그룹을 재사용하므로, 행 단위 id 직렬화와 해시 조회를 건너뜁니다. #113580 (nikitamikhaylov).

기타 성능 개선 사항

  • Apache Arrow 라이브러리를 사용하지 않는 Arrow 및 ArrowStream 포맷용 네이티브 리더와 writer를 구현하여 불필요한 데이터 복사와 변환을 없앴습니다. 이제 이 구현이 기본값(설정 input_format_arrow_use_native_reader 및 output_format_arrow_use_native_writer)으로 사용되며, 읽기와 쓰기 모두 더 빨라졌습니다. #106522 (alexey-milovidov).
  • nullIf(key, sentinel) = const 프레디케이트를 최적화하여 키 범위를 구성하고, 이를 통해 프라이머리 키, 파티션, 스킵 인덱스 기반 프루닝을 적용할 수 있도록 했습니다. #107308 (adityaksolves).
  • 각 행을 SipHash로 해시하는 대신 행 값을 키로 사용하여 멀티셋을 구성함으로써 `INTERSECT ALL` 및 `EXCEPT ALL`(`INTERSECT`와 `EXCEPT`의 기본 모드)의 성능을 몇 배 향상했습니다. #107649 (Algunenano).
  • 단순한 정규식을 LLVM을 사용해 네이티브 코드로 컴파일하여 match, extract, extractAll, replaceRegexpOne, replaceRegexpAll 함수의 속도를 높였습니다. 이 기능은 새로운 설정 compile_regular_expressions(기본적으로 활성화됨)로 제어되며, 지원 범위를 벗어나는 패턴은 자동으로 RE2 엔진을 사용하도록 전환됩니다. #108004 (alexey-milovidov).
  • NEON으로 짧은 오프셋의 겹치는 복사를 벡터화하여, 고정 폭 정수 컬럼처럼 매치 오프셋이 작은 컬럼에 대한 AArch64(ARM)의 ZSTD 압축 해제 속도를 높였습니다. 예를 들어 AWS Graviton 4에서 UInt64 컬럼의 압축 해제가 최대 약 2.3배 빨라졌습니다. #108049 (alexey-milovidov).
  • 고정 크기의 낮은 카디널리티 컬럼에 대한 LZ4 압축 해제 속도를 개선했습니다. #108175 (nickitat).
  • 블록 단위 Myers 코드 경로에서 행마다 발생하던 힙 할당을 제거하여, ARM에서 중간 길이 문자열에 대한 levenshteinDistance(및 editDistance)의 성능을 개선했습니다. #108185 (groeneai).
  • precise_float_parsing = 1 설정 시 텍스트에서 부동소수점 숫자를 파싱하는 속도를 높여, 거의 모든 입력에서 기본 파서와 같거나 더 빠르게 동작하도록 했습니다. 또한 번들된 fast_float 라이브러리를 v8.2.10으로 업데이트했습니다. #108205 (Algunenano).
  • 이제 Base64 인코딩 및 디코딩 함수가 simdutf를 사용하므로 성능이 향상되었습니다. #108333 (thevar1able).
  • 처리 비용이 큰 높은 카디널리티 키에 대해 DISTINCT를 최적화했습니다. #108366 (nihalzp).
  • errno를 보존하지 않는 컴파일러 최적화를 활성화하여 수학 함수의 성능을 개선했습니다. #108628 (nickitat).
  • 실제로 압축하지 않고 압축된 크기를 분석적으로 계산하도록 하여, T64로 인코딩된 컬럼에 대한 estimateCompressionRatio의 속도를 높였습니다. #109054 (rienath).
  • 이제 JOIN에서 왼쪽 테이블의 프라이머리 키 인덱스 또는 스킵 인덱스를 사용하여 그래뉼을 프루닝할 수 있습니다. #109085 (shankar-iyer).
  • 좌표 변환에서 사인/코사인 쌍을 함께 계산하고 중복된 삼각 함수 호출을 제거하여 H3 지리 함수(h3ToGeoBoundary, h3ToGeo, h3CellAreaM2/h3CellAreaRads2, geoToH3)의 성능을 개선했습니다. 결과는 이전과 비트 단위까지 동일합니다. #109399 (alexey-milovidov).
  • 비교 및 부호 확장 코드를 분기 없는(branchless) 방식으로 변경하여, 큰 정수 타입(Int128, UInt128, Int256, UInt256 및 Decimal128과 같이 이를 기반으로 하는 타입)의 비교(<, >, <=, >=) 성능을 최대 7배, 부호 있는 정수를 Int256으로 변환하는 성능을 최대 7배(부호가 혼합된 데이터 기준) 개선했습니다. #109474 (raimannma).
  • 상수가 아닌 Nullable 인수가 하나뿐인 함수는 이제 null map을 새로 할당하고 머지하는 대신 인수의 null map을 결과와 공유합니다. #110151 (raimannma).
  • 원소별 비교 루프 대신 벡터화된 축약(reduction)을 사용하여 숫자 배열에 대한 arrayMin 및 arrayMax 함수의 성능을 약 1.3~1.5배 개선했습니다. #110163 (raimannma).
  • 입력 스트림이 distinct 컬럼의 접두사 기준으로 정렬되어 있을 때(예: SELECT DISTINCT a, b FROM table ORDER BY a) DISTINCT의 성능을 개선했습니다. 이러한 쿼리는 최대 2.4배 빠르게 실행됩니다. #110170 (nihalzp).
  • groupBitOr/groupBitAnd/groupBitXor 및 분산 계열 함수(varPop, varSamp, stddevPop, stddevSamp, skewPop, skewSamp, kurtPop, kurtSamp, covarPop, covarSamp, corr)에 벡터화된 배치 경로를 도입했습니다. 조건을 예측하기 어려운 경우 -If 콤비네이터 사용 시 최대 4배, 콤비네이터 없이 분산 계열 함수를 사용할 때는 최대 3배 빨라집니다. #110461 (raimannma).
  • 텍스트 인덱스 분석을 최적화했습니다. #110530 (CurtizJ).
  • 16진수 자릿값의 검증과 변환을 두 번이 아닌 한 번에 처리하여 텍스트에서 UUID 값을 파싱하는 속도를 높였습니다(예: LowCardinality(UUID)로의 JSONExtract, toUUID, CAST AS UUID). #110625 (groeneai).
  • SSSE3 pshufb로 짧은 오프셋의 중첩 복사를 벡터화하여, 고정 폭 정수 컬럼처럼 매치 오프셋이 작은 컬럼에 대한 x86_64 환경의 ZSTD 압축 해제 속도를 높였습니다(#108049의 AArch64 NEON 최적화에 대응하는 x86_64 버전). #110909 (thevar1able).
  • uniqExact와 같이 CRC32 해싱을 사용하고 행별 삽입을 인라인 처리하여 숫자 타입에 대한 groupUniqArray의 속도를 최대 3배 높였습니다. #110917 (raimannma).
  • 부동 소수점 컬럼에 대한 minmax 및 기본 컬럼 통계의 효율성을 개선했습니다. #111221 (cv4g).
  • COUNT() 쿼리 결과를 텍스트 인덱스의 카디널리티 메타데이터에서 직접 반환합니다. #111494 (ahmadov).
  • 128비트 및 256비트 유형(Int128, UInt128, Int256, UInt256, Decimal128, Decimal256)에 대한 min 및 max 연산 속도를 개선했습니다. 큰 정수형은 최대 1.8배, 큰 Decimal 유형은 최대 3.4배 빨라졌습니다. #111965 (raimannma).
  • system.query_log 수집 과정의 성능 저하를 수정했습니다. Settings 및 asynchronous_read_counters 맵 컬럼을 생성하는 작업이 이전보다 약 6배 느려져, 변경된 설정이 많은 쿼리를 다수 기록하는 서버에서 SYSTEM FLUSH LOGS query_log가 180초 타임아웃을 초과할 수 있었습니다. #112210 (groeneai).
  • 텍스트 인덱스에 없는 토큰을 선택적으로 캐싱하는 기능을 추가했습니다. #112742 (rorylshanks).
  • 이제 비동기 로깅에서 크기가 제한된 락프리(lock-free) 큐를 사용합니다. 로그 메시지를 기록하는 스레드는 뮤텍스에서 블로킹되지 않으며 로깅 스레드를 깨우지도 않습니다. #112803 (alexey-milovidov).
  • point 인수가 Point 유형(또는 숫자 요소 2개로 구성된 다른 Tuple)의 키 컬럼 전체인 경우에도 pointInPolygon에 프라이머리 키 인덱스를 사용합니다. 예를 들어 coord로 정렬된 테이블에 대한 pointInPolygon(coord, [...])이 이에 해당합니다. 이전에는 스칼라 키 컬럼 2개를 사용하는 pointInPolygon((x, y), [...]) 형식만 분석했습니다. #112956 (alexey-milovidov).
  • 이제 text_index_posting_list_apply_mode의 기본값이 lazy입니다. 따라서 posting_list_codec이 설정된 텍스트 인덱스에서는 텍스트 인덱스 쿼리가 포스팅 리스트를 비트맵으로 미리 구체화하지 않고, 커서를 사용해 패킹된 블록 세분화 수준에서 필요할 때마다 디코딩합니다. #113521 (CurtizJ).
  • 태그 그룹 ID가 조밀한 범위에 분포하는 경우 해시 기반 재매핑 대신 직접 인덱싱을 사용하여 벡터화된 TimeSeries 태그 변환 속도를 개선했습니다. #114244 (fallintoplace).
  • 텍스트 인덱스 병합 성능을 개선했습니다. #114525 (CurtizJ).
  • PromQL 집합 연산자에 압축된 존재 마스크를 사용합니다. #115224 (fallintoplace).
  • 시스템 테이블을 연결(attach)할 때 테이블 주석을 설정하려고 전체 컬럼 정의를 포함한 각 테이블의 메타데이터를 두 번씩 복사하지 않습니다. #115490 (thevar1able).
  • 모든 값이 0인 PromQL 조건 벡터에 대한 중복 시리즈 검사 속도를 개선했습니다. #115822 (fallintoplace).
  • DateTime64 인수에 대한 toUTCTimestamp/to_utc_timestamp 및 fromUTCTimestamp/from_utc_timestamp의 속도를 개선하여, 이전 오버플로 수정 이후 저하되었던 처리량을 회복했습니다. 결과는 동일합니다. #115838 (groeneai).
  • x86-64에서 무작위 데이터 생성(rand, rand64, randomString, randomFixedString, generateUUIDv4, generateUUIDv7)에 드는 고정 초기 설정 비용을 줄였습니다. 블록이 작을 때 효과가 두드러지며, 생성되는 값은 달라지지 않습니다. #116158 (Algunenano).
  • 이제 enable_function_early_short_circuit 설정으로 분석 단계에서 내장 and 및 or에 대한 조기 단락(short-circuit) 폴딩을 활성화할 수 있습니다. 이를 통해 일반적인 타입 추론과 의미론적 유효성 검사는 그대로 유지하면서, 결과에 영향을 주지 않는 단일 행 count() 스칼라 서브쿼리의 실행을 건너뛸 수 있습니다. #83505 (fhw12345).
  • 단순 직렬화가 가능한 벡터에 대해 단일 버퍼 IO 호출을 사용하도록 했습니다. #89842 (Ergus).
  • optimize_or_like_chain을 기본으로 활성화했습니다. #94517 (alexey-milovidov).
  • 서버에 사용자가 많을 때 system.users에서 단일 사용자 레코드를 조회하는 성능을 개선했습니다. #96699 (alistairjevans).

개선 사항

쿼리 및 SQL 개선 사항

  • UNION 쿼리의 여러 분기에서 참조되는 Materialized CTE가 이제 한 번만 구체화되어 모든 분기에서 공유됩니다. 이전에는 각 분기가 CTE의 개별 복사본을 받아 인라인으로 처리하고 별도로 평가했습니다. #102107 (novikd).
  • probe 측이 작을 것으로 추정되면 JOIN runtime filter를 건너뜁니다. 새 설정 join_runtime_filter_min_probe_rows(기본값 1000)로 임계값을 제어할 수 있습니다 #104860 (vdimir).
  • EXPLAIN [PLAN] actions=1, compact=1, pretty=1이 기본값이 되었습니다. #105036 (Fgrtue).
  • LIMIT BY의 양수 형태(LimitByTransform, LimitBySortedStreamTransform)에서 취소 지연 시간을 줄였습니다. 이제 KILL QUERY와 Ctrl+C를 실행하면 전체 단계가 끝날 때까지 기다리지 않고 단일 청크 내에서 처리가 중단됩니다. #106070 (rvasin).
  • 자동 병렬 레플리카에서 JOIN 쿼리를 지원합니다. #106073 (nickitat).
  • 스레드가 이미 할당했지만 아직 전역 메모리 추적 카운터에 반영되지 않은 메모리 양을 보고하는 새 비동기 메트릭 UntrackedMemory(system.asynchronous_metrics에서 확인 가능)를 추가했습니다. 각 스레드는 작은 할당을 로컬에 누적한 뒤 한꺼번에 보고합니다. 이를 통해 MemoryTracking과 프로세스의 실제 메모리 사용량 사이의 차이를 설명할 수 있습니다. 또한 MEMORY_LIMIT_EXCEEDED 오류 메시지에 추적되지 않은 메모리 양도 함께 표시되므로, 쿼리나 서버가 메모리 한도에 도달한 원인을 더 쉽게 파악할 수 있습니다. #106386 (mstetsyuk).
  • 삽입 파이프라인을 구성하는 중에 materialized view의 TO target table이 쓰기를 거부하여 INSERT가 실패하는 경우(예: 대상이 View이거나 트랜잭션을 지원하지 않는 경우), 이제 오류 메시지에 스토리지 오류만 표시하는 대신 materialized view와 해당 target table의 이름을 함께 표시합니다. #107234 (groeneai).
  • 이름이 지정된 Tuple에 대한 ALTER TABLE ... MODIFY COLUMN <col> Tuple(...)은 하위 필드만 추가하는 경우 이제 메타데이터만 변경하므로, 최상위 ADD COLUMN과 같은 속도로 수행됩니다. SET allow_metadata_only_named_tuple_alter = 1로 활성화할 수 있습니다. #107305 (amosbird).
  • MaterializedPostgreSQL 데이터베이스 엔진에 생성 시점 설정인 materialized_postgresql_use_extended_date_and_time_types를 추가했습니다. 기본값(활성화)에서는 PostgreSQL date/timestamp 컬럼이 Date32/DateTime64로 추론되며, CREATE DATABASE 시점에 이 설정을 0으로 지정하면 범위가 더 좁은 Date/DateTime 타입으로 추론됩니다. 이 설정은 MaterializedPostgreSQL 테이블 엔진에는 적용되지 않습니다. #107428 (alexey-milovidov).
  • 이제 EXPLAIN PLAN은 조인의 예상 결과 행 수가 테이블 통계가 아닌 힌트나 무작위 대체값에서 산출된 경우 이를 근사값(~~...)으로 표시합니다. 이를 통해 JOIN 재정렬에 필요한 신뢰할 수 있는 통계가 없는 계획을 쉽게 식별할 수 있습니다. #107666 (vdimir).
  • 이제 MergeTree 테이블에 대한 INSERT가 많은 파트를 쓰는 중에도 쿼리 취소와 max_execution_time을 준수하므로, kill된 후에도 오랫동안 계속 실행되는 문제가 더 이상 발생하지 않습니다. #107929 (al13n321).
  • 이제 arrayFold가 쿼리 취소와 max_execution_time을 준수합니다. 이전에는 매우 긴 배열에 대한 fold(예: arrayFold(acc, x -> arrayPushFront(acc, x), range(number), emptyArrayUInt64()))가 단일 함수 호출 안에서 전체 fold를 실행하여 중단할 수 없었기 때문에, fold가 끝날 때까지 KILL QUERY와 시간 제한이 무시되었습니다. #108192 (groeneai).
  • 쿼리 실행 전 단계별 ProfileEvents인 QueryParseMicroseconds, QueryAnalysisMicroseconds, QueryPlanBuildMicroseconds, QueryPipelineBuildMicroseconds를 추가했습니다. 이 이벤트로 쿼리 실행 전 각 단계(파싱, 분석, 쿼리 계획 빌드, 파이프라인 빌드)에서 소요되는 시간을 확인할 수 있으며, system.query_log와 system.events에서 조회할 수 있습니다. #108282 (jrdi).
  • 테이블 메타데이터가 max_query_size를 초과하게 되는 ALTER TABLE 작업은 이제 사전에 거부됩니다. 이를 통해 DDL 배포, 레플리카 복구 등의 구성 요소에서 테이블을 로드할 수 없게 되는 문제를 방지합니다. #108283 (lockie).
  • 카티션 조인과 분석기가 계획한 상수 조건 조인을 위한 ConstantJoin을 추가했습니다. 이에 따라 분석기를 사용할 때 이러한 쿼리가 호환되지 않는 join_algorithm 설정 때문에 실패하는 문제가 더 이상 발생하지 않습니다. #108289 (antaljanosbenjamin).
  • 각 엔터티의 문서가 정의된 소스 파일의 경로를 담은 source 컬럼을 system.documentation에 추가했습니다. 이제 이 테이블에는 압축 코덱, 프로파일 이벤트, 현재 메트릭, 비동기 메트릭, 시스템 테이블 자체(컬럼 포함)에 대한 문서도 포함되며, 설정 문서에는 유형과 기본값도 표시됩니다. #108346 (alexey-milovidov).
  • WHERE에 table 및 database 필터를 지정하면 system.iceberg_history는 일치하는 데이터베이스만 나열합니다. 서버에 관련 없는 원격 데이터베이스가 많을 때 시간을 절약할 수 있습니다. #108492 (Diskein).
  • 이제 쿼리 매개변수({name:Type} 치환)를 설정 값으로 사용할 수 있습니다. 쿼리(예: SELECT, INSERT)의 SETTINGS 절과 독립된 SET 쿼리 모두에서 사용할 수 있습니다. 예: SELECT ... SETTINGS max_threads = {threads:UInt64}, SET max_threads = {threads:UInt64}. #108760 (alexey-milovidov).
  • EXPLAIN WHATIF에서 스킵 인덱스의 결합 효과를 계산할 수 있습니다. 적합한 모든 가상 인덱스 성능의 교집합에 해당하는 데이터 비율을 보여 줍니다. #108934 (yariks5s).
  • 이제 CTE가 하나인 쿼리도 여러 CTE가 있는 쿼리와 동일한 줄바꿈 및 들여쓰기로 포맷됩니다. 이전에는 WITH a AS (...)의 경우 CTE가 WITH와 같은 줄에 놓였지만, CTE가 2개 이상이면 WITH가 별도 줄에 놓이고 각 CTE가 들여쓰기되었습니다. #109092 (groeneai).
  • File 테이블 엔진으로 읽는 로컬 Parquet 파일에서도 쿼리 조건 캐시(Query Condition Cache)를 지원합니다(이전에는 객체 스토리지와 데이터 레이크에서만 지원). #109247 (alexey-milovidov).
  • 원격(객체 스토리지) Parquet 파일의 쿼리 조건 캐시 키로 경로와 함께 ETag도 사용합니다. 따라서 객체를 같은 위치에 덮어쓰더라도 더 이상 오래된 캐시 결과가 반환되지 않습니다. #109310 (alexey-milovidov).
  • ON 조건에서 동등 비교되는 INNER JOIN 키를 한정자 없이 참조하더라도(예: SELECT id FROM a INNER JOIN b ON a.id = b.id) 양쪽이 동일한 값을 가지는 것이 보장되므로 더 이상 모호한 식별자로 보고되지 않습니다. #109366 (alexey-milovidov).
  • QBit에 대한 전치 거리 함수(L2DistanceTransposed, cosineDistanceTransposed, dotProductTransposed 및 양자화 버전인 L2DistanceTransposedQuantized, cosineDistanceTransposedQuantized, dotProductTransposedQuantized)가 이제 검색 대상 차원 수보다 긴 기준 벡터를 허용하며, 추가로 뒤에 오는 원소는 무시합니다. 따라서 축소 차원(Matryoshka) 검색 시 전체 크기의 쿼리 벡터를 미리 잘라낼 필요 없이 그대로 재사용할 수 있습니다. #109388 (alexey-milovidov).
  • 분산 쿼리에 항상 알려진 클라이언트 버전이 포함되는지 확인하는 정합성 검사를 추가했습니다. 이제 원격 샤드(shard)에 버전 0을 조용히 전달하는 대신 논리 오류를 발생시킵니다. 서버가 시작하는 쿼리(백그라운드 플러시, 스트리밍 컨슈머, 딕셔너리 리로드, 비동기 insert 플러시)는 이제 서버 자체 버전을 개시자(initiator) 버전으로 보고합니다. #109408 (alexey-milovidov).
  • MergeTree 계열 테이블 엔진에 대한 뮤테이션(mutation) 작업의 where 절에서 한정된 컬럼 이름을 사용할 때 발생하던 문제를 수정했습니다. #109491 (Michicosun).
  • 분산 쿼리 계획(make_distributed_plan)에서 파티션을 지정하지 않은 윈도우 함수(OVER (ORDER BY ...))를 지원합니다. 이전에는 WindowStep을 원격 실행용으로 직렬화할 수 없어 윈도우 함수가 포함된 쿼리는 모두 실패했습니다. PARTITION BY가 있는 윈도우는 당분간 계속 거부됩니다. #109802 (VighneshPath).
  • 이제 ALTER DATABASE ... MODIFY SETTING = 'xxx'를 사용하여 one-lake 카탈로그의 일부 인증 설정을 변경할 수 있습니다. #110019 (alesapin).
  • IN의 오른쪽 서브쿼리가 왼쪽 인수보다 한 차원 더 깊은 배열 컬럼 하나만 반환하는 경우, 이제 혼란스러운 타입 불일치 오류로 실패하지 않고 (배열 리터럴이나 배열을 반환하는 함수와 마찬가지로) 해당 배열 원소의 집합으로 해석됩니다. 예를 들어 x IN (SELECT groupArray(x) FROM ...)이 이제 정상적으로 동작합니다. #110169 (alexey-milovidov).
  • TopK 동적 필터링(ORDER BY ... LIMIT k)으로 가속되는 쿼리가 이제 쿼리 조건 캐시를 더욱 폭넓게 활용합니다. 지연 머티리얼라이즈가 적용된 경우에도 캐시가 채워지며, 이러한 쿼리는 동일한 WHERE 조건을 가진 일반 쿼리가 이전에 기록한 항목을 재사용할 수 있습니다. #110507 (shankar-iyer).
  • 이제 SHOW CREATE TABLE(및 SHOW CREATE VIEW / SHOW CREATE DICTIONARY)은 요청한 테이블이 존재하지 않으면 SELECT 쿼리와 마찬가지로 오류 메시지에서 이름이 비슷한 테이블을 제안합니다. #110633 (alexey-milovidov).
  • 스트리밍 쿼리의 첫 번째 스냅샷만 읽은 뒤 업데이트를 구독하지 않고 종료하는 STREAM BOUNDED 수정자를 추가했습니다. #110653 (SmitaRKulkarni).
  • PromQL 쿼리의 쿼리 결과 캐시 문제를 수정했습니다. promql 방언은 비결정적 함수 검사를 우회하여 now() 시점에 고정된 오래된 결과를 반환할 수 있었으며, Prometheus HTTP API(/api/v1/query, /api/v1/query_range)는 캐시 엔트리를 전혀 저장하지 않았습니다. #110887 (nikitamikhaylov).
  • 이제 EXPLAIN ANALYZE는 조인 양쪽의 행 수, 매칭 비율, 팬아웃(fanout)과 함께 해시 테이블 메모리, 스필링(spilling) 등 알고리즘별 상태를 보고합니다. 추가 기록 작업이 필요한 매칭 메트릭을 수집하려면 matches = 1을 사용하십시오. #110892 (Fgrtue).
  • 쿼리가 런타임에 프로세서를 제거할 때(예: 지연 읽기를 사용하는 FINAL 또는 외부 정렬) 서버가 비정상 종료될 수 있던 파이프라인 실행기의 heap-use-after-free 문제를 수정했습니다. 이 문제는 AST fuzzer를 통해 발견되었습니다. #111017 (groeneai).
  • 공유 스토리지 스냅샷(enable_shared_storage_snapshot_in_query 설정)을 사용하는 쿼리가 스냅샷에서 데이터 파트를 제거할 때 발생하던 use-after-free(세그멘테이션 폴트) 문제를 수정했습니다. 예를 들어 쿼리의 다른 부분이 동시에 읽고 있는 MergeTree 테이블을 스트리밍 서브쿼리가 함께 읽는 경우가 이에 해당합니다. #111192 (alexey-milovidov).
  • 비어 있는 MergeTree 테이블 읽기처럼 계획 단계에서 소스가 행을 생성하지 않는다는 것이 확실한 쿼리에 대해서도 분산 쿼리 계획(make_distributed_plan)을 지원합니다. 이전에는 이러한 쿼리가 SUPPORT_IS_DISABLED 오류로 실패했습니다. #111941 (groeneai).
  • 여러 AND 조건으로 구성된 WHERE 절에서 마지막 조건이 아닌 다른 조건에 의해 제외된 그래뉼(granule)이 쿼리 조건 캐시에 기록되지 않던 문제를 수정했습니다. #112083 (shankar-iyer).
  • 버킷 기반 공유 데이터 직렬화(map_with_buckets 및 advanced)를 사용하는 JSON 컬럼을 쓸 때, 모든 버킷을 동시에 구체화하지 않고 쓰기 시 공유 데이터를 버킷 하나씩 분할하도록 하여 최대 메모리 사용량을 줄였습니다. 이 개선은 주로 Array(JSON) 컬럼에 효과적입니다. 스칼라 JSON은 공유 데이터가 그래뉼 단위로(index_granularity_bytes로 제한됨) 분할되므로 절감 효과가 작지만, Array(JSON)는 그래뉼 하나에 많은 중첩 행과 그만큼 많은 공유 데이터가 담길 수 있어 버킷을 하나씩 분할하는 방식으로 최대 메모리 사용량을 크게 낮출 수 있습니다 #112172 (Avogar).
  • 메모리 예약 스케줄링(Experimental)은 한도를 초과한 예약 증가에 필요한 공간을 대기 중인 메모리 해제로 확보할 수 있는 경우 더 이상 할당을 축출하지 않습니다. 이제 진행 중인 감소가 적용될 때까지 기다린 후 축출 여부를 결정하므로, 메모리 압력 상황에서 불필요하게 쿼리가 강제 종료되는 일을 방지합니다. #112299 (serxa).
  • 이제 SYSTEM DROP FILESYSTEM CACHE는 캐시 메타데이터 키를 병렬로 삭제하므로 대용량 파일 시스템 캐시를 더 빠르게 정리할 수 있습니다. 새로운 파일 캐시 설정 drop_cache_threads로 삭제 작업자 수를 지정할 수 있으며 기본값은 16입니다. 값을 1로 지정하면 쿼리 스레드에서 직접 삭제를 수행합니다. #112532 (kssenii).
  • 컬럼 선언의 수정자인 COMMENT, CODEC, STATISTICS, TTL, COLLATE, PRIMARY KEY 및 컬럼별 SETTINGS를 이제 CREATE TABLE에서 임의의 순서로 작성할 수 있으며, 각 수정자는 최대 한 번만 사용할 수 있습니다. 이전에는 정해진 순서 하나만 허용되었기 때문에, 예를 들어 x UInt64 CODEC(ZSTD) COMMENT 'text'는 구문 오류였습니다. ALTER TABLE ... ADD COLUMN / MODIFY COLUMN에서도 지원되는 수정자인 COMMENT, CODEC, STATISTICS, TTL 및 컬럼별 SETTINGS를 임의의 순서로 작성할 수 있습니다. 또한 ADD COLUMN의 컬럼별 SETTINGS와 ADD COLUMN / MODIFY COLUMN에 선언된 STATISTICS가 이제 아무 알림 없이 누락되지 않고 정상적으로 적용되며, 이러한 ALTER 명령에서 COLLATE와 PRIMARY KEY를 사용하면 조용히 무시되는 대신 예외가 발생합니다. #112788 (alexey-milovidov).
  • 많은 테이블과 일치하는 Merge 테이블(또는 merge 테이블 함수)에 대한 쿼리가 이제 모든 하위 테이블의 계획 수립이 끝난 뒤에야 반응하는 것이 아니라, 테이블별 쿼리 계획을 생성하는 도중에도 KILL QUERY와 max_execution_time에 반응합니다. #113415 (alexey-milovidov).
  • timeout_overflow_mode = 'break' 설정에서 max_execution_time을 초과한 Merge 테이블의 SELECT는 이제 중단 전에 일치하는 모든 테이블에 대해 전체 쿼리 분석을 실행하지 않고, 나머지 일치 테이블에 대한 쿼리 계획 생성을 바로 중단합니다. 해당 모드의 문서에 설명된 대로 쿼리는 여전히 오류 없이 완료됩니다. #113642 (groeneai).
  • MergeTree 읽기 중 컬럼의 선언된 타입과 실제 데이터가 일치하지 않는 경우(타입 출처가 혼재된 경우, 예: 뮤테이션이 완료되지 않은 ALTER TABLE ... MODIFY COLUMN 이후), 서버는 이제 검사 없이 캐스트를 수행하는 대신 해당 컬럼과 두 구조를 명시한 명확한 예외를 보고합니다. 이전에는 디버그 및 새니타이저 빌드에서 컬럼 이름 없이 Bad cast from type A to B만 출력하고 비정상 종료되었으며, 릴리스 빌드에서는 일치하지 않는 메모리를 아무 알림 없이 탐색했습니다. #114087 (alexey-milovidov).
  • ie_join이 기본적으로 활성화되었습니다. 이제 join_algorithm의 기본값은 direct,parallel_hash,hash,ie_join입니다. ON 절에 부등 조건(조인 대상 테이블의 표현식 간 <, <=, >, >= 비교 2개)만 있는 JOIN은 이제 필터를 적용한 CROSS JOIN 대신 정렬 기반 IEJoin 알고리즘으로 실행되며, 이러한 조건을 사용하는 LEFT/RIGHT/FULL/SEMI/ANTI 조인도 지원됩니다. ie_join은 목록의 마지막에 있으므로 다른 알고리즘을 적용할 수 없을 때만 사용됩니다. #114327 (vdimir).
  • 비동기 연결 수립 및 원격 쿼리 실행(헤지 요청, async_socket_for_remote, async_query_sending_for_remote)에 사용되는 파이버로 OpenTelemetry 추적 컨텍스트를 전파합니다. 이제 분산 쿼리에서 원격 쿼리의 스팬은 클라이언트가 제공한 추적 컨텍스트에 직접 연결되지 않고 시작 노드의 Connection::sendQuery 스팬의 하위 스팬으로 올바르게 연결되며, 각 비동기 작업 실행마다 별도의 스팬이 생성됩니다. #114813 (diegomestre2).
  • DROP DATABASE는 이제 로딩 의존성과 참조 의존성을 모두 고려한 역위상 순서로 테이블을 삭제합니다(이전에는 로딩 의존성만 고려). 따라서 DROP DATABASE 도중 크래시가 발생하더라도 의존 대상이 이미 삭제된 테이블이 남지 않습니다. #114952 (alexey-milovidov).
  • PostgreSQL 스타일의 정규식 매칭 연산자를 지원합니다: ~(match 함수의 별칭), ~*(대소문자를 구분하지 않는 매칭), !~ 및 !~*(부정). 이제 PostgreSQL 호환 프로토콜로 ClickHouse에 연결했을 때 psql의 \d, \dt, \dv 명령이 동작하며, 쿼리가 실패해도 더 이상 연결이 끊어지지 않습니다. #115066 (alexey-milovidov).
  • 이제 EXPLAIN WHATIF는 empirical_status가 unsupported일 때 새로 표시되는 empirical_reason 줄을 통해 경험적 추정을 건너뛴 이유를 알려 줍니다. #115140 (yariks5s).
  • join_algorithm 설정으로 활성화된 조인 알고리즘 중 어느 것도 JOIN을 실행할 수 없을 때, 이제 오류 메시지가 단순히 모두 동작하지 않았다고만 알리는 대신 시도한 알고리즘과 실패한 JOIN의 엄격성(strictness) 및 종류를 명시합니다. #115226 (elkinal).
  • 이제 기준 벡터가 정수 배열 리터럴인 경우(예: ORDER BY L2Distance(vec, [1, 2]))에도 벡터 검색 쿼리에서 벡터 유사성 인덱스를 사용할 수 있습니다. 이전에는 이러한 쿼리가 아무런 알림 없이 전수 스캔(brute-force scan)으로 대체되었습니다. #115255 (rschu1ze).
  • 잠금 파일을 생성한 BACKUP 시도가 아무것도 기록하기 전에 실패하면, 대상을 점유하는 도중이든 아카이브를 여는 도중이든 더 이상 대상에 잠금 파일이 남지 않습니다. 이전에는 이후의 어떤 백업도 이러한 잠금과 일치할 수 없었기 때문에, 파일을 수동으로 삭제하기 전까지 같은 대상에 대한 재시도가 모두 실패했습니다. 또한 S3 및 Azure 대상으로의 백업에서도 잠금을 배타적으로 생성하며, 다른 백업이 소유한 잠금은 스토리지가 반환한 임의의 오류 대신 동시 백업으로 보고됩니다. #115387 (jkartseva).
  • 샘플링(opentelemetry_start_trace_probability)으로 시작된 트레이스가 이제 쿼리의 클라이언트 정보에 다시 기록됩니다. 따라서 원격 및 분산 보조 쿼리와 DDL 항목이 별개의 트레이스를 새로 시작하지 않고 동일한 트레이스에 합류합니다. #115619 (diegomestre2).
  • 테이블 위치를 자체적으로 관리하는 Amazon S3 Tables 기반 Iceberg 테이블에서 CREATE TABLE이 동작하도록 수정했습니다. #115652 (scanhex12).
  • 적응형 GROUP BY 집계(enable_adaptive_aggregator)는 이제 드문 키의 처리를 지연하는 것이 실제로 효과가 있는지 측정하고, 해당 키나 집계 인수가 너무 커서 복사하는 이점이 없으면 일반 알고리즘으로 되돌아갑니다. 따라서 큰 문자열 컬럼에 대한 집계(예: 사용자별 min(URL))도 일반 알고리즘과 같은 속도와 메모리 사용량으로 실행됩니다. 각 스레드의 고정(frozen) 테이블 크기를 바이트 단위로 제한하는 adaptive_aggregator_freeze_threshold_bytes를 추가했습니다(이 값과 키 개수 임계값 중 먼저 도달하는 쪽에서 테이블이 고정됩니다). #115755 (nihalzp).
  • 최종 집계 결과가 LIMIT n이 포함된 ORDER BY로 전달될 때 각 2단계 버킷에서 상위 n개 그룹만 구체화하는 계획 최적화를 켜고 끌 수 있는 query_plan_aggregation_bucket_top_k 설정(기본적으로 활성화됨)을 추가했습니다. 이제 이 최적화는 EXPLAIN 출력에도 표시됩니다. #116124 (nihalzp).
  • 매개변수화된 뷰(parameterized view)에 대한 DESCRIBE 쿼리 지원을 개선했습니다. 새 분석기에서 스칼라 표현식 내의 매개변수화된 뷰를 지원합니다. #68978 (novikd).
  • 이제 SELECT * FROM t WHERE id와 같은 쿼리에서 id 컬럼에 대해 인덱스 스키핑이 사용됩니다. #89603 (adityachopra29).
  • JOIN 재정렬 최적화 과정에서 Expression 단계를 JOIN 단계로 머지할 수 있도록 query_plan_merge_expression_into_join 설정을 추가했습니다. 이를 통해 조인을 감싸는 서브쿼리(예: 계산된 컬럼이 있는 서브쿼리 안에 JOIN이 있는 경우)에 걸쳐서도 JOIN 재정렬을 수행할 수 있으므로, 복잡한 조인 트리를 더 효과적으로 최적화할 수 있습니다. #98533 (vdimir).
  • system.grants 테이블에 권한 부여가 와일드카드 접두사 매칭(예: GRANT SELECT ON db*.*)을 사용하는지 여부를 나타내는 is_wildcard 컬럼을 추가했습니다. 기존에는 system.grants에서 같은 이름에 대한 와일드카드 권한 부여와 정확히 일치하는 권한 부여를 구분할 수 없었습니다. #98577 (il9ue).

함수 및 데이터 타입

  • 새로운 설정 allow_lossy_numeric_supertype(기본값: 비활성화)을 추가했습니다. 이 설정을 활성화하면 손실 없는 공통 타입이 없는 숫자 인수(예: Decimal과 Float64, 또는 Int64와 Float64)에 대해 if, multiIf, coalesce, ifNull, array, map의 결과 타입이 Variant 대신 숫자 상위 타입인 Float64로 결정되므로, 그 결과를 sum, avg, min, max 등의 집계 함수에 사용할 수 있습니다. 또한 관련 집계 함수 오류 메시지에 이 설정 이름이 함께 표시됩니다. #107236 (groeneai).
  • 이제 SOME / ALL 배열 한정자(expr OP SOME(array) / expr OP ALL(array))에서 키워드 비교 프레디케이트인 IS DISTINCT FROM, IS NOT DISTINCT FROM과 문자열 검색 프레디케이트인 LIKE, ILIKE, NOT LIKE, NOT ILIKE, REGEXP도 사용할 수 있으며, 이들은 arrayExists / arrayAll로 재작성됩니다. #107454 (alexey-milovidov).
  • 파싱 시 JSON 객체 크기를 제한하는 input_format_json_max_object_size 설정을 추가했습니다. #107669 (Avogar).
  • SQLite 데이터베이스 열기에 실패할 때(예: sqlite 테이블 함수나 SQLite 데이터베이스 엔진에 열 수 없는 경로를 지정한 경우) 발생하던 메모리 누수를 수정했습니다. #107807 (alexey-milovidov).
  • QBit 데이터 타입에서 length 함수를 지원합니다. 이 함수는 벡터의 차원을 상수로 반환합니다. #108071 (alexey-milovidov).
  • QBit을 Array로 CAST하여 원래 벡터를 복원하는 기능을 지원합니다. 이는 기존의 Array에서 QBit으로의 변환과 반대 방향의 변환입니다. #108072 (alexey-milovidov).
  • 이제 MySQL 데이터베이스 엔진, 테이블 엔진, 테이블 함수가 MySQL의 공간 컬럼 타입(LINESTRING, POLYGON, MULTILINESTRING, MULTIPOLYGON 및 범용 GEOMETRY)을 String 대신 이에 대응하는 ClickHouse 기하 타입으로 매핑합니다. 이 동작은 mysql_datatypes_support_level 설정의 새로운 geometry 플래그로 제어하며, 기본적으로 활성화되어 있습니다. POINT는 기존과 같이 항상 Point로 변환됩니다. 범용 GEOMETRY 컬럼은 포괄 타입인 Geometry로 매핑되며, ClickHouse에 대응 타입이 없는 하위 타입(MULTIPOINT, GEOMETRYCOLLECTION)의 값을 읽으면 읽기 시점에 예외가 발생합니다. #108944 (alexey-milovidov).
  • 정밀한(가장 가까운 표현 가능 값을 찾는) 부동소수점 파싱 알고리즘을 기본으로 사용하며, precise_float_parsing 설정이 toFloat*/CAST뿐 아니라 입력 형식(CSV, TSV, JSON, VALUES 등)과 숫자 리터럴에도 적용됩니다. 경우에 따라 더 빠르지만 정확도가 낮은 이전 동작을 사용하려면 precise_float_parsing = 0으로 설정하십시오. #109086 (Algunenano).
  • 고정 크기 요소로 이루어진 Array를 String으로 reinterpret하는 기능을 지원합니다. 이는 기존의 String/FixedString을 Array로 reinterpret하는 기능과 반대 방향의 변환입니다. #109383 (alexey-milovidov).
  • 차원이 동일하게 유지된다면 원소 타입 및/또는 stride가 서로 다른 QBit 타입 간의 CAST를 허용합니다(예: QBit(Float32, N)에서 CAST(x AS QBit(Float64, N))로 변환). stride만 변경하는 경우에는 손실이 없으며, 원소 타입을 변경하는 경우에는 해당 Array 변환 의미 체계를 따릅니다(예: Float32에서 BFloat16으로 변환하면 정밀도가 손실될 수 있으며, accurateCast / accurateCastOrNull은 정확하게 표현할 수 없는 행을 거부합니다). #109387 (alexey-milovidov).
  • quantizeBFloat16ToInt8 및 dequantizeInt8ToBFloat16 함수가 기존 스칼라 오버로드에 더해 이제 Array 및 QBit 인수도 받으며, 전체 벡터에 Lloyd-Max 코덱을 적용합니다(해당 원소 타입의 Array/QBit를 반환). #109398 (alexey-milovidov).
  • parseDateTime / parseDateTime64(및 OrZero / OrNull 변형)의 MySQL 스타일 형식 지정자 %f가 이제 정확히 6자리를 요구하지 않고 1~6자리의 소수 자릿수를 허용하며, MySQL의 STR_TO_DATE처럼 왼쪽 정렬된 마이크로초로 해석합니다. 또한 내장 함수 문서 예시에서 PrettyCompact 테이블이 잘못 정렬되던 문제를 수정했습니다. #109421 (alexey-milovidov).
  • basic 통계의 NullCount 하위 통계 이름이 DefaultCount로 변경되었습니다. 이제 build는 Nullable 컬럼의 NULL 행을 세는 대신 IColumn::getNumberOfDefaultRows를 통해 컬럼 타입 고유의 기본값과 같은 행을 셉니다. #109977 (hanfei1991).
  • 거의 사용되지 않는 혼합 타입 쌍(Decimal과 너비가 다른 정수, 그리고 Int128/UInt128/Int256/UInt256이 포함된 쌍)의 비교 및 산술 연산을 타입 조합마다 전용 컴파일 커널을 두는 대신 공통 타입으로 변환하여 실행하도록 변경해 바이너리 크기를 약 10.5MB 줄였습니다. 동일 타입 쌍, 자주 사용되는 쌍, 메모리 바운드 연산인 plus/minus/multiply는 전용 커널을 그대로 유지하며, 결과, 결과 타입 및 예외 상황은 변경되지 않습니다. #110131 (alexey-milovidov).
  • SQLite 테이블 엔진 또는 sqlite 테이블 함수에서 읽을 때 SQLite 데이터베이스가 다른 연결에 의해 잠겨 있어도 더 이상 바쁜 대기(busy-spin)로 CPU 코어 하나를 완전히 점유하지 않습니다. 이제 읽기는 잠금을 기다리는 동안 유휴 상태로 대기하며, 취소도 가능합니다. #110248 (groeneai).
  • 로그 및 예외 메시지의 경과 시간, 속도, 비율 값을 세 자리로 반올림하여 1.345844286 sec.와 같은 숫자가 더 이상 전체 정밀도로 출력되지 않도록 했습니다. #110277 (alexey-milovidov).
  • 선행 행을 건너뛴 후 별도의 크기 스트림이 있는 String 컬럼을 MergeTree에서 읽으면 잘못된 데이터를 반환하거나 서브스트림 캐시에서 경계를 넘어 읽을 수 있던 문제를 수정했습니다. 또한 map shared data 직렬화로 저장된 JSON 하위 객체에 동시 읽기 또는 반복 읽기가 접근할 때 잘못된 데이터가 반환될 수 있던 문제를 수정했습니다. #110471 (alexey-milovidov).
  • PostgreSQL 테이블 엔진과 postgresql 테이블 함수에서 SETTINGS 절을 지원하여(예: SETTINGS postgresql_connection_pool_size = 50) MySQL 엔진과 동등한 기능을 제공합니다. #110614 (alexey-milovidov).
  • 이제 bitmaskToArray 및 bitmaskToList 함수가 (U)Int128 및 (U)Int256 인수를 지원합니다. 또한 큰 정수 인수에 대해 bitPositionsToArray 함수의 실행 시간이 가장 높은 설정 비트의 위치가 아니라 설정된 비트 수에 비례하도록 개선되었습니다. #110743 (raimannma).
  • 음수가 포함된 부호 있는 고정 폭 값을 GCD 코덱이 처리하는 방식을 수정했습니다. 이전에는 부호 있는 값으로 제수를 직접 계산했기 때문에 공약수를 찾지 못할 수 있었고, 그 결과 부호 있는 정수 및 decimal 컬럼의 압축 효율이 크게 떨어질 수 있었습니다. 이제 부호 있는 타입은 절댓값을 기준으로 제수를 계산하며, 부호 없는 타입과 압축 해제는 기존 동작을 그대로 유지합니다. #113798 (kshcherbatov).
  • 이제 PARTITION BY를 포함한 윈도 함수가 make_distributed_plan에서도 동작합니다. 계획 구조가 허용하는 경우, 윈도우는 각각 완전한 파티션을 할당받는 여러 버킷에서 병렬로 실행됩니다. #114111 (VighneshPath).
  • 이제 외부 집계의 널 허용 고정 폭 집계 방식에 64비트 해시 함수를 사용합니다(카디널리티가 매우 높은 집계에서 심각한 해시 충돌을 방지합니다). #114210 (nickitat).
  • 이제 LowCardinality 컬럼에 대한 x IN (subquery)가 x IN (literal list)와 동일한 타입인 LowCardinality(UInt8)를 반환합니다. 이전에는 두 형식이 서로 다른 타입을 반환했기 때문에, 이러한 IN이 포함된 분산 계획은 계획 타입 검사에서 별도의 예외 처리가 필요했습니다. #114229 (davenger).
  • JSON 데이터 타입, JSONExtract, isValidJSON에서 64비트 범위를 초과하는 정수를 파싱할 수 있습니다. 이러한 값이 있어도 전체 문서가 거부되지 않고, Int128/UInt256 등의 넓은 정수 타입으로 읽힙니다. #114379 (Avogar).
  • OpenSearch, Elasticsearch, SolR, Lucene과의 호환성을 높이기 위해 텍스트 인덱스 토크나이저 array의 별칭으로 keyword를 추가했습니다. #115507 (rschu1ze).
  • 이제 toDateOrNull, toDateTimeOrNull, toDateTime64OrNull 함수가 모든 기본 정수 타입의 정수 인수를 받을 수 있으며(toDate, toDateTime, toDateTime64와 동일한 방식으로 해석되고 시간대 인수를 선택적으로 지정할 수 있음), 결과 타입의 범위를 벗어나는 값에는 NULL을 반환합니다. 예를 들어 toDateTimeOrNull(1583851242, 'Asia/Shanghai')는 2020-03-10 22:40:42를 반환하고, toDateTimeOrNull(4294967296)은 NULL을 반환합니다. #79791 (jitendra1411).

저장소, 데이터 레이크 및 객체 저장소

  • 파일 시스템 캐시 eviction 활동에 대한 선택적(opt-in) Prometheus 메트릭(filesystem_cache_evictions_total, filesystem_cache_evicted_bytes_total, filesystem_cache_evicted_segment_hits, filesystem_cache_evicted_segment_size_bytes 및 user_id 레이블이 붙은 사용자별 변형)을 추가했습니다. 이 메트릭은 캐시별로 system.dimensional_metrics, system.histogram_metrics 및 Prometheus 엔드포인트를 통해 노출됩니다. 캐시 디스크 구성 설정인 expose_prometheus_eviction_metrics 및 expose_prometheus_eviction_metrics_per_user(둘 다 기본값은 비활성화)로 제어하며, SYSTEM RELOAD CONFIG를 사용해 런타임에 켜고 끌 수 있습니다. #105020 (sacheendra).
  • 이제 대상 테이블이 MergeTree 엔진 계열인 경우 Alias 엔진에서 병렬 레플리카 읽기를 지원합니다. #107830 (nauu).
  • Azure Blob Storage의 읽기 후 쓰기 방식 복사(네이티브 복사를 사용할 수 없을 때 백업에서 사용)에서 동시에 스테이징되는 파트 수를 max_inflight_parts_for_one_file로 제한하여, 여러 대용량 파일을 병렬로 복사할 때 메모리가 과도하게 사용되지 않도록 했습니다. #108232 (SmitaRKulkarni).
  • HDFS 저장소에서 _etag 가상 컬럼을 지원합니다. #108255 (zhangyifan27).
  • system.backups 및 system.backup_log에 settings 및 engine_settings 컬럼을 추가했습니다. settings는 작업 시 요청된 백업/복원 관련 설정(예: allow_s3_native_copy, deduplicate_files, structure_only)을 보여 주고, engine_settings는 백업 엔진의 reader/writer가 실제로 사용한 설정(예: allow_native_copy와 같은 S3 요청 설정으로, 엔드포인트 구성과 머지된 후에는 요청된 값과 다를 수 있음)을 보여 줍니다. 이를 통해 BACKUP/RESTORE 작업이 실제로 어떤 설정으로 실행되었는지 확인할 수 있습니다. #108334 (jkartseva).
  • 등록된 S3Queue 및 AzureQueue 테이블의 Keeper 상태(처리 완료, 처리 중, 실패한 파일 수 포함)를 조회할 수 있는 system.s3_queue_metadata 및 system.azure_queue_metadata를 추가했습니다. #108522 (kssenii).
  • 텍스트 인덱스 헤더 캐시의 메모리 사용량을 2~2.5배 줄였습니다. 캐시(text_index_header_cache_size 설정)에 더 많은 데이터 파트의 헤더를 담을 수 있어 텍스트 검색 쿼리의 디스크 읽기가 줄어듭니다. #109332 (CurtizJ).
  • INFORMATION_SCHEMA 뷰에 MySQL 호환 컬럼을 추가했습니다. 추가된 컬럼은 SCHEMATA.DEFAULT_COLLATION_NAME 및 DEFAULT_ENCRYPTION, TABLES.ENGINE 및 관련 MySQL 컬럼, 그리고 COLUMNS.COLUMN_KEY, PRIVILEGES, GENERATION_EXPRESSION, SRS_ID입니다. 이를 통해 MySQL 호환 클라이언트가 UNKNOWN_IDENTIFIER 오류 없이 카탈로그 조회 쿼리를 실행할 수 있습니다. #109351 (alexey-milovidov).
  • 스키마에서 파생된 파트별 메타데이터(컬럼 목록, 컬럼 정의, 직렬화, 컬럼 하위 스트림)를 모든 파트에 복사하지 않고 테이블의 파트 간에 공유하도록 변경하여, 데이터 파트가 많은 MergeTree 테이블의 메모리 사용량을 줄였습니다. 작은 파트가 많은 넓은 테이블에서 효과가 가장 큽니다. #109816 (Algunenano).
  • 새로운 설정 use_projection_index_in_read_pools를 추가했습니다(기본값은 비활성화). 이 설정을 활성화하면 프로젝션 인덱스로 완전히 필터링된 마크 범위를 읽기 중에 그래뉼 단위로 건너뛰는 대신, 해당 범위에 대한 읽기 작업을 생성하기 전에 MergeTree 읽기 풀 내부에서 제거합니다. 따라서 읽지 않을 데이터에 대해 읽기 작업을 생성하거나 리더를 설정하지 않으며, 읽기 작업 크기도 남은 마크를 기준으로 유지됩니다. #110291 (KochetovNicolai).
  • MergeTree에서 파트별 기본 키 이진 탐색 진단 정보의 로깅 수준을 trace에서 test로 낮추어 출력량을 줄였습니다. #110324 (alexey-milovidov).
  • TLS(HTTPS, S3) 기반의 풀링된 HTTP keep-alive 연결이 불필요하게 재연결되는 문제를 수정했습니다. 기존에는 오래된 연결을 검사할 때 소켓에 poll을 사용했는데, 이 방식은 아직 읽지 않은 TLS 핸드셰이크 이후 레코드(세션 티켓 또는 KeyUpdate)가 남아 있는 활성 보안 연결을 닫힌 것으로 잘못 판단합니다. 이제 일반 소켓에서는 논블로킹 MSG_PEEK를, TLS 소켓에서는 SSL_peek/SSL_has_pending을 사용하므로 정상적인 TLS 종료와 일부만 도착한 TLS 레코드도 올바르게 감지합니다. #110402 (alexey-milovidov).
  • 이제 OneLake catalog에서 OAuth 리프레시 토큰을 사용해 액세스 토큰을 갱신할 수 있습니다. #110413 (alesapin).
  • *MergeTree 테이블에 INSERT된 블록의 중복을 제거하는 과정에서 수행되는 컬럼 단위 데이터 해시 계산 횟수를 집계하는 DuplicationDataHashComputations ProfileEvent를 추가했습니다. #111173 (valerypetrov).
  • UNIQUE KEY 인덱스 SST를 로컬 임시 파일에 먼저 기록하지 않고, 저장소 추상화 계층을 통해 파트에 직접 기록하도록 변경했습니다. #111189 (JingYanchao).
  • 로컬 디스크의 Iceberg 테이블에 대한 동시 쓰기를 지원합니다. 이제 LocalObjectStorage가 조건부 쓰기를 구현하므로 version-hint.text를 통해 새 스냅샷을 게시하는 compare-and-swap이 로컬 디스크에서도 동작하며, 동시에 쓰는 여러 작성자가 서로의 업데이트를 덮어써 잃어버리는 일이 없습니다. #112556 (alexey-milovidov).
  • 이제 S3 클라이언트의 버킷 리전 캐시가 데이터 레이크 카탈로그에서도 동작합니다. 이전에는 데이터 레이크 카탈로그로 요청을 보낼 때마다 리전을 다시 조회했습니다. #113330 (scanhex12).
  • 이제 Azure 클라이언트 측 네트워크 장애(연결 재설정/거부, DNS 및 TLS 오류)가 인위적인 500 오류로 표시되지 않고 전송 오류로 처리되어 재시도됩니다. 이는 S3 클라이언트와 동일한 동작입니다. #115269 (arsenmuk).

포맷 및 수집

  • HTTP 인터페이스에서 snappy 압축(Accept-Encoding: snappy)을 허용하고, 일반 file/url snappy I/O에서 Hadoop snappy 블록 포맷과 snappy 프레이밍 포맷 중 하나를 선택할 수 있도록 snappy_mode 설정을 추가했습니다. #100752 (alexey-milovidov).
  • input_format_csv_missing_nullable_as_empty_string 설정을 추가했습니다(기본값은 비활성화). 이 설정을 활성화하면 input_format_csv_empty_as_default 설정과 관계없이 CSV 입력에서 누락된 Nullable(String) 값을 NULL 대신 빈 String으로 읽습니다. #107577 (alexey-milovidov).
  • input_format_protobuf_oneof_presence를 사용해 protobuf 메시지를 처리할 때 스키마 변경을 허용할 수 있도록 태그가 정확히 일치하지 않아도 되도록 변경했습니다. #109174 (ilejn).
  • 레거시 Apache Arrow 기반 ORC 리더를 제거했습니다. 이제 ORC 입력 형식은 항상 ClickHouse 네이티브 디코더(기존 기본값)를 사용합니다. input_format_orc_use_fast_decoder 설정은 더 이상 사용되지 않습니다(설정은 가능하지만 아무런 효과가 없습니다). #110074 (alexey-milovidov).
  • 이제 Hive 엔진은 Apache Arrow ORC 어댑터 대신 ClickHouse 네이티브 ORC 리더를 사용해 ORC 파일 메타데이터(min/max 인덱스, 행 수)를 읽습니다. #110086 (alexey-milovidov).

보안, 액세스 및 관측성

  • system.tables 테이블에 새 컬럼 skipping_indices_types가 추가되었습니다. 이 컬럼에는 각 테이블에 정의된 데이터 스킵 인덱스의 고유한 타입 목록이 포함됩니다. #106388 (CurtizJ).
  • 이제 max_threads 등 유사한 설정의 자동 값이 system.settings에서 'auto(8)'가 아닌 auto(8)로 표시됩니다. 값을 감싸던 작은따옴표는 오래전부터 값에 고착되어 있던 잔재였습니다. 버전 간 호환성은 그대로 유지되며, 이전 버전 서버에서 받은 설정을 파싱할 때는 기존의 따옴표 형식도 계속 허용됩니다. #108657 (alexey-milovidov).
  • system.documentation에서 설정 기본값이 비어 있으면 빈 백틱 대신 빈 문자열로 표시합니다. #108708 (alexey-milovidov).
  • 내장 /docs 페이지와 help 명령에서 보여 주는 system.documentation의 설정 문서에 이제 기본값 변경 이력이 포함됩니다. 설정이 도입된 버전과 이후의 모든 기본값 변경 내역이 이전 값, 새 값, 변경 사유와 함께 표시됩니다. #112177 (alexey-milovidov).
  • 이제 모든 SQL 문의 문서(예: 이름, 구문, 설명, 예시)를 시스템 테이블 system.statements에서 조회할 수 있습니다. #115341 (rschu1ze).

설정 및 구성

  • 새로운 서버 설정 memory_worker_rss_speculative_reserve_ratio(기본값 1.0, 새니타이저 빌드에서는 0)를 추가했습니다. 이 설정을 사용하면 전역 메모리 트래커가 MemoryWorker의 각 주기마다 관측된 RSS에 더해 ratio * min(resident - previous_resident, resident - tracked)만큼을 추정적으로 예약합니다. 샘플 사이에 RSS 증가 속도가 트래커의 집계 속도를 앞지르면 트래커 값을 높게 잡으므로, 할당 시 MEMORY_LIMIT_EXCEEDED가 더 일찍 발생하고 커널 OOM-killer가 먼저 작동할 가능성이 줄어듭니다. 추정 예약을 비활성화하려면 ratio를 0으로 설정하십시오. 새니타이저 빌드에서는 resident - tracked 차이의 대부분을 새니타이저 섀도 메모리가 차지하므로 기본값이 0입니다. #104976 (alexey-milovidov).
  • 텍스트 인덱스의 지연(lazy) 포스팅 리스트 적용 모드가 더 이상 Experimental 기능이 아니므로, allow_experimental_text_index_lazy_apply 없이도 text_index_posting_list_apply_mode = 'lazy'로 선택할 수 있습니다. 밀도 임계값 설정의 이름이 text_index_density_threshold에서 text_index_lazy_intersection_density_threshold로 변경되었습니다. #108814 (CurtizJ).
  • merge_selector_enable_heuristic_to_lower_max_parts_to_merge_at_once 설정이 이제 기본적으로 활성화됩니다. 이에 따라 머지 선택기가 파티션이 얼마나 차 있는지에 따라 한 번에 머지할 최대 파트 수를 자동으로 낮춥니다. #110726 (Michicosun).
  • PostgreSQL wire protocol에서 PostgreSQL 정리 명령인 RESET, UNLISTEN, DISCARD를 구문 오류로 처리하지 않고, 아무 작업도 수행하지 않는(no-op) 명령으로 허용합니다. 이를 통해 연결 설정 및 정리 과정에서 RESET ALL과 UNLISTEN *를 전송하는 Skunk 등의 드라이버와의 호환성이 향상됩니다. #110780 (alexey-milovidov).
  • AI 텍스트 함수(aiGenerate, aiClassify, aiExtract, aiTranslate)는 이제 잘렸거나 불완전한 제공자 응답(예: 모델이 max_tokens 한도에 도달한 경우)을 받으면 부분 출력을 별도 알림 없이 반환하지 않고 거부합니다. 이때의 동작은 ai_function_throw_on_error 설정을 따릅니다. #111830 (george-larionov).
  • 가우스 조건부 평균 접두사 중심점(centroid)으로 p < 8QBit(Int8) 코드를 재구성하여 축소 정밀도 L2DistanceTransposedQuantized, cosineDistanceTransposedQuantized, dotProductTransposedQuantized를 개선했습니다. 전체 정밀도(p = 8)에서는 계속 비트 단위까지 동일한 결과를 반환합니다. 축소 정밀도의 근사 거리는 달라질 수 있으며, 재현율/지연 시간 개선 효과는 워크로드에 따라 다릅니다. #111867 (skuznetsov).
  • write_snapshot_version 설정을 재시작 없이 다시 로드할 수 있도록 했습니다. #112150 (alesapin).
  • 원격 레플리카와의 비동기 통신에 사용되는 파이버(fiber) 스택의 관측성을 추가했습니다. 프로파일 이벤트 FiberStackAllocs, FiberStackAllocBytes, FiberStackAllocNanoseconds, FiberStackFreeNanoseconds와 메트릭 FiberStacks, FiberStackBytes가 제공됩니다. #114541 (alexey-milovidov).
  • Prometheus remote-write 프로토콜이 이제 비동기 삽입(asynchronous insert)을 지원합니다. async_insert 설정에 따라 동시에 들어오는 여러 remote-write 요청의 데이터를 일괄 처리한 후 파트를 생성합니다(기본적으로 활성화되어 있으며, 동기 방식을 유지하려면 핸들러 URL에 async_insert=0을 추가하십시오). 요청은 데이터가 대상 TimeSeries 테이블의 모든 내부 테이블에 플러시된 후에만 승인됩니다. #115688 (nikitamikhaylov).

기타 개선 사항

  • shrink_over_allocated_columns_min_waste_ratio와 shrink_over_allocated_columns_min_waste_bytes 설정 2개를 추가했습니다. 이 설정을 사용하면 INSERT 시 과다 할당된 컬럼(가변 길이 컬럼이 2의 거듭제곱 단위로 증가하여 예약된 메모리가 실제 사용 메모리보다 큰 컬럼)을 머티리얼라이즈 및 파트 쓰기 전에 실제 크기에 맞게 축소하므로 최대 메모리 사용량이 줄어듭니다. 기본적으로 비활성화되어 있습니다. #112161 (Avogar).
  • TTLDrop 머지에서는 데이터 읽기 단계를 완전히 건너뛰어 과도한 메모리 사용, 특히 읽기/프리페치 버퍼 할당으로 인한 메모리 사용을 방지합니다. #105859 (Avogar).
  • dotProduct에서 BFloat16을 지원하도록 했으며, SIMD 경로를 배치 처리하여 내적 성능을 개선했습니다. #106569 (nickitat).
  • max_named_collection_num_to_throw, max_table_num_to_throw, max_replicated_table_num_to_throw, max_view_num_to_throw, max_dictionary_num_to_throw, max_database_num_to_throw를 서버를 재시작하지 않고도 변경할 수 있도록 했습니다. #106821 (UberDever).
  • allow_experimental_delta_lake_writes로 제어되는 DeltaLake 테이블 쓰기 기능이 Beta로 승격되었습니다. #107034 (kssenii).
  • uniqCombined64 스케치 기반의 uniq 경량 대안인 uniq_v2 컬럼 통계 유형을 추가했습니다. #107863 (hanfei1991).
  • make_distributed_plan 실행을 관찰할 수 있도록 ProfileEvents DistributedPlanRemoteTasks, DistributedPlanLocalExecution, DistributedPlanHostsUsed를 추가했습니다. #107985 (shankar-iyer).
  • 이제 OneLake 등 REST 데이터 레이크 카탈로그로 보내는 요청에 ClickHouse User-Agent 헤더가 포함됩니다. #108117 (scanhex12).
  • 이제 MVTEncodeGeom은 클리핑 전에 지오메트리를 정수 픽셀 그리드에 스냅하고 wagyu로 폴리곤을 클리핑합니다. 따라서 클리핑된 출력이 유효하고(자기 교차 링이 복구됨) 경계에 정렬되어 PostGIS ST_AsMVTGeom의 결과와 일치합니다. #108248 (saarthak2002).
  • 텍스트 인덱스 캐시 3개를 모두 전역으로 활성화했습니다. 이전에는 쿼리 내에서만 활성화되었습니다. 또한 포스팅 리스트 캐시 크기가 이제 0으로 설정되어 사실상 이 캐시는 다시 비활성화됩니다. 포스팅 리스트는 크기가 커서 캐싱 비용이 지나치게 높기 때문입니다. #108274 (rschu1ze).
  • 테이블을 로드하기 전에 Prometheus 엔드포인트(메트릭 전용 구성인 경우)와 비동기 메트릭 수집을 시작하도록 하여, 오래 걸릴 수 있는 메타데이터 로딩 단계에서도 메트릭을 관찰할 수 있습니다. #108402 (cwurm).
  • 이항 수학 함수에서 BFloat16을 지원합니다. #108442 (zhangyifan27).
  • 이제 전치 벡터 거리 함수 L2DistanceTransposed, cosineDistanceTransposed, dotProductTransposed는 Nullable(QBit) 컬럼에도 부분 비트 평면 읽기 최적화를 적용하여, 컬럼 전체가 아닌 요청된 비트 평면만 읽습니다. #109358 (alexey-milovidov).
  • BFloat16 배열에 대해 arraySum, arrayAvg, arrayProduct를 지원합니다. #109420 (alexey-milovidov).
  • L1Normalize, L2Normalize, LinfNormalize, LpNormalize 함수(및 해당 별칭)가 이제 튜플뿐만 아니라 배열에서도 동작합니다. 이는 L2Norm 및 거리 함수의 동작과 일관됩니다. #110052 (alexey-milovidov).
  • 풀링된 연결(pooled connection)에 대해 더 이상 사용할 때마다 ping을 보내지 않습니다. 이에 따라 재사용되는 모든 연결에 추가되던 Ping-Pong 왕복이 제거되어 분산 쿼리와 clickhouse-benchmark의 지연 시간이 줄어듭니다. 오래된(stale) 풀링 연결은 타임아웃이 0인 poll(왕복이 추가되지 않는 논블로킹 검사)로 감지하고 재연결하여 복구합니다. #110068 (alexey-milovidov).
  • 분산 인덱스 분석(distributed index analysis)에 사용되는 큰 파트 목록을 스칼라로 전송합니다(max_ast_elements/max_query_size로 인해 발생할 수 있는 실패를 방지하고 AST 파싱 오버헤드를 제거합니다). #110419 (azat).
  • 이제 Playground에서 클라우드 로고를 클릭하면 ClickHouse 웹사이트가 새 탭에서 열리므로, 쿼리 실행 중에 진행 상황을 잃지 않습니다. #110422 (williamhatcher).
  • auto_statistics_types의 기본값을 basic, uniq에서 basic, uniq_v2로 변경했습니다. #110878 (hanfei1991).
  • RWLockImpl::getLock() 재진입 어설션(RWLock is already locked in exclusive mode / Cannot acquire exclusive lock while RWLock is already locked)이 발생하면, 이제 오류 메시지에 현재 잠금을 보유한 다른 query_id와 요청한 query_id가 이미 보유한 잠금 개수가 표시되므로 이러한 잠금 순서 오류를 진단할 수 있습니다. #110971 (groeneai).
  • randomHadamardTransform은 이제 가장 큰 홀수 인수가 64 이하인 모든 벡터 길이(예: 임베딩 모델에서 흔히 쓰이는 3584 = 512 * 7)에 대해 길이를 보존하는 정확한 변환을 계산합니다. 이로써 기존에 지원하던 2^N, 2^k * {12, 20}, 2^k * 9 계열이 확장됩니다. 정확히 표현할 수 없는 길이에 대해 전체 변환을 수행하면, 이제 더 긴 벡터로 조용히 0을 채우는 대신 예외가 발생합니다. 임의 길이의 잘린 프로젝션을 계산하려면 output_dims를 전달하십시오. #111006 (alexey-milovidov).
  • HTTP 인터페이스에서 ACCESS_DENIED 예외가 발생하면 500 Internal Server Error 대신 HTTP 코드 403 Forbidden을 반환합니다. #111043 (Schum-io).
  • UTMToGeo는 이제 네 번째 인수로 정수 반구 플래그뿐만 아니라 geoToUTM이 반환하는 MGRS 위도 밴드 문자도 받습니다. 따라서 geoToUTM 결과를 UTMToGeo에 그대로 전달하여 왕복 변환할 수 있습니다. #111521 (alexey-milovidov).
  • MaterializedPostgreSQL은 이제 업데이트 시 변경되지 않은 PostgreSQL TOAST 값을 기본값으로 대체하지 않고 그대로 보존합니다. #111552 (OrpheusAgent).
  • 텍스트 인덱스 빌더가 임시 세그먼트를 플러시하는 시점을 제어하는 text_index_max_processed_tokens_before_flush 및 text_index_max_memory_usage_before_flush 설정을 추가했습니다. #111573 (rorylshanks).
  • 스냅샷별 커밋 순서 정렬을 건너뛰는 STREAM UNORDERED 수정자를 추가했습니다. #111794 (SmitaRKulkarni).
  • 이제 make_distributed_plan=1을 설정하면 아직 지원되지 않는 기능이 비활성화됩니다. #112463 (alesapin).
  • stdout이 tty인 경우 INTO OUTFILE 출력에 ANSI 이스케이프 시퀀스를 기록하지 않습니다. #113252 (azat).
  • allow_experimental_delta_kernel_rs의 이름을 allow_delta_kernel_rs로 변경했습니다. 기존 이름은 별칭으로 계속 사용할 수 있습니다. #113476 (kssenii).
  • Experimental 압축 코덱을 각각 개별적으로 활성화할 수 있도록 enable_alp_codec, enable_sz3_codec, enable_zxc_codec, enable_quantized_codec 설정을 추가했습니다. #113824 (rienath).
  • 스택 오버플로우가 발생하면 아무 보고 없이 종료되는 대신 이를 보고합니다. 이제 치명적 시그널 핸들러가 대체 시그널 스택에서 실행되므로, 오류가 발생한 스레드가 스택을 모두 소진한 경우에도 SIGSEGV, SIGABRT, SIGILL, SIGBUS, SIGSYS, SIGFPE, SIGTRAP에 대한 스택 트레이스가 생성됩니다. #113927 (groeneai).
  • 인스턴트 쿼리와 범위 쿼리에서 Prometheus HTTP API의 lookback_delta 매개변수를 지원합니다. #113971 (fallintoplace).
  • 이제 QueryRunner 테이블은 테이블 수명 내내 스레드를 점유하지 않고, 필요할 때 워커 스레드를 시작했다가 유휴 상태가 되면 해제합니다. #114522 (mstetsyuk).
  • 이번 변경으로 WHATIF 인덱스를 사용할 때 프로젝션 기반 기준값이 SQL 문을 실패 처리하는 대신 후보별로 not_applicable을 보고합니다. #114846 (yariks5s).
  • 동일한 표현식에 대한 여러 비교 조건으로 구성된 AND 체인을 최적화합니다. 모순되는 조건을 감지하고(예: a < 3 AND a > 5 → false), 중복 조건을 제거합니다(예: a = 3 AND a < 5 → a = 3). #99736 (wudidapaopao).

버그 수정

MergeTree, 복제 및 저장소 관련 수정 사항

  • MergeTree에서 ALTER TABLE ... RENAME COLUMN과 동시에 실행되는 OPTIMIZE TABLE ... FINAL(또는 임의의 백그라운드 머지) 간의 경쟁 조건으로 인해, 이름이 변경된 컬럼의 데이터가 아무런 경고 없이 기본값으로 대체될 수 있던 문제를 수정했습니다. 이제 두 작업이 진행되는 동안 currently_processing_in_background_mutex를 계속 보유하도록 하여, 새로운 인메모리 메타데이터를 게시하는 시점과 current_mutations_by_version에 이름 변경 뮤테이션을 등록하는 시점 사이의 경쟁 구간을 제거했습니다. #104822 (groeneai).
  • 프로젝션에서 GROUP BY, ORDER BY와 arrayJoin을 함께 사용할 때 잘못된 쿼리 결과가 반환되던 문제를 수정했습니다. #101775 (Onyx2406).
  • 잘못된 Azure 업로드 크기 설정(예: azure_min_upload_part_size = 0 또는 azure_max_blocks_in_multipart_upload = 0)은 이제 쓰기 경로 깊숙한 곳에서 내부 예외(second_size > 0)를 일으키는 대신, 초기 단계에서 명확한 오류와 함께 거부됩니다. 이는 쿼리 설정과 Azure 디스크 구성 모두에 적용됩니다. #103394 (statxc).
  • 그래뉼래리티 설정이 서로 호환되지 않는(하나는 적응형, 다른 하나는 비적응형) 두 MergeTree 테이블 간에 ALTER TABLE ... MOVE/REPLACE/ATTACH PARTITION을 실행하면 이제 LOGICAL_ERROR 대신 BAD_ARGUMENTS가 발생합니다. #103881 (groeneai).
  • KILL QUERY / KILL MUTATION / KILL PART_MOVE_TO_SHARD / KILL TRANSACTION의 WHERE 절에 행 단위 서브쿼리가 포함되어 있거나, max_block_size가 작아서 관련 system.* 테이블에 대한 내부 SELECT가 두 개 이상의 블록을 내보내는 경우 LOGICAL_ERROR “Expected one block from input stream”이 발생하던 문제를 수정했습니다. #104927 (groeneai).
  • 갱신 가능 구체화 뷰(MATERIALIZED VIEW ... REFRESH ...)에서 갱신 작업이 EXCHANGE TABLES를 통해 교체한 임시 내부 테이블이 서버의 max_table_size_to_drop보다 크면 삭제되지 않던 누수 문제를 수정했습니다. 그 결과 갱신할 때마다 이전 임시 내부 테이블은 정리되지 않은 채 새 임시 내부 테이블이 계속 생성되어, 디스크가 가득 찰 때까지 뷰의 데이터 디렉터리가 커졌습니다. 이제 갱신 작업의 내부 삭제는 max_table_size_to_drop 및 max_partition_size_to_drop을 우회합니다. 단, 사용자가 뷰 자체에 대해 직접 실행하는 DROP TABLE에는 이러한 안전장치가 그대로 적용됩니다. #105106 (groeneai).
  • 정렬 키에 SimpleAggregateFunction(또는 allow_suspicious_primary_key = 1에서만 허용되는 다른 타입)이 포함된 MergeTree 테이블에서, 정렬 키를 변경할 수 없는 ALTER 쿼리(설정, 주석, 코덱 변경, 키가 아닌 컬럼 추가 등)를 실행하면 예기치 않은 DATA_TYPE_CANNOT_BE_USED_IN_KEY 오류가 발생하던 문제를 수정했습니다. #105111 (groeneai).
  • 쿼리 타임아웃(timeout_overflow_mode = 'break'가 설정된 max_execution_time)으로 중단된 OPTIMIZE ... DRY RUN은 이제 rows_sources 관련 논리 오류(디버그 및 새니타이저 빌드에서는 서버가 비정상 종료됨) 대신 TIMEOUT_EXCEEDED를 반환합니다. #107114 (groeneai).
  • use_hive_partitioning=1로 Hive 파티셔닝된 파일을 읽을 때, Hive 파티션 컬럼을 함께 선택한 상태에서 WHERE/PREWHERE 절로 실제(가상이 아닌) 컬럼을 필터링하면 NOT_FOUND_COLUMN_IN_BLOCK이 발생하던 문제를 수정했습니다. #107505 (groeneai).
  • toStartOfDay, toStartOfISOYear, toDaysSinceYearZero, toRelativeSecondNum, toRelativeMinuteNum, toRelativeHourNum, toRelativeWeekNum, toRelativeDayNum, toMonthNumSinceEpoch, toYearNumSinceEpoch를 함수가 표현할 수 있는 범위를 벗어난 날짜(특히 1970-01-01 이전 날짜)가 포함된 Date32 키 컬럼에 적용하면, 프라이머리 키 및 파티션 프루닝이 잘못 수행되어 쿼리 결과가 틀리게 반환되던 문제를 수정했습니다. 이 함수들은 프라이머리 인덱스에 단조(monotonic) 함수로 보고되지만, 이전에는 이러한 인수에 대해 값이 순환(wrap around)되어 인덱스가 실제로 일치하는 행이 있는 그래뉼까지 프루닝할 수 있었습니다. 이제 이 함수들은 결과 타입의 경계값에서 포화(saturate)되어 Date32 전체 범위에서 단조성을 유지하므로 프루닝이 올바르게 동작합니다. #108018 (nihalzp).
  • CREATE TABLE dst AS src SETTINGS ...(및 명시적인 ENGINE 없이 ORDER BY/PARTITION BY를 사용하는 유사한 형태)가 원본 테이블의 엔진, 저장소 절(테이블 TTL 및 키 등), 설정을 아무런 경고 없이 누락하던 문제를 수정했습니다. 이제 엔진과 재정의되지 않은 저장소 절은 원본 테이블에서 상속되며, 지정한 설정은 원본 테이블의 설정에 덮어쓰는 방식으로 병합됩니다. #108085 (alexey-milovidov).
  • Windows 기반 파일 시스템(WSL, CIFS/SMB, Docker Desktop 바인드 마운트)에서 MergeTree 테이블에 대한 INSERT가 filesystem error: in rename: Permission denied 오류로 실패하던 문제를 수정했습니다. 이 문제는 파트 작성기(part writer)가 파트 디렉터리 이름을 변경하는 동안에도 파일 디스크립터를 열어 두어 발생했습니다. #108089 (alexey-milovidov).
  • 레거시 hypothesis 스킵 인덱스(ATTACH 호환성을 위해서만 남아 있는, 제거된 인덱스 유형)를 가진 채 ATTACH된 MergeTree 테이블이 작업 불능 상태에 빠지던 문제를 수정했습니다. 이전에는 이러한 테이블에서 경량 DELETE, OPTIMIZE, 일반 INSERT, 필터가 적용된 SELECT가 ILLEGAL_INDEX(“Index of type ‘hypothesis’ is no longer supported”) 오류로 실패했으며, DELETE 뮤테이션은 끝없이 재시도되었습니다. 이제 더 이상 쓰이지 않는 이 인덱스는 비활성 상태로 취급됩니다. 즉, 머지/뮤테이션 시에는 변경 없이 그대로 유지되고, 삽입 및 쿼리 계획 수립 시에는 무시되며, ALTER TABLE ... DROP INDEX로 여전히 삭제할 수 있습니다. #108217 (groeneai).
  • 병렬 레플리카 환경에서 MergeTree 테이블의 가상 컬럼을 조회할 때(asterisk_include_virtual_columns = 1로 SELECT *를 실행하는 경우 포함) NOT_FOUND_COLUMN_IN_BLOCK 오류(예: Column _part not found)가 발생하던 문제를 수정했습니다. #108451 (groeneai).
  • 프라이머리 키가 동일하지만 선언 방식이 다른 테이블(한쪽은 명시적 PRIMARY KEY, 다른 쪽은 ORDER BY로부터 암시적으로 지정)을 ATTACH PARTITION ... FROM이 거부하던 문제를 수정했습니다. #108590 (jordiori).
  • 이제 디스크로의 자동 스필링을 사용하는 조인을 포함해 지원되는 모든 해시 기반 조인 경로에서 join_any_take_last_row가 적용됩니다. #108936 (antaljanosbenjamin).
  • query_plan_optimize_lazy_final이 활성화된 상태에서 WHERE 필터의 일부가 (optimize_move_to_prewhere_if_final에 의해) PREWHERE로 이동될 때 NOT_FOUND_COLUMN_IN_BLOCK 오류가 발생하던 문제를 수정했습니다. 이제 지연 실행 FINAL 최적화는 prewhere에서 계산된 조건 컬럼을 저장소에 요청하지 않습니다. #109073 (groeneai).
  • 세션에 optimize_respect_aliases = 0이 설정된 상태에서 테이블 수준 ALIAS 컬럼에 대해 ALTER TABLE ... ADD PROJECTION을 실행하면 테이블을 사용할 수 없게 되던 문제(이후 INSERT가 UNKNOWN_IDENTIFIER, “Missing columns” 오류로 실패)를 수정했습니다. #109091 (groeneai).
  • 이전 분석기(allow_experimental_analyzer = 0)에서 다른 테이블과 조인된 Merge 엔진 테이블에 대해 ORDER BY ALL(또는 GROUP BY ALL)을 실행할 때 발생하던 널 포인터 assertion 실패(TreeRewriter::analyzeSelect의 px != 0, 디버그 및 sanitizer 빌드에서 서버가 중단됨)를 수정했습니다. #109139 (groeneai).
  • 상관관계가 서브쿼리 프로젝션에만 나타나고 상관관계가 없는 WHERE 절이 함께 사용될 때 상관 EXISTS 서브쿼리와 스칼라 서브쿼리가 잘못된 결과를 반환하던 문제(서브쿼리가 모든 행에서 false / NULL로 평가될 수 있음)를 수정했습니다. https://github.com/ClickHouse/ClickHouse/issues/105760 문제를 해결합니다. #109186 (novikd).
  • enable_block_number_column 또는 enable_block_offset_column 설정이 활성화된 상태에서 프로젝션이 있는 MergeTree 테이블을 머지하면 불필요한 _block_number/_block_offset 컬럼이 포함된 프로젝션 파트가 생성되던 버그를 수정했습니다. 이로 인해 머지된 프로젝션 파트가 프로젝션 정의 및 삽입으로 생성된 프로젝션 파트와 일치하지 않게 되어, CHECK TABLE과 OPTIMIZE ... DRY RUN이 해당 파트를 손상된 것(CORRUPTED_DATA)으로 보고했습니다. #109284 (groeneai).
  • 영구 가상 컬럼 _block_number 또는 _block_offset에 대한 암시적 min-max 인덱스(add_minmax_index_for_block_number_column / add_minmax_index_for_block_offset_column으로 활성화)가 있는 MergeTree 테이블에서 ALTER TABLE ... RENAME/ADD/MODIFY COLUMN을 실행할 때 발생하던 UNKNOWN_IDENTIFIER 오류를 수정했습니다. #109428 (groeneai).
  • Wide 파트에서 MATERIALIZED 컬럼에 대한 ALTER TABLE ... DROP COLUMN처럼 파트 전체를 재작성하는 뮤테이션을 실행한 후 데이터 파트에서 스킵 인덱스가 삭제되던 문제(또는 CHECK TABLE이 UNEXPECTED_FILE_IN_DATA_PART로 실패하던 문제)를 수정했습니다. #109616 (groeneai).
  • ALTER TABLE ... APPLY PATCHES로 경량 업데이트를 구체화한 후 스킵 인덱스(text, bloom_filter 등)와 프로젝션이 오래된 상태로 남던 문제를 수정했습니다. 이전에는 패치로 업데이트된 컬럼에 의존하는 인덱스 및 프로젝션 파일이 갱신되지 않아, 이를 사용하는 쿼리가 잘못된 결과를 반환할 수 있었습니다(예: hasToken이 업데이트된 행을 찾지 못하거나, 적용이 끝난 패치 파트가 제거된 후 프로젝션이 오래된 집계 결과를 반환). #109709 (groeneai).
  • _sample_factor 가상 컬럼을 참조하는 뮤테이션이 실행 도중 Unexpected const virtual column: _sample_factor 오류로 실패하여 뮤테이션이 멈춘 상태로 남던 문제를 수정했습니다. 이제 뮤테이션은 이 컬럼을 SAMPLE이 없는 쿼리가 반환하는 값과 동일한 1로 읽습니다. #109813 (groeneai).
  • GROUP BY GROUPING SETS가 포함된 쿼리(또는 이를 포함하는 스칼라 서브쿼리나 뮤테이션 서브쿼리)를 force_aggregation_in_order = 1로 실행할 때 발생하던 두 가지 오류를 수정했습니다. 하나는 이전 분석기(enable_analyzer = 0)에서 발생하던 Trying to get name of not a column: ExpressionList 오류이고, 다른 하나는 분석기 사용 시 enable_memory_bound_merging_of_aggregation_results = 1로 분산 쿼리를 실행할 때 발생하던 Memory bound merging of aggregated results is not supported for grouping sets. 오류입니다. #109862 (groeneai).
  • use_constant_folding_in_index_analysis와 관련된 세 가지 문제를 수정했습니다. 첫째, 테이블에 part_minmax_index_columns = 'with_block_number_offset'가 설정된 경우 일반 프로젝션을 사용하는 SELECT가 논리 오류 Invalid partition key size로 중단될 수 있던 문제, 둘째, PARTITION BY id % 200과 같은 모듈로 파티션 키에 대한 필터에서 잘못된 결과가 반환되던(행이 경고 없이 누락되던) 문제, 셋째, max_threads > 1 설정에서 sparseGrams 토크나이저를 사용하는 text 인덱스를 여러 파티션에 걸쳐 LIKE 프레디케이트로 쿼리할 때 크래시(데이터 레이스)가 발생하던 문제입니다. #109896 (groeneai).
  • LowCardinality(Nullable(...)) 컬럼에 minmax 스킵 인덱스를 생성한 경우 잘못된 결과가 반환되던 문제를 수정했습니다. 이전에는 저장소로 푸시다운된 WHERE/PREWHERE/HAVING ... IS NULL 프레디케이트가 모든 그래뉼을 프루닝하여, 컬럼에 NULL이 있는데도 0개의 행을 반환했습니다. #110061 (groeneai).
  • prefer_localhost_replica에 의해 로컬 레플리카가 선택될 때 Distributed 테이블에서 ORDER BY ... LIMIT 쿼리가 느리게 실행되던 문제를 수정했습니다. #110136 (EmeraldShift).
  • DELETE 또는 ALTER UPDATE 뮤테이션의 WHERE 조건 내 서브쿼리나 UPDATE 할당에서 집합 연산(UNION/UNION ALL/UNION DISTINCT/EXCEPT/INTERSECT)을 사용하면 예외(UNION mode UNION_DEFAULT must be normalized)가 발생하던 문제를 수정했습니다. #110196 (alexey-milovidov).
  • x IN (subquery)를 포함한 뮤테이션이 기본 키 분석 중 서브쿼리 집합을 생성하는 동안 서버 종료가 지연되고 KILL MUTATION이 응답하지 않던 문제를 수정했습니다. 이제 집합 생성이 즉시 취소됩니다. #110198 (alexey-milovidov).
  • KILL TRANSACTION과 트랜잭션 내에서 실행되는 ALTER TABLE ... UPDATE/DELETE 간의 레이스 컨디션을 수정했습니다. 뮤테이션이 트랜잭션에 등록된 후 테이블에 등록되기 전에 롤백이 발생하면 고아 뮤테이션 항목이 남았고, 이로 인해 백그라운드 작업에서 논리 오류(Cannot find transaction ... that has started mutation ...)가 발생하며 서버를 재시작할 때까지 해당 파트에 대한 이후의 모든 뮤테이션이 차단되었습니다. #110226 (tiandiwonder).
  • DataLakeCatalog(Iceberg/Glue) 데이터베이스에서 테이블 하나의 메타데이터라도 확인할 수 없으면 system.tables 쿼리 전체가 중단되거나 테이블이 경고 없이 누락되던 문제를 수정했습니다. 이제 database_datalake_require_metadata_access 설정과 관계없이 해당 테이블은 이름으로 계속 표시되며, 저장소 객체를 열어야 하는 컬럼(engine, total_rows 등)에는 기본값 또는 NULL이 표시됩니다. 손상된 테이블에 직접 액세스하면 이전과 같이 오류가 보고됩니다. #110242 (groeneai).
  • 조인 순서 카디널리티 추정 시 이제 모든 활성 파트가 아니라 파티션/기본 키 프루닝 후 남은 파트만을 기준으로 컬럼 통계를 조합합니다. 이전에는 작은 파티션으로 프루닝된 쿼리도 테이블 전체 통계를 기준으로 계획이 수립되어(행 수를 2500배 과대 추정해 해시 조인의 빌드 측이 뒤바뀌는 사례가 관찰됨), 오히려 통계를 비활성화해야 더 나은 계획이 생성되는 역설적인 상황이 발생했습니다. 또한 조인 순서 최적화기가 메모이제이션한 인덱스 분석 결과를 적용된 프로젝션으로 오인하여, JOIN 하위의 MergeTree 릴레이션에서 지연 FINAL이 경고 없이 비활성화되던 문제도 수정했습니다. #110283 (skuznetsov-clickhouse).
  • 그래뉼리티가 호환되지 않는(하나는 적응형, 다른 하나는 비적응형) 두 MergeTree 테이블 간에 ALTER TABLE ... MOVE/REPLACE PARTITION을 실행하면 이제 LOGICAL_ERROR 대신 BAD_ARGUMENTS가 발생합니다. 이는 사용자가 충분히 유발할 수 있는 상황이므로 내부 오류(디버그/새니타이저 빌드에서는 서버를 중단시킴)로 처리되어서는 안 됩니다. #110535 (groeneai).
  • WHERE에서 참조하는 컬럼에 ALTER TABLE ... UPDATE가 적용되어 <cond>와 일치하게 된 행을 TTL ... DELETE WHERE <cond>가 삭제하지 않던 문제를 수정했습니다. 이제 뮤테이션이 행 TTL을 다시 계산하므로, 새로 조건과 일치하게 된 만료 행이 아무 알림 없이 남아 있지 않고 삭제됩니다. #110648 (groeneai).
  • non_replicated_deduplication_window가 활성화된 파티션된 MergeTree 테이블에 INSERT할 때, 비동기 삽입 배치가 부분적으로만 중복 제거되면(일부 insert_deduplication_token은 중복이고 일부는 새로운 경우) LOGICAL_ERROR “Invalid partition key size: 0”가 발생하여 작업이 중단될 수 있던 문제를 수정했습니다. #110651 (groeneai).
  • 새 분석기에서 constant folding이 상수 Geometry 값의 타입을 아무 알림 없이 변경하던 문제를 수정했습니다. Geometry는 이름이 지정된 Variant로, 각 대안이 동일한 저장 레이아웃을 공유할 수 있습니다(LineString/Ring, MultiLineString/Polygon, 빈 값). 이 때문에 대안만 다른 두 폴딩된 상수가 하나로 합쳐져, 예를 들어 상수 MULTIPOLYGON EMPTY가 LINESTRING()으로 반환되었습니다. #110709 (groeneai).
  • read-in-order 쿼리에서 distinct-in-order 또는 aggregation-in-order가 ORDER BY로 read-in-order virtual row를 설정한 정렬 키 접두사보다 더 긴 접두사까지 읽기를 확장할 때 잘못된 결과(머지 순서 오류)가 발생하던 문제를 수정했습니다. virtual row의 추가 정렬 컬럼이 기본값으로 채워져 MergingSortedTransform의 순서가 어긋날 수 있었습니다(debug/sanitizer 빌드에서는 LOGICAL_ERROR로 중단됨). #110725 (groeneai).
  • interserver-secret 클러스터에서 병렬 레플리카 읽기 및 분산 읽기를 수행할 때 쿼리의 활성 역할(SET ROLE / role=)이 원격 노드로 전달되도록 했습니다. 이전에는 사용자의 기본 역할이 대신 사용되어 row policy가 initiator와 다르게 평가되었습니다. #110867 (evillique).
  • ReplicatedMergeTree 테이블에 대한 주석 전용 또는 설정 전용 ALTER가 동시에 실행된 ALTER ... ADD COLUMN으로 추가된 컬럼을 아무 알림 없이 누락시켜, 레플리카가 오래된 테이블 structure에 머무를 수 있던 드문 경쟁 조건을 수정했습니다. #111029 (tiandiwonder).
  • Distributed 테이블을 감싸는 Merge 테이블에서 집계가 포함된 GROUP BY를 실행할 때, 그룹화 키가 컬럼에 대한 함수이고 집계 함수가 같은 컬럼을 읽으면(예: SELECT toString(g), min(g) FROM merge_over_distributed GROUP BY toString(g)) NUMBER_OF_COLUMNS_DOESNT_MATCH 오류가 발생하던 문제를 수정했습니다. #111334 (groeneai).
  • 왼쪽 키는 Nullable이지만 저장소 키는 그렇지 않을 때, Join 엔진 테이블(StorageJoin)에 USING을 사용한 FULL JOIN이 잘못된 결과를 반환하던 문제를 수정했습니다. 키가 NULL이고 일치하는 행이 없는 왼쪽 행에서 NULL 대신 0이 반환되었습니다. #111371 (groeneai).
  • 이제 테이블의 fsync_part_directory 설정이 활성화되어 있으면 ALTER TABLE ... DETACH PARTITION/PART가 detached/ 아래에 생성하는 복제본(파트 하위 트리 및 디스크 루트까지 이어지는 디렉터리 체인)을 fsync합니다. 이는 Full(디렉터리) 및 Packed 파트 저장 방식 모두에 적용됩니다. 이전에는 활성 집합에서 행을 제거하는 빈 커버링 파트는 fsync되었지만 복제본은 전혀 fsync되지 않았기 때문에, 확인 응답 직후 전원이 끊기면 btrfs에서 분리된 데이터가 손실될 수 있었습니다(동기화되지 않은 복제본 디렉터리 엔트리가 롤백되어 detached/가 비게 되고 ATTACH할 대상이 남지 않음). 이 동작은 기존 fsync_part_directory 설정으로 제어되며, 기본 동작은 변경되지 않습니다. #111426 (groeneai).
  • 스키마를 저장소에서 추론하는 경우(예: SELECT NULL을 수행하는 뷰를 기반으로 컬럼 없이 정의한 remote()/Remote/Distributed 테이블) 이제 Nullable(Nothing) 컬럼(또는 테이블에서 허용되지 않는 다른 유형의 컬럼)을 CREATE TABLE 시점에 거부합니다. 이전에는 이러한 메타데이터가 그대로 저장되어, 다음 서버 재시작 시 로드에 실패하고 관련 없는 테이블의 로드까지 막았습니다. #111487 (groeneai).
  • 병렬 레플리카로 읽을 때 이니시에이터에서 프로젝션 최적화(정확한 개수 계산, minmax-count, 또는 범위를 선택하지 않는 저장된 집계/일반 프로젝션)만으로 쿼리 결과가 모두 산출되는 경우, 서버를 중단시킬 수 있던 LOGICAL_ERROR(Got read request from replica N for unknown stream ...)를 수정했습니다. #111689 (groeneai).
  • DeltaLake 파티션 INSERT(allow_experimental_delta_lake_writes=1)가 경로 문자를 포함한 파티션 값을 손상시키고 NULL을 거부하던 문제를 수정했습니다. a/b 같은 값은 아무 경고 없이 a로 커밋되었고, %가 포함된 값은 다시 읽을 수 없는 데이터 파일을 생성했으며, NULL 파티션 값은 NOT_IMPLEMENTED 오류로 실패했습니다. 이제 파티션 값은 퍼센트 인코딩되어 하나의 경로 세그먼트로 기록되고, 실제 값은 경로에서 다시 파싱하지 않고 partitionValues에 저장되며, NULL(또는 빈 문자열) 파티션 값은 partitionValues 항목을 null로 하여 __HIVE_DEFAULT_PARTITION__으로 기록됩니다. #111793 (groeneai).
  • enable_parallel_blocks_marshalling(기본적으로 활성화됨)이 설정된 샤드에서 분산 쿼리를 실행할 때 발생하던 Expected UInt64 column for __grouping_set, got BLOB 및 ColumnBLOB should be converted to a regular column before usage 논리 오류를 수정했습니다. 이 오류는 예를 들어 로컬 레플리카가 있는 클러스터에서 GROUP BY GROUPING SETS를 사용하거나, 로컬 테이블과 분산 테이블에 걸친 Merge 테이블을 읽을 때 발생했습니다. 이제 블록이 동일 프로세스 내에서 소비되는 플랜에는 BlocksMarshallingStep을 추가하지 않습니다. #111997 (groeneai).
  • 통계가 있는 컬럼의 유형을 메타데이터만 변경하는 ALTER MODIFY COLUMN(예: Enum8에서 Int8로, 또는 DateTime에서 UInt32로)으로 바꾼 테이블에서 MergeTree 뮤테이션을 수행할 때 발생하던 LOGICAL_ERROR(Type mismatch when building statistics for column)를 수정했습니다. 이제 뮤테이션은 실제로 다시 쓰는 컬럼의 통계만 재계산하고 나머지는 그대로 유지합니다. 또한 MATERIALIZE COLUMN, MATERIALIZED 컬럼이 의존하는 컬럼에 대한 UPDATE, 또는 CLEAR COLUMN으로 다시 쓰인 컬럼은 이전 통계를 그대로 유지하지 않고 재계산합니다. #112009 (groeneai).
  • 쿼리가 intDiv(constant, key) 또는 divide(constant, key)로 필터링할 때 오류 없이 행이 누락되는 문제를 수정했습니다. 상수를 키 컬럼으로 나누면 기본 키(primary key) 및 파티션 분석이 단조성(monotonicity)의 방향을 잘못 판단하여, 조건에 맞는 그래뉼이 제외되고 쿼리가 오류 없이 더 적은 행을 반환했습니다. 또한 최상위 비트가 설정된 부호 없는 상수를 피제수로 사용하는 intDiv를 수정했고, Decimal 피연산자 때문에 나눗셈이 decimal의 고유 너비로 계산되는 경우에는 단조성을 보장하지 않도록 했으며, IPv4/IPv6 상수를 키 컬럼으로 나누는 유효한 쿼리에서 키 분석이 Cannot compare DB::IPv4 with long 오류를 발생시키지 않도록 했습니다. #112156 (groeneai).
  • SELECT 본문에서 INTERSECT/EXCEPT를 사용하거나 UNION DISTINCT와 UNION ALL을 혼합한 UNION 체인을 사용하는 매개변수화된 뷰(parameterized view)가 일반 뷰로 분류되는 문제를 수정했습니다. 이러한 뷰는 정상적으로 생성되지만 메타데이터를 다시 읽을 수 없었습니다. 로드 시 Invalid storage definition in metadata file 오류가 발생하여 뷰를 영구적으로 로드할 수 없었고, 디버그 또는 sanitizer 빌드 서버는 시작 중에 중단되었습니다. 또한 system.tables.parameterized_view_parameters에도 해당 뷰의 매개변수가 표시되지 않았습니다. #112211 (groeneai).
  • 쿼리가 geohashesInBox를 평가하는 동안 max_execution_time과 KILL QUERY가 무시되는 문제를 수정했습니다. 이러한 쿼리는 블록의 모든 행을 확장한 뒤에야 중단될 수 있었기 때문에 취소가 몇 분이 지나서야 적용되었습니다. 이제 함수가 행을 순회하면서 쿼리의 시간 제한을 확인합니다. 정렬 키, 스킵 인덱스, PARTITION BY처럼 영구 저장되는 테이블 표현식 내부의 평가는 이번 수정에 포함되지 않으며 별도로 추적됩니다. #112273 (groeneai).
  • 다른 Merge 테이블 또는 컬럼 유형이 다른 materialized view를 기반으로 하는 Merge 테이블에서 PREWHERE를 사용할 때 발생하던 논리 오류(logical error)를 수정했습니다. 또한 원격 서버에서 데이터를 읽는 테이블(분산 테이블 또는 이를 감싸는 테이블)에서 행 정책(row policy)이 경고 없이 무시되어, 정책으로 숨겨야 할 행이 노출될 수 있던 문제를 수정했습니다. 이제 이러한 쿼리는 ILLEGAL_PREWHERE 오류와 함께 거부됩니다. 이 경우 각 원격 서버의 기본 로컬 테이블에 정책을 정의하십시오. 단, serialize_query_plan = 1로 전송되는 읽기에는 여전히 이 정책이 적용되지 않으며, 이는 기존부터 있던 별도의 버그입니다. #112326 (PedroTadim).
  • ALTER TABLE ... MODIFY COLUMN으로 유형을 변경했으나 뮤테이션이 실행되지 않은 경우(예: KILL MUTATION으로 제거된 경우) 오래된 보조(스킵) 인덱스를 읽는 문제를 수정했습니다. 디스크의 그래뉼은 이전 유형으로 기록되었는데 새 유형으로 디코딩되어 LOGICAL_ERROR가 발생하거나, 수 엑사바이트 규모의 메모리 할당을 요청하거나, 오류 없이 잘못된 결과를 반환했습니다. 또한 저장된 바이트는 모두 그대로이지만 의미가 바뀌어 뮤테이션이 아예 생성되지 않는 표현식의 인덱스가 잘못된 결과를 반환하는 문제도 수정했습니다. DateTime 시간대만 변경하거나 UInt8에서 Bool로 바꾸는 것처럼 사용자 정의 유형 이름만 변경하는 MODIFY COLUMN이 이에 해당합니다. 이제 영향을 받는 파트에서는 이러한 인덱스를 건너뜁니다. #112484 (groeneai).
  • 클러스터 전체를 대상으로 집계하는 쿼리를 serialize_query_plan = 1 및 계획 기반 병렬 레플리카(plan-based parallel replicas)로 실행할 때, 머지 단계가 파이프라인을 0개의 스트림으로 재조정하여 발생하던 LOGICAL_ERROR(Cannot add transform Resize to Pipes because it has no outputs)를 수정했습니다. #112506 (groeneai).
  • ReplicatedMergeTree 레플리카가 자신의 대기 중인 ALTER ... ADD COLUMN을 적용하기 전에 다른 레플리카에서 가져온 파트를 뮤테이션할 때 발생하던 LOGICAL_ERROR(“Part … contains column … that is absent in table …”)를 수정했습니다. 이제 이러한 뮤테이션은 메타데이터 변경이 적용될 때까지 연기됩니다. #112510 (groeneai).
  • ORDER BY가 디스크로 스필되는 쿼리에서 읽기 카운터(read_rows, read_bytes, ProfileEvents['SelectedRows'], ProfileEvents['SelectedBytes'])와 READ_ROWS 및 READ_BYTES 쿼터가 과다 집계되던 문제를 수정했습니다. 외부 정렬 임시 파일에서 다시 읽은 행이 소스 읽기로 중복 집계되어, 스필이 발생한 쿼리는 실제보다 많이 읽은 것으로 보고되었고 쿼터를 초과하지 않았는데도 QUOTA_EXCEEDED로 거부될 수 있었습니다. #112645 (groeneai).
  • 디스크로 스필되는 JOIN의 결과 크기를 ProfileEvents['JoinResultRowCount']가 실제보다 적게 보고하던 문제를 수정했습니다. 지연된 버킷에서 출력된 행이 JoinDelayedJoinedTransformRowCount에만 집계되고 전체 합계에서는 누락되었습니다. 쿼리 결과 자체는 항상 정확했으며, 프로필 이벤트 값만 잘못되었습니다. #112673 (groeneai).
  • 레플리카와 연결을 수립하는 중인 분산 쿼리에서 max_execution_time과 KILL QUERY가 아무런 알림 없이 적용되지 않던 문제를 수정했습니다. 이제 이러한 쿼리는 남은 레플리카와 재시도를 모두 거치지 않고 다음 연결 시도 시점에 중지됩니다. #112689 (groeneai).
  • 완료되지 않은 RENAME COLUMN alter-뮤테이션이 진행 중인데도 MergeTree 테이블에 ALTER가 적용되던 문제를 수정했습니다. 이로 인해 저장소 메타데이터가 호환되지 않는 방식으로 갱신되어 이후 뮤테이션이 완전히 막힐 수 있었습니다. #112783 (Michicosun).
  • Distributed 테이블을 기반으로 하는 Merge 테이블에서 읽을 때 ORDER BY 결과가 잘못되던 문제를 수정했습니다. 행이 올바른 순서로 반환되지 않을 수 있었고, LIMIT을 사용하면 결과에 포함되어야 할 행이 누락될 수 있었습니다. #112931 (alexey-milovidov).
  • share_nested_offsets가 활성화된(기본값) 테이블에서 파일 시스템 읽기 프리페치가 활성화되어 있고, 삭제 후 다시 추가된 서브컬럼과 함께 Nested 컬럼을 읽을 때 잘못된 결과가 반환되던 문제를 수정했습니다. 이러한 쿼리는 ALTER의 영향을 전혀 받지 않았고 물리적으로도 존재하는 컬럼에 대해 기본값을 반환할 수 있었습니다. 객체 스토리지에서는 remote_filesystem_read_prefetch의 기본값이 1이므로 별도의 설정 변경 없이도 발생하며, 로컬 디스크에서는 local_filesystem_read_prefetch = 1일 때 발생합니다. 읽기 범위가 여러 블록에 걸쳐 있을 때 이러한 읽기 결과를 손상시키는, 프리페치와 무관한 별도의 결함은 여전히 남아 있으며 이번 수정에서는 다루지 않습니다. #112997 (groeneai).
  • PARTITION BY를 사용하는 윈도 함수나 join_algorithm = 'parallel_full_sorting_merge'를 사용하는 조인처럼 데이터를 파티션별로 분산하는 쿼리에서, 블록이 일부만 분배된 상태에서 한 샤드의 다운스트림이 종료되면 Pipeline stuck 논리 오류가 발생하던 문제를 수정했습니다. #113190 (groeneai).
  • ReplicatedMergeTree에서 alter_sync = 2로 실행한 ALTER, OPTIMIZE, TRUNCATE 및 파티션 조작 SQL 문이 다른 레플리카를 기다리는 동안 테이블 종료가 시작되면(예: 동시에 실행된 DROP DATABASE ... SYNC로 인해) 응답 없이 멈추던 문제를 수정했습니다. 이제 이러한 SQL 문은 UNFINISHED로 실패하며, max_execution_time과 KILL QUERY도 정상적으로 적용됩니다. #113228 (groeneai).
  • read_in_order_use_virtual_row가 활성화된 상태에서 MergeTree 순차 읽기(read-in-order) 쿼리가 WITH FILL ... INTERPOLATE와 IN 또는 has 필터를 함께 사용하면 Cannot insert element into Set(NOT_IMPLEMENTED) 오류가 발생하던 문제를 수정했습니다. #113264 (groeneai).
  • inject_random_order_for_select_without_order_by 설정이 활성화된 상태에서 집계 쿼리가 Distributed 자식 테이블을 포함하는 Merge 테이블을 읽을 때 발생하던 논리 오류(예외) Chunk info was not set for chunk in MergingAggregatedTransform를 수정했습니다. 이제 중간 단계까지만 계획되는 쿼리에는 무작위 ORDER BY rand() 래퍼가 주입되지 않습니다. #113266 (alexey-milovidov).
  • MergeTree 테이블에 시간 표현식이 동일하고 WHERE 조건만 다른 TTL ... DELETE WHERE 규칙이 2개 이상 있을 때 행이 전혀 삭제되지 않던 문제를 수정했습니다. TTL 삭제 머지 후 파트의 rows_where_ttl_info가 0으로 초기화되어 해당 파트에 대한 TTL 머지가 더 이상 예약되지 않았고, 그 결과 만료된 행이 오류나 로그 메시지 없이 무기한 남아 있었습니다. #113384 (groeneai).
  • 정렬 키, 스킵 인덱스, PARTITION BY 키 등 테이블 메타데이터에 저장된 표현식 안에서 쿼리가 geohashesInBox, arrayFold, sleep, base58Decode, h3PolygonToCells 또는 h3PolygonToCellsWithContainment를 평가하는 동안 max_execution_time과 KILL QUERY가 무시되던 문제를 수정했습니다. #113456 (groeneai).
  • 자식 테이블이 2개 이상인 Merge 테이블이 외부 쿼리에서 참조하는 머티리얼라이즈된 CTE를 읽을 때 발생하던 LOGICAL_ERROR(Reading from materialized CTE '...' before its materialization completed - DelayedPortsProcessor gate is missing in the query plan)를 수정했습니다. #113558 (alexey-milovidov).
  • 자식 테이블이 여러 개인 Merge 테이블에 대해 단일 컬럼 PREWHERE와 별도의 WHERE를 함께 사용한 EXPLAIN ANALYZE에서 발생하던 Logical error: 'Required output position N is out of range for pass-through inputs'를 수정했습니다. #113725 (groeneai).
  • 컬럼 타입이 기반 저장소와 다른 뷰(예: engine이 Nullable(String)인 information_schema.tables와, 기반이 되며 해당 컬럼이 String인 system.tables)에 대한 필터가 저장소로 푸시다운될 때 발생하던 논리 오류(Unexpected return type)를 수정했습니다. #113984 (alexey-milovidov).
  • 조건절에 IN (subquery)가 포함된 뮤테이션이 서브쿼리의 Set이 아직 생성되는 도중에 KILL MUTATION이나 DETACH DATABASE 등으로 취소될 때 발생하던 Not-ready Set is passed as the second argument for function 'in' 오류를 수정했습니다. #114463 (groeneai).
  • 정렬 키, 기본 키 또는 파티션 키에 사용되는 컬럼에 대해 ALTER TABLE ... DROP COLUMN을 실행하면 이제 ALTER TABLE ... CLEAR COLUMN과 마찬가지로 설명과 함께 ALTER_OF_COLUMN_IS_FORBIDDEN 오류로 실패합니다. 이전에는 키 표현식을 다시 계산하는 과정에서 발생한, 원인을 파악하기 어려운 UNKNOWN_IDENTIFIER: Missing columns 오류로 실패했습니다. 그룹의 컬럼이 키에 사용되는 상태에서 공통 접두사로 Nested 그룹 전체를 삭제하거나 초기화하는 경우에도 동일하게 적용됩니다. 이전에는 이로 인해 그룹의 데이터가 아무 알림 없이 손상되거나 끝나지 않는 뮤테이션이 남을 수 있었습니다. 또한 TTL 표현식에서만 사용되는 컬럼을 삭제하면 이제 어떤 TTL 표현식이 영향을 받는지 알려 줍니다. #114468 (m7kss1).
  • 하나의 ALTER에서 이름 변경, 삭제 후 다시 추가된 컬럼이 뮤테이션이 아직 대기 중인 동안 자체 기본값 대신 삭제된 컬럼의 값을 반환하던 문제를 수정했습니다. #114601 (tiandiwonder).
  • 기본 테이블(underlying table)이 상위 컬럼을 ALIAS로 선언한 경우 Merge 테이블을 통해 서브컬럼(.size0, .null, 튜플 요소, String.size)을 읽을 때 발생하던 문제를 수정했습니다. 이러한 읽기는 해당 타입의 기본값을 반환했으며, 같은 쿼리에서 상위 컬럼도 함께 선택하면 관련 없는 컬럼의 값이 반환될 수 있었습니다. #114673 (groeneai).
  • 폴리곤 인수가 유효하지 않은 상수 리터럴이고 validate_polygons = 0인 경우, MergeTree 프라이머리 키에 대해 pointInPolygon으로 필터링한 SELECT 결과에서 행이 누락되던 문제를 수정했습니다. 프라이머리 키 분석이 검사하지 않은 폴리곤을 기반으로 그래뉼 프루닝(granule pruning)을 수행하면서, 조건에 맞는 행이 포함된 그래뉼까지 제외했습니다. #114710 (groeneai).
  • ALTER TABLE ... MATERIALIZE INDEX, MATERIALIZE STATISTICS, MATERIALIZE PROJECTION을 포맷팅할 때 IF EXISTS 절이 누락되어, 포맷팅된 쿼리가 파싱된 쿼리와 달라지던 문제를 수정했습니다. 또한 SQL 파서가 생성할 수 없고 포맷팅하면 다른 명령으로 바뀌던 4가지 ALTER ... STATISTICS AST JSON 페이로드를 거부하도록 했습니다. #115099 (groeneai).
  • 집계 도중 딕셔너리가 커지는 LowCardinality(String) 키로 집계하거나 조인할 때 캐시된 딕셔너리 해시를 범위 밖에서 읽던 문제를 수정했습니다. 이 문제는 TTL ... GROUP BY에서 발생할 수 있었으며, 잘못된 해시가 산출되거나 새니타이저 빌드에서 heap-buffer-overflow가 보고될 수 있었습니다. #115604 (groeneai).
  • 이제 CREATE TABLE 및 ALTER TABLE에서 파티션 키에 사용되는 컬럼에 SZ3와 같은 손실 압축 코덱을 지정하면 거부됩니다. #115626 (groeneai).
  • 대상이 매개변수화된 뷰(parameterized view)인 Alias 테이블과 일치하는 Merge 테이블을 통해 읽을 때 더 이상 LOGICAL_ERROR: Table has no columns.(디버그 및 새니타이저 빌드에서는 서버가 중단됨)가 발생하지 않습니다. 이러한 테이블은 이제 매개변수화된 뷰 자체와 동일한 STORAGE_REQUIRES_PARAMETER 오류를 보고합니다. 컬럼을 제공할 수 없는 그 밖의 일치 테이블은 이제 내부 오류 대신 UNSUPPORTED_METHOD를 보고합니다. #115896 (groeneai).
  • 표현식이 _sample_factor를 참조하는 대기 중인 뮤테이션의 즉석 프리뷰 문제를 수정했습니다. apply_mutations_on_fly = 1이고 SAMPLE 절이 있으면, 표현식이 백그라운드 머티리얼라이즈 시 저장되는 값 대신 읽기 쿼리의 샘플 계수로 평가되었습니다. 이로 인해 프리뷰된 행이 최종 구체화 결과와 일치하지 않았으며, 대기 중인 ALTER TABLE t DELETE WHERE _sample_factor > 1 때문에 SAMPLE 읽기가 행을 전혀 반환하지 않을 수도 있었습니다. 쿼리 자체의 _sample_factor 컬럼은 변경되지 않습니다. #115906 (groeneai).
  • 형식 버전 V3의 통계 파일을 이제 ILLEGAL_STATISTICS로 거부하지 않고 읽습니다. 이러한 파일은 특정 짧은 기간의 master 빌드에서만 생성되었지만, 이를 포함한 파트는 전혀 읽을 수 없었고, 읽기 전용 디스크에서는 ALTER TABLE ... MATERIALIZE STATISTICS로 다시 생성할 수도 없었습니다. #116030 (alexey-milovidov).
  • SELECT ... FROM t STREAM ... ORDER BY ... LIMIT n 쿼리가 PROJECTION이 있는 테이블을 읽을 때 Invalid number of columns in chunk pushed to OutputPort(LOGICAL_ERROR)가 발생하던 문제를 수정했습니다. 이제 STREAM 읽기에는 지연 머티리얼라이즈(lazy materialization)가 적용되지 않습니다. #116187 (groeneai).
  • 복제 데이터베이스에서는 ALTER TABLE ATTACH PARTITION FROM을 복제하지 않습니다. #94835 (MikhailBurdukov).
  • 롤백된 트랜잭션 MergeTree 파트가 커밋된 파트와 교차하는 경우, 테이블 시작 과정에서 서버가 중단되거나(새니타이저 빌드) 데이터가 아무런 알림 없이 손실되던 문제를 수정했습니다. 이제 PartLoadingTree::add는 교차하는 두 파트 중 롤백된 파트를 올바르게 식별하여 제거하고, 부모를 잃은 하위 파트를 커밋된 파트 아래에 올바른 순서로 다시 연결합니다. #100992 (tuanpach).
  • MergeTree 테이블의 Array(LowCardinality(String)) 컬럼에서 indexOfAssumeSorted가 잘못된 결과를 반환하던 문제를 수정했습니다. #101771 (Onyx2406).
  • Iceberg 메타데이터의 동시 업데이트나 DeltaLake 테이블에 대한 merge 읽기처럼, 고정된 datalake_table_state 없이 읽기 파이프라인에 도달할 수 있는 경로로 Iceberg 또는 DeltaLake 데이터 레이크 테이블을 읽을 때 발생하던 LOGICAL_ERROR 예외를 수정했습니다. #102033 (groeneai).
  • Time 유형의 파티션 키를 사용하는 테이블에서 OPTIMIZE TABLE ... PARTITION ...(및 convertFieldToTypeImpl을 통해 파티션 값을 해석하는 기타 쿼리) 실행 시 Logical error: Parsed partition value: ... doesn't match partition value for an existing part with the same partition ID: ... 오류가 발생하던 문제를 수정했습니다. #106202 (groeneai).
  • 경량한 삭제 이후 프로젝션 파트가 남지 않는 경우(프로젝션이 출력 행 0개로 재구성되거나 삭제되는 경우, lightweight_mutation_projection_mode = 'rebuild'/'drop') 데이터 파트에 손상된 프로젝션이 있는 것으로 잘못 표시되던 문제를 수정했습니다. 기존에는 이 손상 상태 때문에 해당 파트에 대한 쿼리에서 프로젝션 최적화가 비활성화되었습니다. #106273 (tiandiwonder).
  • system.warnings의 메모리/CPU/뮤테이션 과부하 경고가 비동기 메트릭 사이클보다 한 사이클씩 늦게 반영되고 첫 번째 사이클에서는 아예 표시되지 않던 문제를 수정했습니다. #108035 (alexey-milovidov).
  • 실험적 설정 make_distributed_plan = 1을 사용한 상태에서 Distributed 테이블이나 뷰를 기반으로 하는 Merge 테이블을 쿼리할 때 발생하던 LOGICAL_ERROR 예외(ScatterExchangeStep should have one source shard, got 8)와 행 중복 문제를 수정했습니다. #108401 (groeneai).
  • Nullable(Tuple(...)) 컬럼 내 널을 허용하지 않는 LowCardinality 요소를 서브컬럼으로(예: 정렬 키로) 사용할 때, 머지 도중 서버가 중단되거나(Sort order of blocks violated) 잘못된 읽기가 발생하던 문제를 수정했습니다. #108679 (groeneai).
  • 계정 키가 유효한 Base64가 아닐 때 azureBlobStorage()(및 관련 Azure 테이블 함수/저장소)를 통해 벤더링된 Azure SDK의 Base64Decode에서 크래시가 발생하던 문제를 수정했습니다. >= 0x80인 바이트는 디코드 테이블의 범위를 벗어난 읽기를 일으켰고, 유효하지 않은 바이트는 모두 음수 값에 대한 정의되지 않은 왼쪽 시프트(새니타이저 환경에서 중단)를 일으켰습니다. 이제 유효하지 않은 키는 정상적으로 거부됩니다. #108716 (groeneai).
  • 이전에 수행된 동일한 작업이 중단되어(예: 트랜잭션 롤백 또는 크래시) 오래된 tmp_empty_<part> 디렉터리가 남아 있는 상태에서 MergeTree 테이블에 DROP/DETACH/MOVE/REPLACE PARTITION을 실행하면, 디버그 및 새니타이저 빌드에서 서버가 중단될 수 있는 LOGICAL_ERROR(“New empty part is about to materialize but the directory already exist”)가 발생하던 문제를 수정했습니다. 이제 실패하는 대신 오래된 디렉터리를 회수합니다. #108879 (groeneai).
  • 와이드 파트(wide part)에서 컬럼의 TTL이 만료된 후 프로젝션이 컬럼의 DDL DEFAULT(예: -1) 대신 타입 기본값(예: 0)을 반환하던 문제를 수정했습니다. #109013 (tiandiwonder).
  • 사용자 정의 disk 설정(SETTINGS disk = disk(...))으로 생성된 MergeTree 테이블에서 ALTER 쿼리가 실패하던 문제를 수정했습니다. #109199 (Michicosun).
  • Merge 테이블을 통해 MaterializedPostgreSQL 데이터베이스의 테이블을 읽을 때 오래된 행과 삭제된 행이 나타나던 문제를 수정했습니다. #109339 (vdimir).
  • 값이 Int32 범위를 벗어나는 BIGINT 컬럼으로 파티셔닝된 Paimon 테이블을 읽지 못하던 문제를 수정했습니다. 이러한 파티션 값이 잘리면서(예: 9223372036854775807이 -1로 변환됨) 잘못된 파티션 경로가 생성되어 파일 시스템 오류가 발생했습니다. #109510 (groeneai).
  • 하위 테이블에 기존 컬럼 하나만으로 필터를 구성한 row policy(예: CREATE ROW POLICY ... USING flag)가 있는 Merge 테이블을 읽을 때 발생하던 논리 오류(“Cannot determine row level filter; 0 columns deleted, 0 columns added”)를 수정했습니다. #109843 (groeneai).
  • IcebergLocal이 저장소 유형을 Azure로 보고하던 문제를 수정했습니다. #109872 (PedroTadim).
  • 이제 CHECK TABLE은 메타데이터 로드에 실패한 프로젝션 파트에 대해 오해를 일으키는 Columns doesn't match ... Expected: 0 columns 오류 대신 실제 손상 내용을 보고합니다. #110262 (Algunenano).
  • 남아 있는 txn_version.txt.tmp 파일의 디스크 수준 메타데이터가 손상된 경우 객체 스토리지 디스크의 MergeTree 테이블 때문에 서버 시작이 실패하던 문제를 수정했습니다. #110519 (alexey-milovidov).
  • _part_offset 또는 커밋 순서 프로젝션이 있는 MergeTree 테이블에서 allow_part_offset_column_in_projections 또는 allow_commit_order_projection을 비활성화한 뒤 테이블을 분리(detach)하거나 서버를 재시작하면 테이블을 영구적으로 ATTACH할 수 없게 되던 문제를 수정했습니다. 이 두 설정은 CREATE 시점에만 확인하는 조건이므로 이제 ATTACH 시에는 다시 검사하지 않습니다. #110570 (groeneai).
  • ReplicatedMergeTree에서 두 개의 파티션 작업(예: 두 개의 MOVE PARTITION / REPLACE PARTITION 쿼리, 또는 백그라운드 DROP_RANGE와 경합하는 쿼리 하나)이 겹치는 범위에 대한 백그라운드 파트 검사를 동시에 취소할 때 서버를 중단시킬 수 있던 드문 LOGICAL_ERROR(“Unexpected number of parts to remove from parts_queue”)를 수정했습니다. #110738 (groeneai).
  • Quantized(...) 코덱을 사용하는 컬럼이 풀링 가능한 직렬화 내부에 중첩된 경우(예: 이름이 같은 컬럼의 타입이 소스마다 달라 Variant로 병합되는 Merge 테이블) 발생할 수 있던 Hash is not set for serialization 논리 오류를 수정했습니다. #110776 (groeneai).
  • 비정상적으로 큰 max_streams_for_merge_tree_reading 값(UInt64 최댓값에 가까운 값)과 allow_asynchronous_read_from_io_pool_for_merge_tree = 1을 함께 사용하여 MergeTree 테이블을 읽을 때 발생하던 std::length_error(LOGICAL_ERROR)를 수정했습니다. 이제 이 설정값은 max_threads와 동일한 상한으로 제한됩니다. #110936 (groeneai).
  • 단일 컬럼 MergeTree 테이블의 유일한 컬럼에 완전히 만료되는 컬럼 TTL이 설정된 경우(min_bytes_for_wide_part = 1) 머지 중에 발생하던 논리 오류 Cannot calculate columns sizes when columns or checksums are not initialized를 수정했습니다. #111169 (groeneai).
  • min_rows_to_fsync_after_merge / min_compressed_bytes_to_fsync_after_merge / fsync_part_directory가 설정된 경우, 머지되었거나 구체화된 파트의 텍스트 인덱스 파일도 fsync하도록 했습니다. 이전에는 파트 내에서 이 파일들만 동기화되지 않았기 때문에, 머지 직후 전원이 차단되면 커밋은 되었지만 손상된 파트가 남아 데이터 손실이 발생할 수 있었습니다. #111335 (groeneai).
  • 매니페스트 파티션 튜플이 파티션 스펙과 일치하지 않을 때 Iceberg 테이블에서 OPTIMIZE TABLE ... MANIFEST가 올바르게 동작하지 않던 문제를 수정했습니다. #111368 (SmitaRKulkarni).
  • 여러 개의 text 인덱스가 있는 MergeTree 테이블에서 텍스트 인덱스 직접 읽기 최적화가 읽기 헤더에 사용되지 않는 인덱스 가상 컬럼을 남기는 경우, 지연 머티리얼라이즈 최적화에서 발생하던 범위 밖 읽기(릴리스 빌드) / 논리 오류(debug 빌드)와 Merge 테이블의 Pipe::unitePipes에서 발생하던 논리 오류를 수정했습니다. #111467 (groeneai).
  • part_minmax_index_columns를 낮춘 후(예: with_block_number_offset에서 partition_key_only로 되돌린 경우) debug/새니타이저 빌드에서 백그라운드 머지를 중단시킬 수 있던 LOGICAL_ERROR(“Part level Min-Max index was constructed from unexpected columns set”)를 수정했습니다. #111511 (groeneai).
  • 파티션이 2개 이상이고 행 정책(row policy)이 정의된 테이블에서 STREAM 읽기(enable_streaming_queries = 1)를 실행할 때 발생하던 크래시를 수정했습니다. debug 및 새니타이저 빌드에서는 Filter column ... not found in DAG outputs 논리 오류로 실패했고, 릴리스 빌드에서는 세그폴트가 발생할 수 있었습니다. #111572 (groeneai).
  • 현재 설정에서 다형성 파트가 비활성화된 상태(비적응형 세분화 수준)에서 MergeTree 테이블이 기존 Compact 파트를 로드할 때 발생하던 LOGICAL_ERROR(Cannot create part with type Compact and storage type Full because table does not support polymorphic parts)를 수정했습니다. 예를 들어 읽기 전용 테이블이 다른 테이블과 디스크 경로를 공유하고 있고, SYSTEM RESTART DISK 실행 시 또는 서버 시작 시 파트를 다시 로드하는 경우 이 문제가 발생할 수 있었습니다. debug 및 새니타이저 빌드에서는 이 예외로 인해 서버가 중단됩니다. #111626 (groeneai).
  • fsync_part_directory = 1인 경우, 이제 상위 디렉터리(상위 디렉터리 간 이동 시에는 원본 상위 디렉터리까지)를 fsync하여 파트 디렉터리 이름을 임시 이름에서 최종 이름으로 변경하는 작업 자체의 영속성도 보장합니다. 이전에는 이동된 디렉터리만 fsync되었기 때문에, 파트가 커밋된 직후 전원이 차단되면 파일이 이미 기록되었는데도 디스크에서 파트가 누락될 수 있었고, 그 결과 해당 설정을 활성화했더라도 행이 손실될 수 있었습니다. #111861 (groeneai).
  • MergeTree 테이블에서 Nullable(Tuple(...)) 컬럼을 NULL 정보를 담는 요소 하위 컬럼(Variant, Dynamic 또는 LowCardinality) 중 하나와 함께 조회할 때 잘못된 결과와 LOGICAL_ERROR가 발생하던 문제를 수정했습니다. 하위 컬럼을 읽는 과정에서 상위 튜플에서 NULL인 행을 서브스트림 캐시를 통해 이미 공유된 컬럼에 NULL로 표시했기 때문에, 전체 컬럼을 읽을 때 값이 밀린 상태로 읽혔습니다. #111949 (groeneai).
  • 자동 디스크 스필(spill-to-disk) 임계값이 설정된 경우(26.5부터 기본값) 해시 조인에서 빌드 이후 최적화(고정 해시 테이블로의 변환, 공유 런타임 필터, 오른쪽 테이블 범위 재조정)가 적용되지 않던 문제를 수정했습니다. #111972 (alexey-milovidov).
  • text_index_posting_list_apply_mode = 'lazy'일 때 simdcomp를 사용하지 않는 빌드(x86_64 Linux를 제외한 모든 대상, 예: aarch64)에서 hasAllTokens 및 기타 다중 토큰 text 인덱스 검색이 잘못된 결과(행이 경고 없이 누락됨)를 반환하던 문제를 수정했습니다. 이식 가능한(portable) 비트 패킹 디코더가 비트 폭이 0인 블록에 대해 디코딩된 0 값을 기록하지 않아, 단일 포스팅 세그먼트에 있는 포스팅이 누락되었습니다. 디스크 저장 형식은 변경되지 않았으며, 수정 후에는 기존 데이터도 올바르게 읽힙니다. #112178 (groeneai).
  • 이제 손상된 MergeTree 통계가 로드되면 오류를 무시하지 않고 작업이 실패합니다. #112201 (skuznetsov-clickhouse).
  • HDFS에서 확인 응답된 Iceberg 쓰기가 경고 없이 손실되던 문제를 수정했습니다. Iceberg 커밋은 새 메타데이터 파일마다 조건부 쓰기로 게시하지만, HDFSObjectStorage가 조건을 무시하고 단순 덮어쓰기를 수행했습니다. 이 때문에 동시에 쓰는 writer가 모두 확인 응답을 받았음에도 그중 한 writer의 스냅샷에는 접근할 수 없게 되었습니다. 이제 HDFS는 조건부 쓰기를 거부하므로, 명시적 컬럼 목록이 포함된 CREATE TABLE ... ENGINE = IcebergHDFS(...)를 비롯하여 HDFS에서 저장소가 관리하는 Iceberg 쓰기는 실패합니다. 읽기에는 영향이 없습니다. #112437 (groeneai).
  • KeeperMap 테이블에 대한 DELETE가 일치하는 행 중 처음 max_block_size개만 삭제하면서도 뮤테이션이 성공적으로 완료되었다고 보고하던 문제를 수정했습니다. 또한 keeper_map_strict_mode = 1인 DELETE가 원자적으로 동작하지 않던 문제도 수정했습니다. 기존에는 버전 없는 삭제로 대체되어 동시에 업데이트된 행이 삭제될 수 있었고, 일치하는 행을 블록 단위로 적용했기 때문에 충돌이 발생하면 삭제가 일부만 적용될 수 있었습니다. #112777 (alexey-milovidov).
  • 읽기 또는 머지 경로에서 발생한 일시적인 Azure blob storage 오류(RBAC 권한 전파 중 발생한 403 Forbidden, 자격 증명 인증 실패, 408로 나타나는 연결 시간 초과)가 재시도 불가능한 오류로 잘못 분류되어 POTENTIALLY_BROKEN_DATA_PART(Code 740)로 보고되고, 정상 파트에 대해 잘못된 심각 경보가 발생하던 문제를 수정했습니다. 이제 이러한 일시적 실패는 재시도 가능한 오류로 처리되며, 실제로 지속되는 실패는 존재하지 않는 손상 데이터 파트가 아닌 일반 Azure 오류로 표시됩니다. #112871 (arsenmuk).
  • 접두사가 붙은 엔드포인트를 사용하는 Azure blob storage 디스크에서 listObjects가 첫 페이지 이후의 모든 페이지에서 잘못된 blob 이름을 반환하던 문제를 수정했습니다. 페이지네이션 과정에서 엔드포인트 접두사를 제거하는 클라이언트 래퍼를 우회한 것이 원인이었습니다. 이제 페이지네이션은 연속 토큰(continuation token)을 통해 래퍼를 다시 거치므로 모든 페이지에서 올바른 blob 이름이 반환됩니다. #112872 (arsenmuk).
  • 파트 전체를 다시 쓰지 않는 뮤테이션으로 생성된 파트에서, 테이블을 다시 로드한 후 _block_number 및 _block_offset에 대한 파트별 MinMax 인덱스가 손실되던 문제를 수정했습니다. #112878 (alexey-milovidov).
  • 뮤테이션 조건식에서 명시적 데이터베이스 이름 없이 merge 테이블 함수를 사용하면 예외(릴리스 빌드에서는 서버 시작을 막는 오류)가 발생하던 문제를 수정했습니다. 이제 테이블 이름과 마찬가지로 뮤테이션이 적용된 테이블의 데이터베이스가 사용됩니다. #113185 (alexey-milovidov).
  • share_nested_offsets = 1인 MergeTree 테이블에서 삭제 후 다시 추가된 Nested 멤버의 서브컬럼을 같은 그룹의 기존 멤버와 함께 읽을 때 잘못된 결과가 반환되거나 LOGICAL_ERROR가 발생하던 문제를 수정했습니다. 읽기 범위가 2개 이상의 블록에 걸치면 기존 멤버가 이후 블록의 값을 반환했습니다. #113225 (groeneai).
  • max_streams_to_max_threads_ratio가 매우 큰 상태에서 Merge 테이블을 읽을 때 디버그 및 새니타이저 빌드에서 산술 예외가 발생하던 문제를 수정했습니다. 스트림 수가 32비트로 잘려 2^32의 배수가 0이 되는 것이 원인이었습니다. 또한 Merge 테이블의 스트림 수를 곱한 값이 size_t를 초과하면 정의되지 않은 동작 대신 PARAMETER_OUT_OF_BOUND를 발생시키고, MergeTree 스트림 수를 데이터 양에 맞게 제한할 때 오버플로가 발생하지 않도록 했으며, 전체 소스 수가 65536을 초과하는 Merge 테이블 읽기는 거부하도록 했습니다. #113382 (alexey-milovidov).
  • hdfs 디스크에 쓰기가 실패하던 문제를 수정했습니다. 생성된 객체 키에 중첩된 디렉터리 접두사가 포함되는데, 블롭 저장소와 달리 HDFS는 실제 디렉터리를 사용하며 파일 생성 시 누락된 상위 디렉터리를 자동으로 만들지 않기 때문에 Parent directory doesn't exist 오류가 발생했습니다. #113396 (alexey-milovidov).
  • remote/remoteSecure 테이블 함수 또는 Remote/RemoteSecure 테이블 엔진에 존재하지 않는 명명된 컬렉션을 key = value 재정의와 함께 지정했을 때 엉뚱한 오류가 보고되던 문제를 수정했습니다. 이러한 호출은 별도의 알림 없이 위치 기반 호출로 다시 파싱되어 재정의가 데이터 표현식으로 분석되었고, 그 결과 관련 없는 대상을 가리키는 오류가 보고되었습니다(예: remote(collection, database = merge(...))에 대해 Function with name merge does not exist). 이제는 명명된 컬렉션이 없다는 오류가 보고됩니다. #113510 (groeneai).
  • merge_max_block_size_bytes가 빈 컬럼의 byteSize()보다 작게 설정되었을 때 백그라운드 머지와 OPTIMIZE에서 무한 루프가 발생하던 문제를 수정했습니다. 빈 LowCardinality 컬럼에도 딕셔너리가 포함되어 있어 단 하나의 행도 머지되기 전에 바이트 제한에 도달할 수 있었고, 이 경우 머지가 빈 블록을 끝없이 생성하면서 CPU 코어 하나를 100% 점유하고 백그라운드 풀 슬롯을 해제하지 않았습니다. #113585 (groeneai).
  • 테이블이 serialization_info_version = 'basic'을 사용할 때 Compact 파트의 뮤테이션 결과가 파트의 직렬화 정보가 메모리에 남아 있는지, 아니면 serialization.json에서 다시 로드되었는지에 따라 달라지던 문제를 수정했습니다. 이로 인해 ReplicatedMergeTree에서는 바이트 수준에서 동일한 원본 파트를 가진 두 레플리카가 서로 다른 뮤테이션 결과 파트를 기록했고, 뮤테이션이 CHECKSUM_DOESNT_MATCH로 실패했습니다. #113588 (groeneai).
  • 대상 저장소에서 .lock 파일을 읽을 수 없을 때 Backup이 동시 백업이 진행 중이라고 잘못 보고하는 대신 실제 잠금 파일 접근 오류를 보고하도록 개선했습니다. #113637 (kirillshokhin).
  • MergeTree 테이블의 백그라운드 작업(통계 갱신, 파트 갱신, 오래된/예상치 못한 파트 로딩)과 테이블 소멸 간의 데이터 경쟁을 수정했습니다. #113722 (alexey-milovidov).
  • 업데이트 대상 테이블의 데이터베이스가 세션의 데이터베이스와 다를 때 UPDATE와 경량 DELETE가 잘못된 테이블을 읽던 문제를 수정했습니다. 이제 뮤테이션의 표현식은 현재 데이터베이스를 암묵적으로 사용하는 merge 테이블 함수와 한정되지 않은 테이블 식별자 모두에 대해 업데이트 대상 테이블의 데이터베이스를 기준으로 정규화됩니다. 이전에는 이러한 이름이 세션의 데이터베이스를 기준으로 해석되어, 다른 테이블에서 선택된 행이 아무런 경고 없이 업데이트되거나 삭제되었습니다. #113748 (groeneai).
  • 기본 키 범위 레이어 단위로 MergeTree 테이블을 읽을 때 특정 레이어가 빈 파이프를 생성하면 예외가 발생하던 문제를 수정했습니다. #114177 (alexey-milovidov).
  • 이제 BACKUP, RESTORE, ENGINE = Backup은 s3(), file(), azureBlobStorage()와 동일한 방식으로 사용자의 SOURCES 권한을 기준으로 백업 위치에 대한 권한을 검사합니다. 이전에는 BACKUP 권한만 있고 SOURCES 권한이 없는 사용자도 서버가 접근할 수 있는 모든 위치에 백업을 쓰거나 그 위치에서 백업을 읽을 수 있었습니다. 이제 백업을 쓰려면 대상 소스에 대한 WRITE 방향 권한(WRITE ON S3, WRITE ON AZURE, WRITE ON FILE)이 필요하고, 백업을 읽으려면 READ 권한이 필요합니다. Disk(...) 대상은 기존과 같이 backups.allowed_disk로만 제한됩니다. #114405 (groeneai).
  • 뮤테이션 진행 중 테이블을 읽을 때 발생하던 문제를 수정했습니다. 이전에는 MATERIALIZED 컬럼이 오래된 값을 반환할 수 있었고, 이 컬럼을 업데이트된 컬럼과 함께 조회하면 오류가 발생할 수 있었습니다. #114561 (tiandiwonder).
  • make_distributed_plan을 활성화한 상태에서 내부에 집합 연산이 포함된 하위 테이블을 가진 Merge 테이블을 읽을 때 발생하던 논리 오류(Block structure mismatch)를 수정했습니다. #114753 (alexey-milovidov).
  • 컴팩션을 구현하지 않은 엔진을 사용하는 객체 스토리지 테이블에서 OPTIMIZE TABLE을 실행하면 실제로는 아무 작업도 하지 않으면서 성공으로 보고되었습니다. 이제는 해당 구문을 지원하지 않는 다른 모든 엔진과 마찬가지로 오류를 발생시킵니다. 이 변경은 DeltaLake, Paimon, Hudi 및 일반 객체 스토리지 엔진(S3, GCS, COSN, OSS, AzureBlobStorage, HDFS, 객체 스토리지 기반 URL)에 적용되며, 컴팩션을 구현한 Iceberg는 영향을 받지 않습니다. #114805 (groeneai).
  • allow_deprecated_syntax_for_merge_tree 설정하에 사용 중단 예정인 위치 기반 구문으로 생성한 ReplicatedMergeTree에서 발생하던 BAD_DATA_PART_NAME(“Trying to get part name in new format for old format version”) 오류를 수정했습니다. 이전에는 뮤테이션을 적용하지 않은 레플리카에서도 해당 뮤테이션이 완료된 것으로 보고될 수 있었고, 재시작 후 테이블이 읽기 전용 상태로 남을 수 있었습니다. #114980 (groeneai).
  • 경량 업데이트를 사용하는 테이블에서 발생하던 Found patch part ... that intersects mutation with version ...(LOGICAL_ERROR) 오류를 수정했습니다. 패치 파트를 머지하면 데이터 버전 범위가 기존 파트의 데이터 버전에 걸치는 패치가 생성될 수 있었습니다. 이러한 패치는 적용할 수도 건너뛸 수도 없어 해당 파티션에 대한 이후의 모든 작업이 실패하고 복제 큐가 멈췄습니다. 이제 이러한 머지는 할당되지 않습니다. #115064 (alexey-milovidov).
  • Backup 데이터베이스 엔진이 사용할 수 없게 된 백업(예: 파일이 삭제되었거나 기반 스토리지에 접근할 수 없는 경우)을 참조할 때 서버가 시작되지 않던 문제를 수정했습니다. 이제 서버 전체의 시작을 막는 대신 해당 데이터베이스를 테이블 없이 로드합니다. #83188 (orloffv).
  • 디스크 용량 부족 오류 이후 로깅이 복구되지 않던 문제를 수정했습니다. 이전에는 로그 디스크가 가득 차면 ClickHouse가 실패 상태에 빠져 syslog에 오류 메시지를 끊임없이 쏟아냈으며(시간당 100GB 이상 기록될 수 있음), 디스크 공간이 확보된 후에도 복구되지 않았습니다. 이제 디스크 공간이 확보되면 서버를 재시작하지 않아도 로깅 시스템이 자동으로 복구됩니다. #93127 (jaehanbyun).
  • DeltaLake 스토리지의 스키마 방문자(schema visitor)에서 발생하던 크래시를 수정했습니다. #97112 (kssenii).

데이터 레이크 및 외부 저장소 관련 수정 사항

  • S3 멀티파트 업로드(예: INSERT INTO ... hits_s3)에서 일시적으로 발생하던 Code: 499 ... InvalidPart (S3_ERROR) 실패를 수정했습니다. MinIO는 CompleteMultipartUpload 시 방금 업로드된 파트를 잠시 누락된 것으로 보고할 수 있습니다. 이제 이 오류도 기존에 처리되던 NoSuchKey와 마찬가지로 s3_max_unexpected_write_error_retries 한도 내에서 재시도됩니다. #109364 (groeneai).
  • 데이터 파일 형식이 Parquet가 아닌 Iceberg 테이블에서 ALTER TABLE ... DELETE 및 ALTER TABLE ... UPDATE를 실행하면, 서버가 비정상 종료되거나 테이블이 아무런 경고 없이 손상되는 대신 명확한 NOT_IMPLEMENTED 오류와 함께 거부됩니다. #105893 (groeneai).
  • file, s3, input 등의 테이블 함수에서 INSERT SELECT를 수행할 때 동일한 소스 컬럼을 두 번 이상 선택하면 Cannot add column ...: column with this name already exists 오류가 발생하던 문제를 수정했습니다. #105982 (crakjie).
  • HTTP 쿼리 문자열 매개변수로 전달된 민감한 값(예: param_secret_key/param_aws_secret_access_key와 같은 param_* 쿼리 매개변수 바인딩, password 매개변수, S3 방식의 signature 매개변수)이 더 이상 system.text_log나 OpenTelemetry 스팬에 그대로 기록되지 않습니다. 이제 Request URI 로그 줄에서는 민감한 정보로 보이는 이름을 가진 매개변수의 값을 [HIDDEN]으로 가립니다. #108475 (groeneai).
  • S3Queue 및 AzureQueue 테이블 엔진의 _etag 가상 컬럼을 수정했습니다. 이 컬럼은 선언만 되어 있고 값이 채워지지 않아 SELECT _etag가 항상 빈 문자열을 반환했습니다. 이제 S3 엔진 및 s3() 테이블 함수와 마찬가지로 객체의 ETag를 반환합니다. #108625 (groeneai).
  • S3 요청이 진행 중일 때 S3에서 읽거나 S3에 쓰는 쿼리가 취소되면(예: KILL QUERY), 이제 오해를 일으키는 네트워크/S3 오류 대신 취소로 보고됩니다. 특히 S3로의 백업 또는 복원이 취소되면 이제 system.backups에 BACKUP_CANCELLED/RESTORE_CANCELLED가 기록됩니다. #108673 (jkartseva).
  • S3Queue 테이블 엔진의 _tags 가상 컬럼을 수정했습니다. 이 컬럼은 선언만 되어 있고 값이 채워지지 않아 SELECT _tags가 항상 빈 맵을 반환했습니다. 이제 S3 엔진 및 s3() 테이블 함수와 마찬가지로 객체의 태그를 반환합니다. #108676 (groeneai).
  • 데이터 레이크 카탈로그 데이터베이스에서 SHOW TABLES와 SELECT … FROM system.tables가 서로 다른 결과를 반환하던 문제를 수정했습니다. 이제 ClickHouse가 읽을 수 없는 테이블은 양쪽 모두에서 일관되게 숨겨집니다. #109273 (SmitaRKulkarni).
  • Delta Lake 테이블(DeltaLakeLocal / deltaLake)에 대한 INSERT가 싱크의 쓰기 시작 이후에 실패하면(예: 소스 쿼리가 삽입 도중 예외를 발생시키거나 쿼리가 취소된 경우) 서버가 중단되던 문제(릴리스 빌드에서는 데이터 파일이 경고 없이 마무리되지 않던 문제)를 수정했습니다. #109328 (groeneai).
  • optimize_functions_to_subcolumns=1(기본값)인 상태에서, 기존 데이터 파일이 기록된 후 스키마 변경으로 추가된 Iceberg 컬럼에 WHERE col IS NULL / IS NOT NULL을 실행하면 Not found column or subcolumn c.null in block 오류(debug/sanitizer 빌드에서는 Bad cast from ColumnConst to ColumnNullable)가 발생하던 문제를 수정했습니다. #109515 (groeneai).
  • CREATE TABLE ... AS SELECT 쿼리에서 스칼라 서브쿼리를 s3 테이블 함수의 URL 인수(또는 다른 테이블 함수의 인수)로 사용할 때 발생하던 Host is empty in S3 URI 오류를 수정했습니다. 이제 테이블 함수 인수에 포함된 스칼라 서브쿼리는 쿼리 분석 단계에서 평가됩니다. #110254 (CheSema).
  • Iceberg 테이블에 UPDATE ..., DELETE ...와 같은 다중 명령 ALTER를 실행할 때 발생하던 논리 오류(debug/sanitizer 빌드에서는 서버 중단)를 수정했습니다. 이제 이러한 뮤테이션은 명확한 NOT_IMPLEMENTED 오류와 함께 거부됩니다. #110347 (groeneai).
  • 초기 스키마에 중첩 필드(Tuple/Array/Map)가 포함된 Iceberg 테이블에서 ALTER TABLE ... ADD COLUMN 실행 후 중복된 필드 ID가 생성되던 문제를 수정했습니다. 이제 last-column-id에 중첩된 하위 필드까지 포함하여 할당된 최대 필드 ID가 기록되므로, 이후 추가되는 컬럼이 중첩 필드 ID를 재사용하지 않으며 읽기 작업도 더 이상 ICEBERG_SPECIFICATION_VIOLATION(Duplicate field id) 오류로 실패하지 않습니다. #110884 (groeneai).
  • 테이블에 ALTER TABLE ... ADD COLUMN 실행 전후에 기록된 데이터 파일이 함께 존재하고 optimize_move_to_prewhere가 활성화되어 있을 때, Iceberg 테이블에 대한 DELETE/UPDATE가 엉뚱한 행을 경고 없이 삭제하던(또는 NOT_FOUND_COLUMN_IN_BLOCK 오류를 발생시키던) 문제를 수정했습니다. #111693 (groeneai).
  • Iceberg 테이블에서 ALTER TABLE ... EXECUTE expire_snapshots를 실행한 후 보존된 스냅샷의 system.iceberg_history 내 made_current_at 값이 1970-01-01로 표시되던 문제를 수정했습니다. 또한 메타데이터에 snapshot-log가 없는 테이블에 대해 system.iceberg_history가 행을 반환하지 않던 문제도 수정했습니다. #111781 (groeneai).
  • MATERIALIZED VIEW를 통해 Iceberg 테이블에 삽입할 때 발생하던 데이터 손상 문제를 수정했습니다. 데이터 파일이 대상 테이블의 현재 Iceberg 스키마가 아닌 CREATE 시점의 컬럼 타입을 기준으로 기록되었기 때문에, DateTime 값이 단순 Avro int로 저장되어 마이크로초 단위로 읽혔고, DateTime64(0) 또는 DateTime64(9)는 파일을 아예 다시 읽을 수 없었습니다. 이에 따라 대상 테이블의 Iceberg 스키마가 뷰에 선언된 컬럼보다 넓으면, 이제 INSERT INTO <materialized view>는 손상된 행을 기록하는 대신 TYPE_MISMATCH 오류를 발생시킵니다. #112359 (groeneai).
  • 튜플 안에 튜플이 중첩된 스키마를 가진 Iceberg 테이블에 쓰기 작업을 할 때 발생하던 문제를 수정했습니다. 게시된 테이블 메타데이터에서 내부 튜플의 필드 이름이 위치 기반 이름 1, 2, …로 대체되어, 기본 Parquet 포맷에서는 INSERT가 INCORRECT_DATA 오류로 실패했고 Avro 포맷에서는 해당 컬럼을 다시 읽을 수 없었습니다. #112480 (groeneai).
  • 두 쿼리가 동시에 같은 테이블 이름을 조회할 때 Filesystem 또는 HDFS 데이터베이스가 영구적으로 멈추는 교착 상태(deadlock)를 수정했습니다. 이 문제가 발생하면 해당 데이터베이스에 대한 이후의 모든 쿼리가 무기한 대기 상태가 되고 중단할 수도 없어, 복구하려면 서버를 재시작해야 했습니다. #112495 (groeneai).
  • WHERE 프레디케이트의 NOT 아래에 delta-kernel 프레디케이트 변환기가 처리할 수 없는 하위 표현식이 있을 때 DeltaLake 테이블이 실제보다 적은 행을 반환하던 문제를 수정했습니다. 이제 이러한 하위 표현식은 하위 반복자(iterator)의 끝으로 처리되지 않고, 명시적인 알 수 없는 프레디케이트로 delta-kernel에 전달됩니다. 기존에는 이 때문에 상위 논리곱(conjunction)이 경고 없이 잘려 나갔습니다. #112652 (groeneai).
  • ALTER TABLE ... EXECUTE remove_orphan_files가 Iceberg 테이블에서 사용 중인 metadata/version-hint.text를 삭제하던 문제를 수정했습니다. 연결 가능한 집합(reachable set)의 항목을 문자열 연결로 생성할 때 값 끝에 슬래시가 있다고 가정했지만 실제로는 슬래시가 붙지 않는 값이었기 때문에, 실제 힌트 파일이 연결 가능한 파일로 인식되지 않아 older_than 임계값보다 오래되면 삭제되었습니다. 그 결과 iceberg_use_version_hint = 1로 설정된 테이블은 아예 읽을 수 없게 되었습니다. #113548 (groeneai).
  • ALTER TABLE ... MODIFY COLUMN으로 Nullable이 된 Iceberg 컬럼을 필터링할 때 발생하던 LOGICAL_ERROR를 수정했습니다. #114521 (groeneai).
  • ENGINE = URL(...) 정의를 포함한 ATTACH TABLE이 URL 스킴에 따라 실제로 사용되는 엔진의 TABLE ENGINE 권한을 확인하지 않던 문제를 수정했습니다. 이로 인해 TABLE ENGINE ON URL 권한만 가진 사용자도 File, S3, AzureBlobStorage 또는 HDFS 기반 테이블을 ATTACH한 후 읽을 수 있었습니다. CREATE TABLE에서는 이러한 동작이 올바르게 거부됩니다. #115914 (groeneai).
  • IPv4와 IPv6 주소를 모두 제공하지만 그중 한 가지 주소 체계만 라우팅 가능한 호스트에서 외부로 나가는 HTTP 요청(예: `aiGenerate`, `url` 테이블 함수, S3)이 `No route to host`로 실패하던 문제를 수정했습니다. 이제 HTTP 연결 풀은 첫 번째 주소가 네트워크 오류로 실패하면 첫 요청에서 곧바로 오류를 전파하지 않고, 확인된 다음 주소로 폴백합니다. #103786 (alexey-milovidov).
  • {key, value} 두 필드로 구성된 레코드의 Avro array를 ClickHouse Map 컬럼으로 읽을 수 있도록 개선했습니다. 이는 Iceberg와 Spark가 문자열이 아닌 키를 가진 MAP<K, V>를 표현할 때 사용하는 인코딩입니다(Avro 네이티브 맵은 문자열 키만 지원합니다). 이전에는 이러한 파일을 Array(Tuple(key, value))로는 읽을 수 있었지만 Map(K, V)로 읽으면 Type Map(...) is not compatible with Avro array 오류가 발생했습니다. #109289 (groeneai).
  • 버전 번호가 숫자로만 이루어져 있지만 32비트 정수 범위를 초과하는 메타데이터 파일(예: v99999999999999999999.metadata.json)이 있는 Iceberg 테이블을 읽을 때 발생하던 문제를 수정했습니다. 이전에는 이러한 이름에 대해 명확한 BAD_ARGUMENTS 오류 대신 원인을 파악하기 어려운 std::out_of_range(STD_EXCEPTION)가 발생했습니다. #109619 (groeneai).
  • gzip으로 압축된 Iceberg 메타데이터 파일의 파일 이름을 수정했습니다. ClickHouse는 이 파일을 v{N}.gzip.metadata.json(HTTP Content-Encoding 토큰 기준)으로 기록했지만, Iceberg 사양에서는 gz 확장자를 사용한 v{N}.gz.metadata.json을 요구합니다. 이로 인해 Spark 및 기타 Hadoop 카탈로그 리더가 ClickHouse가 기록한 메타데이터를 찾지 못했습니다. 이제 ClickHouse는 v{N}.gz.metadata.json으로 기록하며, 이전 버전과의 호환성을 위해 기존 gzip 이름도 계속 읽을 수 있습니다. #109812 (groeneai).
  • 쓰기 형식이 Avro인 Iceberg 테이블에서 "required": false로 선언된 list, map 또는 struct 유형의 필드가 ["null", T] union 없이 필수 필드로 직렬화되던 문제를 수정했습니다. 이로 인해 데이터 파일 자체의 스키마가 테이블 메타데이터와 일치하지 않았고, 다른 Iceberg 리더에서는 해당 필드를 필수 필드로 인식했습니다. 이제 이러한 필드는 Iceberg 사양에서 선택적 필드에 사용하는 ["null", T] union으로 기록됩니다. #112648 (groeneai).
  • Iceberg snapshot-log에 동일한 snapshot-id가 두 번 이상 나타날 때(롤백 후 이러한 상태가 됨) system.iceberg_history의 made_current_at이 스냅샷이 현재 스냅샷이 된 가장 최근 시각 대신 가장 이른 시각을 보고하던 문제를 수정했습니다. #113598 (groeneai).
  • 명명된 컬렉션에 http_client = 'gcp_oauth'가 설정되어 있고 Google OAuth2 토큰 엔드포인트가 연결은 수락하지만 끝내 응답하지 않을 때, BACKUP/RESTORE ... TO S3, GCS 디스크 및 s3 테이블 함수가 최대 1시간 동안 멈추던 문제를 수정했습니다. 이제 Bearer 토큰 요청은 호출자의 데이터 전송 요청 타임아웃을 상속하지 않으며, STS AssumeRole 요청 상한과 마찬가지로 응답 대기 시간이 최대 10초로 제한됩니다. #115531 (groeneai).
  • 백그라운드 캐시 다운로드가 ErrnoException 이외의 예외로 실패하면(예: Iceberg 테이블에 OPTIMIZE를 수행하는 중) 비어 있는 고아 캐시 파일이 남아, 파일 시스템 캐시에서 논리 오류(Expected file ... not to exist)가 발생할 수 있던 문제를 수정했습니다. #110549 (groeneai).
  • 최대 엔트리 수 기준으로 설정된 캐시(SLRU 정책)가 그 개수만큼의 엔트리가 두 번 이상 접근된 이후로 새 엔트리를 아무런 경고 없이 더 이상 받아들이지 않던 문제를 수정했습니다. 영향을 받는 캐시는 Iceberg 및 Paimon 메타데이터 파일 캐시, Parquet 메타데이터 캐시, 텍스트 인덱스 캐시, 벡터 유사성 인덱스 캐시, 컴파일된 표현식 캐시, ObjectStorageQueue 파일 상태 캐시입니다. #115517 (groeneai).
  • 변경 가능한 snapshot/LATEST 힌트가 동시에 교체되는 도중 Paimon 테이블 읽기가 실패할 수 있던 문제를 수정했습니다. 이제 유효하지 않거나 오래된 힌트가 있으면 안전하게 스냅샷 목록 조회로 폴백됩니다. #112010 (JiaQiTang98).
  • 입력 버퍼(예: restricted_seek = true인 S3 읽기 버퍼)가 minizip이 요청한 seek 또는 읽기를 거부하여 zip 아카이브의 압축을 풀 수 없을 때, 근본 원인이 되는 실제 예외를 표시하도록 개선했습니다. 이전에는 실제 오류가 일반적인 Couldn't unpack zip archive: Code = -100 / Couldn't open zip archive 메시지에 가려져 있었습니다. #105103 (groeneai).
  • refs가 없는 메타데이터에서 Iceberg 쓰기가 제대로 동작하지 않던 문제를 수정했습니다 #106896 (AVMusorin).
  • 외부 엔진이 생성한 메타데이터에 선택 항목인 snapshots, metadata-log 또는 snapshot-log 배열이 없는 Iceberg 테이블에 데이터를 삽입할 때 예외가 발생하던 문제를 수정했습니다. 이제 이러한 삽입이 실패하지 않고 정상적으로 완료됩니다. #107473 (tiandiwonder).
  • 일시적인 읽기 오류 후 S3 업로드(예: 백업)를 재시도할 때 발생할 수 있던 ReadBuffer is canceled. Can't read from it. 오류를 수정했습니다. #108573 (groeneai).
  • 최종 비동기 S3/Azure 멀티파트 업로드 완료 작업의 스케줄링이 실패하면(예: 스레드 풀 고갈 시) std::future_error(“The associated promise has been destructed prior to the associated state becoming ready”)가 발생하고, debug/새니타이저 빌드에서는 서버가 비정상 종료될 수 있던 문제를 수정했습니다. 이제 실제 스케줄링 오류가 보고됩니다. #108730 (groeneai).
  • 스케일이 9보다 작은 DateTime64 컬럼으로 약 2262년 이후의 ORC 타임스탬프를 읽을 때 발생하던 문제를 수정했습니다. 기존 네이티브 ORC 리더는 모든 타임스탬프를 고정된 DateTime64(9) 중간값을 거쳐 변환했는데, 이 방식은 나노초 스케일에서 Int64 오버플로우를 일으킵니다. 그 결과 요청된 DateTime64 스케일(예: Iceberg가 생성하는 DateTime64(6))로 표현할 수 있는 값조차 VALUE_IS_OUT_OF_RANGE_OF_DATA_TYPE 오류와 함께 거부되었습니다. 이제 타임스탬프를 요청된 스케일로 직접 읽으며, 대상 스케일로도 값을 담을 수 없으면 date_time_overflow_behavior 설정을 따릅니다. #109302 (groeneai).
  • 스키마에 지원되지 않는 중첩 유형(예: ROW 필드)이 포함된 Paimon 테이블을 읽으면, 이제 오류 코드 0에 메시지도 없는 DB::Exception. (OK) 대신 지원되지 않는 유형을 명시한 BAD_ARGUMENTS 오류를 명확하게 보고합니다. #109762 (groeneai).
  • 동일한 원본 컬럼으로 두 번 이상 파티셔닝된 Iceberg 테이블(예: PARTITIONED BY (hours(ts), ts))을 읽을 때 발생하던 문제를 수정했습니다. 이전에는 이러한 테이블을 읽으면 Cannot add column ...: column with this name already exists (ILLEGAL_COLUMN) 오류가 발생했습니다. #109895 (groeneai).
  • 이제 ClickHouse가 Iceberg 테이블에 기록하는 데이터 파일은 Avro(field-id) 및 ORC(iceberg.id/iceberg.required 유형 속성) 포맷에서도 Iceberg 필드 ID를 포함하며, ORC String 컬럼은 바이너리가 아닌 ORC string으로 기록됩니다. 이전에는 Parquet만 필드 ID를 포함했기 때문에, 사양을 준수하는 리더(예: Spark/iceberg-java)는 컬럼 이름 변경 후 ClickHouse가 기록한 Avro 행에 대해 아무 경고 없이 NULL을 반환했고, ClickHouse가 기록한 ORC 파일은 아예 읽지 못했습니다. #109994 (groeneai).
  • 모든 포지션 삭제 파일보다 최신인 Parquet 이외 포맷(예: ORC)의 데이터 파일이 포함된 Iceberg 테이블에서 OPTIMIZE TABLE을 실행할 때 발생하던 논리 오류 ChunkInfoRowNumbers does not exist를 수정했습니다. #110107 (alexey-milovidov).
  • s3 및 file을 통해 압축되지 않은 STORED zip 항목에서 대용량 Parquet 파일을 읽을 때 발생하던 문제를 수정했습니다. #110495 (Gudauu).
  • 백그라운드 스케줄 풀(예: Global Thread 풀이 고갈된 상황에서의 iceberg 풀)을 시작하지 못하더라도 더 이상 서버가 중단되지 않으며, 해당 오류는 이제 복구 가능한 예외로 처리됩니다. 또한 system.background_schedule_pool을 조회해도 더 이상 부수 효과로 해당 풀이 생성되지 않습니다. #111209 (groeneai).
  • Paimon REST 카탈로그의 DLF 인증 문제를 수정했습니다. 요청 서명을 한 번만 계산한 뒤 재사용했기 때문에 첫 요청 이후의 모든 카탈로그 요청이 HTTP 401로 실패했고, SHOW TABLES는 빈 목록을 반환했습니다. 테이블 존재 여부를 확인할 때 HTTP 404를 제대로 감지하지 못하던 문제도 함께 수정했습니다. #112015 (JiaQiTang98).
  • 포지션 삭제로 인해 비어 버린 Iceberg 데이터 청크를 파티셔닝할 때(예: 데이터 파일이 완전히 삭제된 파티션 Iceberg 테이블을 컴팩션하는 경우) 발생하던 LOGICAL_ERROR(partitions_count > 0)를 수정했습니다. #112432 (PedroTadim).
  • Azure 배치 객체 삭제 시 배치 요청 자체가 실패하면 system.blob_storage_log에 Delete 이벤트가 전혀 기록되지 않아 배치 전체가 로그에서 누락되던 문제를 수정했습니다. 이제 배치 수준에서 실패하면 각 객체마다 Delete 이벤트가 기록됩니다. #112873 (arsenmuk).
  • 밀리초보다 높은 정밀도의 TIMESTAMP 컬럼으로 파티션된 Paimon 테이블을 읽을 때 scale 6 is not supported, only support scale <= 3 오류와 함께 실패하던 문제를 수정했습니다. #113401 (JiaQiTang98).
  • 스키마에 이름이 비어 있는 컬럼이 선언된 데이터 레이크 테이블을 읽을 때 발생하던 크래시를 수정했습니다. 형식이 잘못된 Iceberg 메타데이터는 ICEBERG_SPECIFICATION_VIOLATION으로 거부되며, 카탈로그, Delta Lake 또는 Paimon에서 제공한 스키마는 AMBIGUOUS_COLUMN_NAME으로 거부됩니다. 이 검사는 조건 없이 항상 수행되므로, 필드 이름이 비어 있는 과거 스키마를 사용하지 않고 보유만 하고 있는 Iceberg 테이블도 해당 스키마를 읽는 시점에 비정상 종료되는 대신 읽을 수 없는 상태가 됩니다. #114394 (groeneai).
  • Iceberg 사양에서 금지하는 스키마 진화(schema evolution)가 메타데이터에 기술된 Iceberg 테이블을 읽어도 더 이상 서버가 비정상 종료되지 않습니다. 기존에는 IcebergSchemaProcessor에서 발생하는 4가지 사양 위반이 실패한 어서션으로 취급되는 LOGICAL_ERROR로 보고되거나, 검사 없이 치명적인 어서션에 도달했습니다. 이제는 ICEBERG_SPECIFICATION_VIOLATION이 발생합니다. #114518 (groeneai).
  • HTTP Last-Modified 헤더를 이식성 없는 방식으로 파싱하는 바람에 musl 기반 빌드에서 url/urlCluster 테이블 함수의 _time 가상 컬럼이 항상 NULL이 되던 문제를 수정했습니다. #111619 (thevar1able).
  • allow_experimental_url_wildcard_from_index_pages가 활성화된 상태에서 CREATE TABLE ... AS url('http://host/**/', ...)로 테이블을 생성하면 이후 서버가 시작되지 않던 문제를 수정했습니다. 이러한 테이블의 메타데이터를 로드할 때 Experimental 기능 검사가 다시 수행되어 SUPPORT_IS_DISABLED로 실패하면서 서버 시작이 중단되었습니다. #115095 (groeneai).
  • URL 데이터베이스 엔진의 테이블이 더 이상 소스 읽기 권한이 없는 사용자에게 로컬 파일의 존재 여부를 노출하지 않습니다. SHOW TABLES 권한만 있으면 실행할 수 있는 EXISTS TABLE과 테이블 해석 과정 모두 이제 권한을 확인하기 전에는 파일 시스템을 조회하지 않습니다. #113029 (alexey-milovidov).
  • Exception::addMessage를 통해 추가되는 메시지에도 query_masking_rules를 적용하여, 마스킹 규칙이 구성된 경우 jdbc()/odbc() 오류의 (in file/uri ...) 접미사에 포함된 URL 인코딩된 자격 증명이 유출되지 않도록 했습니다. #106916 (gaurav0107).

포맷 및 수집 관련 수정 사항

  • Arrow time32/time64를 스키마 없이 읽을 때(예: SELECT * FROM file(..., 'Arrow')) 이제 DateTime64 대신 Time64로 추론합니다. 이전에는 DateTime64로 추론했습니다. 따라서 이전 추론 타입을 전제로 하는 다운스트림 작업은 업그레이드 후 정상적으로 동작하지 않습니다. 또한 Time/Time64를 Arrow로 내보내는 기능을 추가했으며, 정밀도에 따라 적절한 Apache Arrow 시간 타입이 선택됩니다. #104316 (Maoyao233).
  • 지연 컬럼 복제(enable_lazy_columns_replication)가 적용된 상태에서 배치 처리 도중 발생한 오류로 INSERT가 롤백될 때(예: Buffer 테이블, 비동기 삽입(asynchronous inserts), Kafka/RabbitMQ/FileLog 엔진) 잘못된 결과가 반환되거나 범위를 벗어난 읽기가 발생할 수 있던 문제를 수정했습니다. #108935 (groeneai).
  • INSERT 컬럼 목록에서 t.* LIKE '<pattern>' / t.* ILIKE '<pattern>' 형태의 한정 컬럼 매처는 허용하면서, 이와 동일한 정규 형태인 t.COLUMNS('<regexp>')는 거부하던 파서 불일치 문제를 수정했습니다. 이 문제로 쿼리 포맷 왕복 변환이 깨졌으며, debug/sanitizer 빌드에서는 서버가 비정상 종료되었습니다. #109176 (groeneai).
  • ADLS Gen2(DFS) 쓰기를 .blob 호스트 대신 .dfs 엔드포인트 호스트로 라우팅하도록 변경하여, Microsoft Fabric / OneLake DataLakeCatalog 테이블에 대한 INSERT가 IncorrectEndpointError(HTTP 400)로 실패하던 문제를 수정했습니다. 참고: remote_url_allow_hosts를 사용하는 경우 INSERT를 수행하려면 .blob(읽기) 및 .dfs(쓰기) Fabric 호스트를 모두 허용 목록에 추가해야 합니다. #110290 (zlareb1).
  • 데이터 레이크 테이블 함수를 통해 쓰기를 수행할 때(예: INSERT INTO FUNCTION icebergS3(...)) 생성된 parquet 파일의 문자열 컬럼에서 String 타입 어노테이션이 누락되어, Spark 같은 외부 리더가 기록된 데이터를 읽지 못하던 문제를 수정했습니다. 이제 이러한 쓰기에도 테이블 엔진을 통한 쓰기와 동일한 포맷 설정이 적용됩니다. #110465 (tiandiwonder).
  • Arrow Flight로 로그인한 후 system.session_log를 읽을 수 없게 되던 문제를 수정했습니다. interface 컬럼은 Enum8 타입이지만 열거값에 ArrowFlight가 빠져 있어, Arrow Flight 프로토콜로 로그인하면 원시 값 10이 기록되었고 해당 행을 읽는 모든 SELECT에서 Unexpected value 10 in enum 예외가 발생했습니다. #110758 (alexey-milovidov).
  • TSV 계열 포맷의 스키마 추론에서 0.0이나 0.5처럼 앞에 0이 붙은 소수 값을 String으로 추론하던 문제를 수정했습니다(CSV는 올바르게 Float64로 추론합니다). 또한 첫 번째 행이 이러한 값으로만 이루어진 경우 TSV 헤더 자동 감지가 해당 행을 헤더로 간주하여 결과에서 누락되는 문제도 있었습니다. 아울러 TSKV에서 x=1\x2E5처럼 이스케이프 시퀀스로 작성된 값을 숫자 유형으로 추론한 뒤 파싱에 실패하던 문제도 수정했습니다. 단, 007처럼 앞의 0이 정수 패딩인 값은 TSV 값 파서가 다시 읽을 수 없으므로 계속 String으로 추론됩니다. #112226 (groeneai).
  • 값 파서가 다시 읽을 수 없는 텍스트 값에 대해 스키마 추론이 숫자 타입을 제안하던 문제를 수정했습니다. 추론 과정에서는 불완전한 지수(1e+), 가수가 없는 값(.), 반복된 부호(++inf)를 허용했지만, 추론된 스키마로 데이터를 읽을 때 readFloatTextPrecise가 이를 CANNOT_PARSE_NUMBER로 거부했습니다. Dynamic 컬럼에서는 이 문제가 INSERT 시점의 오류로 나타났습니다. 이제 추론 시 리더가 실제로 사용하는 파서로 숫자를 검증합니다. 이에 따라 추론된 타입이 max_read_buffer_size에 따라 달라지던 경우도 없어졌으며, 0e5처럼 앞자리가 0인 유효한 지수 형식이 CSV와 마찬가지로 TSV에서도 Float64로 추론됩니다. 잘못된 지수 형식 처리 문제도 함께 수정했습니다. #112453 (groeneai).
  • 행 기반 입력 형식이 블록 하나를 파싱하는 동안 KILL QUERY와 max_execution_time이 수 분간 무시되던 문제를 수정했습니다. 이제 행 기반 입력 형식은 8192행마다 쿼리 취소 여부를 확인하므로, 종료된 삽입 작업(특히 블록당 최대 max_insert_block_size개의 행을 파싱하는 백그라운드 비동기 삽입 플러시)이 블록 끝까지 실행되지 않고 즉시 중단됩니다. #112646 (groeneai).
  • 스키마가 캐시된 소스에서 추론된 컬럼 타입이 앞서 실행된 쿼리의 순서에 따라 달라지던 문제를 수정했습니다. 추론 타입에 영향을 주는 설정이 스키마 추론 캐시 키에서 누락되어, 첫 번째 쿼리의 설정값이 이후 모든 쿼리의 타입을 결정했습니다. 해당 설정은 input_format_try_infer_exponent_floats, max_parser_depth, input_format_json_infer_array_of_dynamic_from_array_of_different_types이며, Parquet에서는 input_format_parquet_local_time_as_utc, input_format_parquet_allow_geoparquet_parser, input_format_parquet_skip_columns_with_unsupported_types_in_schema_inference, schema_inference_make_json_columns_nullable도 포함됩니다. 또한 Form에 누락되어 있던 캐시 키 getter를 등록하고, Template getter가 자체 행 포맷의 이스케이프 규칙을 사용하도록 수정했습니다. #113533 (groeneai).
  • 상위 쿼리 끝에 SETTINGS 절이 있을 때 view 및 viewIfPermitted 테이블 함수의 서브쿼리 인수가 잘못 포맷되던 문제를 수정했습니다. 이러한 쿼리는 다시 파싱할 수 없는 view((SELECT ...)) 형태로 포맷되어 내부 포맷-파싱-포맷 검사를 통과하지 못하고 Inconsistent AST formatting 오류가 발생했습니다. #114658 (groeneai).
  • 포맷 자동 감지 시 JSON 데이터가 TSKV로 잘못 감지되던 문제를 수정했습니다. #106009 (Avogar).
  • 유효한 시각 범위를 벗어난(음수 또는 >= 24h) Time/Time64 값을 Arrow 포맷으로 내보내면, 이제 잘못된 Arrow time32/time64 데이터를 기록하지 않고 명확한 오류를 반환합니다. #107179 (tiandiwonder).
  • 타임스탬프 컬럼의 시간대가 고정 숫자형 UTC 오프셋(예: +05:30, -08:00, 00:00)이거나 IANA 형식이 아닌 마커 fixed로 지정된 Arrow, ArrowStream 및 Arrow 기반 ORC 파일을 읽을 때 Cannot load time zone ...(BAD_ARGUMENTS) 오류로 실패하던 문제를 수정했습니다. #108633 (groeneai).
  • 이제 Nullable(Tuple(...)) 컬럼을 여러 컬럼으로 평탄화하지 않고 단일 CSV 필드로 직렬화합니다. 이전에는 null이 아닌 값은 여러 CSV 필드로, NULL은 단일 \N으로 기록되어 행마다 컬럼 수가 달라졌고, 그 결과 CSVWithNames/CSVWithNamesAndTypes 헤더와 왕복 변환이 깨졌습니다. #108959 (groeneai).
  • MsgPack 포맷의 스키마 추론 중 과도한 메모리 할당이 발생하던 문제를 수정했습니다. 배열/맵/문자열/바이너리 헤더에 매우 큰 원소 개수가 선언된, 손상되었거나 퍼징된 입력으로 인해 수 기가바이트에 달하는 단일 할당이 더 이상 발생하지 않으며, 이러한 입력은 이제 잘못된 형식의 입력으로 거부됩니다. 이로써 새니타이저 환경에서 발생하던 allocation-size-too-big 중단과 릴리스 빌드에서 발생하던 메모리 부족 문제가 해결되었습니다. #109019 (groeneai).
  • output_format_arrow_low_cardinality_as_dictionary = 1 설정으로 LowCardinality(Time) 컬럼을 Arrow 포맷으로 쓸 때 발생하던 LOGICAL_ERROR를 수정했습니다. #109730 (groeneai).
  • Dynamic 타입 개수 또는 JSON/Object 경로 개수가 SIZE_MAX에 가까운 손상된 Native 포맷 스트림을 읽을 때 발생하던 문제를 수정했습니다. 이러한 잘못된 형식의 입력은 이제 처리되지 않은 std::length_error 대신 명확한 INCORRECT_DATA 오류와 함께 거부됩니다. #110590 (alexey-milovidov).
  • 이전(버전 0) 상태 포맷으로 직렬화된 Bool 값을 가진 sumMap/sumMapWithOverflow/sumMapFiltered 집계 상태를 병합할 때 발생하던 LOGICAL_ERROR: Cannot sum Bools(디버그/새니타이저 빌드에서는 서버 중단)를 수정했습니다. 이번 수정으로 버전 0 Bool 상태에서 오류 없이 잘못된 결과가 반환되던 두 가지 문제도 함께 해결되었습니다. Bool 타입의 맵 키가 상태 간에 중복 제거되지 않던 문제와, 0 값 압축 과정에서 엉뚱한 항목이 삭제되던 문제입니다. #110922 (groeneai).
  • 입력 데이터를 파싱한 결과 행이 0개일 때(예: 빈 JSON 또는 피처가 없는 GeoJSON FeatureCollection) format 테이블 함수에서 NOT_FOUND_COLUMN_IN_BLOCK이 발생하던 문제를 수정했습니다. 이제 올바른 컬럼으로 구성된 빈 결과를 반환합니다. #111428 (groeneai).
  • 이제 WKT로 인코딩된 지오메트리 컬럼에 대문자가 아닌 타입 키워드(point(1 2))나 빈 컨테이너(LINESTRING EMPTY, POLYGON(), POLYGON(()))가 사용된 GeoParquet, Arrow, ArrowStream 파일도 읽을 수 있습니다. 이전에는 동일한 문자열을 readWKT 함수로는 파싱할 수 있었음에도 이러한 파일을 가져올 때 BAD_ARGUMENTS 또는 CANNOT_PARSE_NUMBER 오류가 발생했습니다. 또한 빈 지오메트리에 대한 wkt 출력(LINESTRING()으로 표기됨)을 저장한 파일을 다시 읽지 못하던 문제도 함께 수정되었습니다. #112020 (groeneai).
  • auto 및 none 압축 힌트를 전부 소문자가 아닌 형태로 작성하면(예: file('data.csv.gz', 'CSV', 'x String', 'AUTO')) Unknown compression method가 발생하던 문제를 수정했습니다. GZIP 등의 코덱 이름은 이미 대소문자 구분 없이 허용되었으며, 이제 이 두 특수 힌트도 동일하게 동작합니다. #113631 (groeneai).
  • CSV 이스케이프 규칙을 사용하는 CustomSeparated, Regexp, Template 포맷에서 첫 번째 원소가 NULL인 Tuple 컬럼을 읽을 때 발생하던 문제를 수정했습니다. 이러한 포맷에서 단독 Tuple은 원소마다 필드 하나를 차지하므로, 맨 앞의 \N 필드는 컬럼 전체가 아니라 해당 원소를 나타냅니다. 이전에는 이 필드가 컬럼 전체로 처리되어 나머지 원소 필드가 뒤따르는 컬럼으로 밀려났고, 그 결과 CustomSeparated가 자신의 출력을 다시 읽지 못했습니다. #114471 (groeneai).
  • Regexp 입력 형식이 일치한 필드에서 파싱되지 않은 나머지 부분을 아무런 알림 없이 버려, 오류를 보고하는 대신 잘리거나 엉뚱한 값을 저장하던 문제를 수정했습니다. 예를 들어 JSON 규칙에서 v=-1을 UInt64로 읽으면 0이, v=2020-01-01junk를 Date로 읽으면 1975-07-14가 저장되었습니다. 이제 Escaped, CSV, JSON 규칙에서는 잘못된 형식의 필드를 거부하며, 이는 각 규칙의 기준으로 문서화된 포맷의 동작과 일치합니다. Raw 규칙에서는 탭이 포함된 일치 필드를 탭 위치에서 자르지 않고 전체를 읽습니다. #114520 (groeneai).
  • 포맷-파싱-포맷 왕복 과정에서 동일하게 유지되지 않는 CREATE INDEX / CREATE HYPOTHETICAL INDEX 표현식(예: CREATE HYPOTHETICAL INDEX i0 ON t0 ((a())) TYPE a, CREATE INDEX i0 ON t0 ((a, b).1) TYPE minmax)에서 발생하던 Inconsistent AST formatting 논리 오류(디버그 및 새니타이저 빌드에서 서버 중단)를 수정했습니다. #109175 (groeneai).
  • 포맷 수준의 키 조건이 Parquet 파일에서 읽지 않는 컬럼을 참조할 때 Parquet v3 리더에서 발생하던 논리 오류(Logical error: 'KeyCondition uses PREWHERE output')를 수정했습니다. #109267 (groeneai).
  • 헤더가 없을 때 사전 정의된 HTTP 핸들러에서 발생하던 예외를 수정했습니다. #108324 (vitlibar).
  • 행 기반 입력 형식(예: TSV/CSV)이 입력 파싱에 실패했는데 하위 읽기 작업이 이미 취소된 경우(예: 잘못된 HTTP 청크 또는 잘린 본문) 발생할 수 있던 Logical error: 'ReadBuffer is canceled. Can't read from it.'를 수정했습니다. 이제 상세 파싱 진단 정보를 생성할 때 취소된 버퍼에서 읽지 않습니다. #109708 (groeneai).
  • 스트리밍 파싱이 SQL 표현식 파싱으로 정상 폴백되는 경우, Values 포맷이 더 이상 system.errors 및 system.error_log에 파싱 오류를 기록하지 않습니다. #111141 (pamarcos).
  • 중지된 RabbitMQ 테이블에서 SYSTEM REFRESH가 대기 중인 백로그를 간헐적으로 소비하지 못하던 문제를 수정했습니다. REFRESH는 순서와 무관한 스트리밍 사이클을 정확히 한 번만 허용하는데, AMQP 전달 루프가 막 비동기로 시작된 상태여서 해당 사이클이 0개의 행으로 즉시 반환될 수 있었습니다. 그 결과 단 한 번의 기회가 낭비되어 다음 SYSTEM START까지 메시지가 소비되지 않은 채 남았습니다. #111480 (groeneai).
  • nats_stream이 설정된 NATS 테이블이 NATS 서버 재시작 후 아무런 알림 없이 메시지를 전혀 소비하지 않던 문제를 수정했습니다. 이제 DETACH TABLE 및 ATTACH TABLE을 실행하지 않아도 JetStream subscription이 자동으로 다시 설정됩니다. #112828 (groeneai).
  • 지나치게 큰 kafka_num_consumers 값을 지정하면 Kafka 테이블 엔진 내부에서 메모리 할당에 실패하는 대신 명확한 오류와 함께 거부합니다. 이전에는 kafka_disable_num_consumers_limit이 활성화된 상태에서 이러한 값을 지정하면 std::length_error 예외가 발생했습니다. #114764 (alexey-milovidov).
  • Arrow Flight 서버: ADBC Flight SQL 드라이버 등 Go 기반 Flight 클라이언트가 전송하는, 패딩 없이 Base64로 인코딩된 Basic 인증 자격 증명을 허용합니다. 또한 authorization 헤더 형식이 잘못된 경우 일반적인 Unexpected error in RPC handling 대신 적절한 인증 오류를 반환합니다. #115085 (alexey-milovidov).
  • Arrow Flight 서버: 사용자 이름/비밀번호 구분자가 누락된 잘못된 형식의 기본 인증 자격 증명을 거부하도록 수정했습니다. #115347 (alexey-milovidov).

데이터 타입, 함수 및 직렬화 관련 수정 사항

  • Wide 파트가 있는 테이블에서 ALTER TABLE ... MODIFY COLUMN으로 컬럼을 동적 서브컬럼을 갖는 타입으로 변경(예: Variant에서 Dynamic으로)한 후 해당 파트를 읽거나 병합할 때 발생하던 논리적 오류 Stream <col>.variant_discr ... is not found(디버그 및 새니타이저 빌드에서는 서버 중단)를 수정했습니다. #110204 (groeneai).
  • 요소가 널을 허용하지 않는 LowCardinality(T)인 Nullable(Tuple(...)) 컬럼의 서브컬럼을 읽으면서 같은 쿼리에서 상위 서브컬럼도 함께 읽을 때 발생하던 문제를 수정했습니다. Compact 파트에서는 추출된 서브컬럼이 LowCardinality(Nullable(T)) 버퍼로 역직렬화된 뒤 그 하위 스트림이 상위 서브컬럼의 읽기와 공유되었기 때문에, 상위 서브컬럼이 잘못된 값을 반환하거나, 쿼리가 Unexpected return type from assumeNotNull 오류로 실패하거나, string_view 강화 어설션에 의해 서버가 종료되었습니다. #112232 (groeneai).
  • 통계 기반 파트 프루닝이 인덱스 분석 중에 IN/GLOBAL IN 서브쿼리를 추측 실행하다가 해당 서브쿼리가 실패하면 LOGICAL_ERROR “Not-ready Set is passed as the second argument for function globalNullIn” 오류가 발생하고 쿼리의 실제 오류 메시지가 손실되던 문제를 수정했습니다. #114121 (groeneai).
  • Quantized('product', ...) 코덱을 사용하는 컬럼의 product_quantization_codebook 서브컬럼을 읽을 때 발생하던 Cannot read all data of type FixedString 오류를 수정했습니다. 파트별 코드북은 모든 그래뉼의 데이터 뒤에 기록되므로 마크로 구분되지 않으며, 이 때문에 마크 범위가 파트의 마지막 마크보다 앞에서 끝나는 읽기에서는 코드북을 끝까지 읽지 못할 수 있었습니다. #112818 (alexey-milovidov).
  • Dynamic 컬럼 내부의 Map 값에서 Map 레이아웃이 파트 자체의 메타데이터와 맞지 않는 파트가 기록되지 않도록 했습니다. map_serialization_version만 다른 테이블들이 캐시된 직렬화 객체 하나를 공유했기 때문에, 메타데이터에는 with_buckets로 선언되어 있는데도 파트에는 basic Map 레이아웃이 적용될 수 있었고, 이후 해당 파트를 읽으면 LOGICAL_ERROR: Stream ...buckets_info ... is not found 오류로 실패했습니다. 이전 버전에서 이미 이렇게 기록된 파트는 여전히 읽을 수 없으므로 삭제해야 합니다. #113514 (groeneai).
  • ALP, FPC, GCD가 타입에서 파생된 파라미터를 코덱 해시에 포함하지 않던 문제를 수정했습니다. Compact 파트에서 writer는 서로 다른 코덱 해시마다 압축 스트림 하나를 공유하므로, 같은 코덱을 사용하지만 값 너비가 다른 두 컬럼이 충돌하여 잘못된 너비를 가진 코덱 객체 하나를 공유하게 되었습니다. 이로 인해 너비가 맞지 않으면 유효한 삽입이 CANNOT_COMPRESS 오류로 거부되었고, 그렇지 않더라도 두 컬럼 중 하나가 본래보다 비효율적으로 압축되었습니다. #114189 (groeneai).
  • 테이블의 정렬 키가 Date 컬럼을 toDateTime으로 감싸고(예: ORDER BY toDateTime(date_column)) 쿼리가 WHERE date_column >= '...'와 같은 비교 조건으로 원래 컬럼을 필터링할 때 발생하던 잘못된 인덱스 프루닝을 수정했습니다. toDateTime(Date)는 DateTime 범위를 벗어나는(2106-02-07 이후) Date 값에서 오버플로가 발생하므로 저장된 키가 단조적이지 않습니다. 이 상태에서 프라이머리 키 프루닝을 사용하면 일치하는 행이 포함된 그래뉼이 제외될 수 있으므로, ClickHouse는 이 키/조건 조합에 더 이상 프라이머리 키 프루닝을 적용하지 않습니다. #101814 (nihalzp).
  • DEFAULT가 지정된 Nullable 컬럼을 다른 타입(예: Nullable(UInt8) → String,LowCardinality(String) 또는 Array(UInt8))으로 변환할 때 ALTER MODIFY COLUMN이 실패하던 문제를 수정했습니다. #102156 (il9ue).
  • SQLite로 WHERE 프레디케이트를 푸시할 때 StorageSQLite 및 sqlite() 테이블 함수에서 SQL 리터럴 이스케이프가 잘못 수행되던 문제를 수정했습니다. 작은따옴표와 제어 문자(\n, \r, \t, \)가 백슬래시로 이스케이프되었는데, SQLite는 이를 해석하지 않아 구문 오류가 발생하거나 잘못된 쿼리 결과가 반환되었습니다. 또한 PostgreSQL로 푸시다운되는 문자열 리터럴의 이스케이프도 수정했습니다. 기존에는 IN 목록 내부에 중첩된 문자열에 ClickHouse 방식의 이스케이프가 그대로 남아 있었고, 제어 문자가 백슬래시 시퀀스로 전송되어 PostgreSQL에서 다른 바이트로 해석되었습니다. #104217 (tiandiwonder).
  • query_plan_convert_join_to_in이 활성화되어 있고 SELECT가 소스 배열 컬럼을 참조할 때 INNER JOIN ... ON arrayJoin(...) = ... 쿼리에서 NOT_FOUND_COLUMN_IN_BLOCK 예외가 발생하던 문제를 수정했습니다. #104809 (tiandiwonder).
  • 상수가 아닌 우변 피연산자가 현재 행의 컬럼을 참조하는 IN 및 NOT IN 표현식의 문제를 수정하고, 새 분석기의 튜플 우변 처리를 기존 ClickHouse IN 의미 체계에 맞게 조정했습니다. 이전 분석기에서는 우변에 원본 컬럼만 단독으로 사용하면(x IN (arr)) 여전히 테이블 이름으로 해석되어 범위에서 제외됩니다. #104993 (niyue).
  • String 또는 Nullable(String) 키로 DirectKeyValueJoin을 사용할 때 EmbeddedRocksDB, Redis, KeeperMap 테이블에 대한 JOIN이 아무런 오류 없이 0개의 행을 반환할 수 있던 문제를 수정했습니다. #105253 (vdimir).
  • 비등가 JOIN ... ON 프레디케이트가 ARRAY JOIN []으로 생성된 컬럼처럼 Nothing 유형의 컬럼을 참조할 때 발생하던 LOGICAL_ERROR(“Unexpected expression in JOIN ON section. Expected boolean (UInt8), got ‘Nothing’“)를 수정했습니다. #106981 (groeneai).
  • 별칭이 지정된 람다가 표현식 목록의 첫 번째가 아닌 위치에서 접근 연산자(.N 튜플 원소 또는 [] 배열 원소)의 피연산자로 사용될 때(예: SELECT 1, ((p0, p1) -> p0 AS a7).4[3] FROM t) 디버그 및 sanitizer 빌드에서 서버가 비정상 종료될 수 있던 Inconsistent AST formatting 논리 오류를 수정했습니다. #107092 (groeneai).
  • clusterAllReplicas(..., urlCluster(...))처럼 다른 분산 쿼리 내부에 중첩된 클러스터 테이블 함수(urlCluster, fileCluster, s3Cluster 등)는 이제 논리 오류(Distributed task iterator is not initialized)로 실패하지 않고 BAD_ARGUMENTS 오류와 함께 거부됩니다. #107107 (groeneai).
  • 정밀도가 낮은 부동소수점 컬럼에서 정확히 표현할 수 없는 십진 리터럴(예: Float32 컬럼의 0.1)을 사용하면(예: SELECT * FROM values('x Float32', 0.1)) values 테이블 함수가 ARGUMENT_OUT_OF_BOUND로 실패하던 문제를 수정했습니다. 이제 이러한 값은 CAST 및 INSERT ... VALUES와 마찬가지로 허용되며, 표현 가능한 가장 가까운 값으로 변환됩니다. #108055 (alexey-milovidov).
  • mapFilter, mapSort(및 그 변형), mapConcat이 Map의 키 및 값 유형에서 LowCardinality를 제거하던 문제를 수정했습니다. 이전에는 Map(LowCardinality(String), String) 컬럼에 mapFilter를 적용하면 Map(String, String)이 반환되어, CREATE TABLE ... AS SELECT로 생성된 테이블의 메타데이터가 손상되고 CHECK TABLE이 실패할 수 있었습니다. #108057 (alexey-milovidov).
  • 스킵 인덱스(예: 카디널리티가 높은 컬럼에 대한 무제한 set(0) 인덱스)를 빌드하는 동안 취소되었거나 KILL된 INSERT가 오랫동안 계속 실행되던 문제를 수정했습니다. 이제 쿼리가 취소되면 인덱스 빌드가 즉시 중단됩니다. #108351 (tiandiwonder).
  • primes 테이블 함수에 대한 SELECT가 취소 요청에 응답하지 않던 문제를 수정했습니다. step(또는 limit) 값이 크면 KILL QUERY나 타임아웃 이후에도 쿼리가 오랫동안 계속 실행될 수 있었습니다. 이제 즉시 중단됩니다. #108353 (tiandiwonder).
  • 이름에 부분 문자열 INT가 포함된 데이터 타입 이름(예: 데이터 타입 위치에 사용된 quantileInterpolatedWeighted와 같은 함수 형태의 이름)의 파싱 문제를 수정했습니다. 이러한 이름이 MySQL 정수 타입으로 잘못 인식되어 첫 번째 (...) 인수 그룹이 표시 너비 수정자로 간주되어 경고 없이 제거되었으며, 이로 인해 쿼리 포맷팅 왕복 변환(round-trip)이 깨질 수 있었습니다. #108354 (groeneai).
  • 잘못된 형식의 ARRAY JOIN 뒤에 쉼표와 괄호로 묶인 테이블 목록이 오면 거부되지 않고 크로스 조인으로 잘못 파싱되던 불일치 문제를 수정했습니다. #108365 (Algunenano).
  • 분산 쿼리가 구조적으로 동일한 중복 ALIAS 컬럼을 중복 제거하는 동시에 key = value 형식의 named collection 인수를 사용하는 테이블 함수(예: oss(s3_conn, filename = '...'))를 참조할 때 발생하던 LOGICAL_ERROR(“Invalid action query tree node …”) 예외를 수정했습니다. #108435 (groeneai).
  • 분산 테이블에서 둘 이상의 LowCardinality 인수를 사용하는 함수 호출(예: remote()와 함께 GROUP BY 키로 사용된 concatAssumeInjective((SELECT toLowCardinality('p')), s)) 시 발생할 수 있던 논리 오류(릴리스 빌드에서는 예외 발생, 디버그 및 새니타이저 빌드에서는 서버 중단)를 수정했습니다. 오류 메시지는 Default functions implementation for LowCardinality is supported only with a single LowCardinality argument 또는 Expected the argument ... to have N rows, but it has M였습니다. #108871 (groeneai).
  • 서버에서 해석되는 DateTime/DateTime64 문자열 리터럴(비동기 INSERT, SELECT 리터럴)에 use_client_time_zone이 적용되지 않던 문제를 수정했습니다. 이제 use_client_time_zone이 활성화되면 클라이언트가 로컬 시간대를 session_timezone으로 전달하므로, 서버 측 파싱 결과가 동기 INSERT 경로와 일치합니다. #109051 (groeneai).
  • max_execution_time(timeout_overflow_mode = 'throw' 설정 시)이 쿼리를 취소하지 못하는 경우가 있던 문제를 수정했습니다. 내부 타임아웃 감시자가 이미 기한이 더 늦은 쿼리를 기다리고 있을 때 나중에 등록된 기한이 더 이른 쿼리를 완전히 놓칠 수 있었고, 이 경우 해당 쿼리가 제한 시간을 한참 넘겨 실행되었습니다. #109792 (tiandiwonder).
  • 분석기가 활성화된 상태에서 Distributed 테이블에 대한 쿼리가 Nullable로 바뀐 _shard_num(또는 shardNum())을 ORDER BY와 함께 사용할 때(예: join_use_nulls = 1인 FULL JOIN) 발생하던 NOT_FOUND_COLUMN_IN_BLOCK 오류를 수정했습니다. #109798 (groeneai).
  • enable_join_runtime_filters = 1(26.2부터 기본적으로 활성화됨)이 설정된 조인에서 빌드 측 조인 키가 NULL을 포함하는 LowCardinality(Nullable(...))이고 런타임 필터(runtime filter)가 블룸 필터로 대체될 때 발생할 수 있던 NOT_IMPLEMENTED 오류(“Method getDataAt is not supported for Nullable(String)“)를 수정했습니다. #109824 (groeneai).
  • 고차 함수(higher-order function)가 구체적인 값을 받아야 하는 위치(예: arrayFold(lambda, arr, another_lambda)와 같이 arrayFold의 누산기(accumulator) 위치)에 람다 표현식이 전달되면 서버 크래시가 발생하던 문제를 수정했습니다. 이제 enable_analyzer = 0일 때 이러한 쿼리는 크래시를 일으키지 않고 ILLEGAL_TYPE_OF_ARGUMENT 오류와 함께 거부됩니다. #109840 (groeneai).
  • 행 정책(row policy) 필터에서 arrayJoin의 별칭인 unnest를 사용할 수 없도록 하여, 이러한 정책이 읽기 시점에 column->size() == num_rows 논리 오류(logical error)를 일으킬 수 있던 허점을 해결했습니다. #109973 (Algunenano).
  • 같은 쿼리에서 전체 튜플도 함께 읽는 경우(예: SELECT *) 필드를 tupleElement(t, 'name'), tupleElement(t, N) 또는 t.N으로 액세스하면 Tuple 서브컬럼에 정의된 스킵 인덱스가 사용되지 않던 문제를 수정했습니다. 이제 이 모든 형식에서도 이름 기반 서브컬럼 액세스 t.name과 동일한 방식으로 그래뉼을 제외합니다. #110056 (groeneai).
  • text, tokenbf_v1 또는 ngrambf_v1 스킵 인덱스가 있는 Array(String) 컬럼을 배열 리터럴(arr = ['x'])과 비교할 때 발생하던 BAD_GET 오류를 수정했습니다. 이제 이러한 비교는 쿼리 전체를 실패시키지 않고, 인덱스에서 전체 스캔으로 처리됩니다. #110057 (groeneai).
  • 적용 시점에 컬럼이 이미 존재하면 ALTER TABLE ... ADD COLUMN IF NOT EXISTS에서 불필요하게 ILLEGAL_COLUMN 오류가 발생하던 문제를 수정했습니다. 이 문제는 하나의 구문에서 IF NOT EXISTS로 같은 컬럼을 두 번 추가하거나, 준비 단계와 적용 단계 사이에 동시 실행된 다른 ALTER가 해당 컬럼을 추가한 경우에 발생했습니다. #110080 (groeneai).
  • identity()(또는 스칼라 서브쿼리 결과)가 중첩된 LowCardinality를 포함하는 값을 감싸고, 쿼리에서 WITH TOTALS/WITH ROLLUP을 사용할 때 발생하던 LOGICAL_ERROR(Bad cast from type ColumnLowCardinality to ColumnString)를 수정했습니다. #110138 (groeneai).
  • 튜플 표현식에 GROUP BY ALL을 ORDER BY와 함께 사용할 때 발생하던 NOT_FOUND_COLUMN_IN_BLOCK 오류를 수정했습니다. #110206 (alexey-milovidov).
  • 서브컬럼(예: Nullable 컬럼의 x.null 또는 Array의 arr.size0)을 참조하는 CHECK 제약 조건이 있는 테이블에 INSERT할 때 발생하던 NOT_FOUND_COLUMN_IN_BLOCK 오류를 수정했습니다. #110208 (alexey-milovidov).
  • 기본적으로 활성화되어 있는 optimize_and_compare_chain 최적화로 인해 잘못된 쿼리 결과가 반환되던 문제를 수정했습니다. 체인에 쌍별 변환 규칙이 다른 타입이 섞여 있으면(예: Enum과 String, Decimal과 Float64, 너비가 다른 FixedString) a < b AND b < c에서 추이성으로 도출된 조건이 원래 조건과 다른 비교 의미를 사용할 수 있었습니다. 이제 추이적 조건은 단일 비교 순서를 공유하는 타입 그룹 내에서만 도출됩니다. #110621 (yariks5s).
  • optimize_injective_functions_in_group_by가 GROUP BY GROUPING SETS 및 GROUP BY ... WITH TOTALS의 쿼리 결과를 변경하던 문제를 수정했습니다. 이 설정은 결과를 변경하지 않는 것으로 문서화되어 있지만, 그룹화 키에 적용된 단사(injective) 함수를 제거하면 해당 키가 집계 집합에 포함되지 않은 행(GROUPING SETS에서 해당 키를 포함하지 않는 집합) 또는 WITH TOTALS 행에서 잘못된 값이 생성되거나 행이 누락되었습니다. 이 잘못된 값이 실제 키 값과 우연히 같아질 수 있었기 때문에, 동일한 결과 집합 안에서 상위 집계 행과 실제 그룹을 구분할 수 없었습니다. #110721 (groeneai).
  • median/quantile(ReservoirSampler 기반) 집계 함수 상태에 매우 큰 정수 상수를 곱할 때(예: medianState(x) * 18446744073709551615) 서버가 멈추는 문제를 수정했습니다. 이 경우 쿼리가 취소 요청에 응답하지 않고 무기한 실행될 수 있었습니다. #110779 (groeneai).
  • JSON 인수에 내부 유형 힌트 서브컬럼 이름(백틱 유형 표식으로 시작하는 이름)을 지정하여 getSubcolumn을 호출할 때 발생하던 크래시(쿼리 분석 중 널 포인터 역참조)를 수정했습니다. #110940 (groeneai).
  • map[key]가 첫 번째 키가 아닌 뒤에 나오는 중복 키의 값을 반환하던 문제를 수정했습니다. Map 컬럼에 중복 키가 있으면 map[key]의 결과가 같은 블록의 앞선 행과 optimize_functions_to_subcolumns 설정에 따라 달라질 수 있었으며, 그 결과 같은 행에 대한 SELECT와 WHERE의 결과가 서로 다를 수 있었습니다. #111246 (groeneai).
  • use_variant_default_implementation_for_comparisons = 0일 때 AND 체인에서 컬럼을 Nullable이 아닌 유형의 NULL 값 상수(예: NULL 값을 가진 Variant)와 비교하면 논리 표현식 최적화기에서 논리 오류 !rhs_literal->getValue().isNull()이 발생하던 문제를 수정했습니다. #111292 (groeneai).
  • 쿼리에 set 스킵 인덱스가 있고 (x AND <null-value>) OR y 형태의 조건식에서 NULL이 함수로 생성되는 경우(예: toInt64OrNull('x'), nullIf(1, 1), CAST(NULL AS Nullable(Int64))) 잘못된 결과가 반환되던 문제를 수정했습니다. 이러한 값이 __bitWrapperFunc로 래핑되면서 “unknown” 마스크 대신 NULL이 전파되었고, 이로 인해 set 인덱스가 실제로 조건에 맞는 그래뉼까지 제외하여 쿼리가 반환해야 할 행보다 적은 행을 반환했습니다. #111604 (groeneai).
  • 분석기를 사용할 때 CREATE TABLE/ALTER TABLE에서 _table이나 _database 같은 가상 컬럼을 참조하는 컬럼 DEFAULT/MATERIALIZED 표현식이 허용되던 문제를 수정했습니다. 이런 테이블에 삽입하면 NOT_FOUND_COLUMN_IN_BLOCK 오류가 발생했고, MATERIALIZED 컬럼(값을 명시적으로 지정할 수 없음)이 있으면 테이블에 영구적으로 삽입할 수 없었습니다. 이제 이러한 표현식은 정의 시점에 거부되며, 이는 분석기를 사용하지 않을 때의 동작과 같습니다. 가상 컬럼을 참조하는 ALIAS 컬럼(읽기 시점에 계산)과 EPHEMERAL 컬럼(저장되지 않는 삽입 입력)은 계속 정상적으로 동작합니다. #111776 (groeneai).
  • 매개변수화된 뷰(parameterized view)를 Array, Tuple 또는 LowCardinality 유형의 값을 반환하는 서브쿼리 인수로 호출할 때(예: SELECT * FROM v(param = (SELECT groupArray(x) FROM t))) UNKNOWN_QUERY_PARAMETER 오류가 발생하던 문제를 수정했습니다. #111790 (groeneai).
  • 비교 연산의 연쇄(x = c1 OR x = c2 OR ..., x != c1 AND x != c2 AND ..., has(const_array, x))를 IN/NOT IN으로 변환하는 분석기 재작성에서 발생하던 버그 3개를 수정했습니다. use_variant_default_implementation_for_comparisons = 0인 Variant 표현식에서는 재작성으로 인해 표현식 결과 유형이 UInt8에서 Nullable(UInt8)로 바뀌었고, 그 결과 디버그 및 새니타이저 빌드의 쿼리 트리 검증 단계에서 LOGICAL_ERROR가 발생했습니다. 동적 구조를 가진 표현식(Dynamic, Array(Dynamic), JSON)에서는 IN이 이러한 인수를 허용하지 않기 때문에, 재작성 후 정상적으로 동작하던 쿼리가 Illegal type ... of argument of function in 오류와 함께 실패했습니다. 또한 상수가 표현식의 유형으로 손실 없이 변환되지 않을 때(예: 시각 정보가 포함된 DateTime 상수를 Date 컬럼과 비교하는 경우) 두 방향 모두 잘못된 결과를 반환했습니다. #111924 (groeneai).
  • 쿼리가 병렬 레플리카, 분산 테이블 또는 외부 집계를 사용하거나 상태가 테이블에 저장된 경우(Dynamic 값 내부 포함), quantileDeterministic, quantilesDeterministic, medianDeterministic이 동일한 데이터에 대해 실행할 때마다 다른 결과를 반환하던 문제를 수정했습니다. 이 버전 이전에 버전 정보가 없는 유형 표기로 기록된 상태는 레이아웃을 변경할 수 없으므로 기존 동작을 유지합니다. #112052 (alexey-milovidov).
  • 벡터 검색 쿼리가 쿼리 조건 캐시를 오염시켜 잘못된 결과가 반환되던 문제를 수정했습니다. vector_similarity 인덱스가 있는 테이블에 대한 SELECT ... WHERE <condition> ORDER BY <distance function> LIMIT n 쿼리가 그래뉼을 <condition>과 일치하지 않는 것으로 기록할 수 있었고, 이 때문에 이후 같은 테이블에 대해 실행한 일반 SELECT ... WHERE <condition> 쿼리가 별다른 경고 없이 더 적은 행을 반환했습니다. 이제 벡터 검색 읽기는 쿼리 조건 캐시에 기록하지 않습니다. #112086 (groeneai).
  • 직렬화된 쿼리 계획에서 serialize_string_in_memory_with_zero_byte가 누락되던 문제를 수정했습니다. serialize_query_plan = 1일 때 이 설정을 비활성화한 클러스터에서는 개시 노드와 역직렬화된 계획을 실행하는 노드 간에 메모리 내 문자열 표현이 서로 달라질 수 있었습니다. 해당 설정이 역직렬화 시에는 읽히지만 직렬화 시에는 기록되지 않아, 실행 노드에서는 항상 기본값이 적용되었기 때문입니다. #112131 (groeneai).
  • ON l.id = r.id AND CAST(NULL AS Nullable(UInt8))처럼 ON 표현식에 상수 논리곱 항이 포함된 JOIN에서 잘못된 결과가 반환되던 문제를 수정했습니다. 쿼리 계획 최적화 과정에서 해당 상수가 별다른 경고 없이 제거되어, 조인이 마치 상수가 없는 것처럼 실행되었습니다. 그 결과 INNER, LEFT SEMI, RIGHT SEMI 조인은 항상 거짓인 조건이므로 아무 행도 반환하지 않아야 하는데도 일치하는 행을 반환했고, RIGHT ANTI는 모든 행을 반환해야 하는데도 아무 행도 반환하지 않았습니다. #112155 (vdimir).
  • 매개변수화된 뷰(parameterized view)를 parameter = value 형식의 할당이 아닌 인수로 호출하면 잘못된 결과가 반환되던 문제를 수정했습니다. enable_analyzer = 0인 경우와 기본 설정의 EXPLAIN SYNTAX에서 pv(concat(name, '!')), pv(name, 'a'), pv(name != 'a'), pv(tuple(name = 'a')) 같은 호출은 분석기처럼 UNKNOWN_QUERY_PARAMETER를 보고하지 않고, 별다른 경고 없이 뷰 매개변수를 관련 없는 표현식에 바인딩했습니다. 이제 이러한 호출은 두 실행 경로 모두에서 동일하게 거부됩니다. #112194 (groeneai).
  • 정의에서 substring 문법으로 다시 파싱할 수 없는 형태로 substr, mid 또는 byteSlice를 호출하는 CREATE VIEW 또는 CREATE FUNCTION은 생성은 허용되지만, ClickHouse가 기록하는 메타데이터가 유효한 SQL이 아니던 버그를 수정했습니다. 이후 해당 정의를 읽으면 SYNTAX_ERROR로 실패했고, 서버 시작 시에는 메타데이터 로딩이 중단되어 서버가 아예 시작되지 않았습니다. 이제 이러한 정의도 왕복이 가능하며, substring(x, a, b, c) 형태의 기존 메타데이터 파일도 다시 읽을 수 있으므로 영향을 받은 서버가 수동 조치 없이 시작됩니다. #112195 (groeneai).
  • 프라이머리 키가 Array 또는 Tuple이고 쿼리에서 여기에 plus, minus, multiply, divide 또는 intDiv를 적용하면 잘못된 결과, 잘못 정렬된 ORDER BY 출력, BAD_TYPE_OF_FIELD 예외가 발생하던 문제를 수정했습니다. 복합 값에 대한 산술 연산은 요소별로 평가되지만 복합 값의 비교는 사전식으로 이루어지므로, 이제 프라이머리 키 분석에서 이러한 표현식을 단조(monotonic)로 간주하지 않습니다. #112339 (groeneai).
  • 왼쪽 테이블이 Distributed 테이블이거나 *Cluster 테이블 함수인 경우처럼 PASTE JOIN을 포함한 쿼리가 다른 서버로 전송될 때, 원격 서버에서 Code: 62 ... You must not specify ANY or ALL for PASTE JOIN. (SYNTAX_ERROR)가 발생하던 문제를 수정했습니다. 포매터가 파서에서 허용하지 않는 표기인 ALL PASTE JOIN을 출력했기 때문에 수신 서버가 전달받은 쿼리를 파싱할 수 없었습니다. #112404 (groeneai).
  • (SELECT 1) AS t(x) 또는 WITH t(x) AS (SELECT 1)과 같은 컬럼 별칭 목록이 view 테이블 함수 내부에서 인식되지 않아, view 외부에서는 동일한 구문이 정상 동작하는데도 t.x 참조가 UNKNOWN_IDENTIFIER로 실패하던 문제를 수정했습니다. #112690 (groeneai).
  • ARRAY JOIN 절에 표현식이 없을 때 쿼리 포맷팅 중 논리 오류가 발생하던 문제를 수정했습니다. 이제 이러한 절은 허용된 후 다시 파싱할 수 없는 텍스트로 포맷팅되지 않고, 빈 USING과 마찬가지로 파싱 단계에서 SYNTAX_ERROR로 거부됩니다. #112699 (groeneai).
  • 서브쿼리용으로 준비된 표현식 액션이 빌드 시 사용된 Context가 해제된 뒤에 실행되면 connectionId에서 Context has expired 예외가 발생하던 문제를 수정했습니다. #112870 (clickgapai).
  • 조인 중에 평가되는 비등가(non-equi) JOIN ON 조건에 arrayJoin이 포함되면 논리 오류와 잘못된 결과가 발생하던 문제를 수정했습니다. 이제 hash, parallel_hash 또는 grace_hash 조인은 이러한 조건을 INVALID_JOIN_ON_EXPRESSION으로 거부합니다. 확장이 한쪽에만 의존한다면 조인 전에 서브쿼리 내 ARRAY JOIN으로 옮기십시오. arrayJoin 인수가 양쪽 컬럼을 모두 읽는 조건은 구조를 재작성해야 합니다. #112889 (groeneai).
  • geohashesInBox(0., 0., 180., 0., 12)처럼 면적이 0인 박스에 대해 geohashesInBox가 제한 없이 시간을 소모하던 문제를 수정했습니다. 이러한 쿼리는 올바른 단일 geohash를 반환하기는 했지만 행마다 약 5e8회의 무의미한 루프를 반복했으며, max_execution_time과 KILL QUERY도 모두 무시했습니다. #112976 (groeneai).
  • 값 없이 작성된 것으로 표시된 SETTINGS 변경에 true가 아닌 값이 포함된 경우 이를 거부하고, 쿼리를 포맷할 때 이러한 변경의 값을 생략하지 않도록 수정했습니다. 이전에는 조작된 AST JSON 페이로드로 Bool 설정을 false로 실행하면서도 system.query_log와 formatQueryFromJSON에는 값이 없는 형태로 표시되게 할 수 있었습니다. #113025 (alexey-milovidov).
  • 선언된 컬럼 타입이 내부 쿼리가 생성하는 타입과 다른 VIEW에서 조회할 때 발생하던 UNKNOWN_IDENTIFIER를 수정했습니다. 예를 들어 v가 String 컬럼에 대해 arr Array(UInt8)를 선언한 상태에서 SELECT sum(length(arr)) FROM v를 실행하는 경우입니다. 기본값인 optimize_functions_to_subcolumns = 1에서는 옵티마이저가 length(arr)를 arr.size0 서브컬럼 읽기로 재작성한 뒤 그 이름을 내부 쿼리로 전달했지만, 내부 쿼리에는 해당 서브컬럼이 존재하지 않았습니다. #113057 (groeneai).
  • postgresql 테이블 함수 및 PostgreSQL 엔진 읽기의 취소 처리를 수정했습니다. 읽기가 시작되는 도중에 취소하면 트랜잭션 포인터에서 경쟁 상태가 발생할 수 있었고, 취소 요청이 아예 유실되어 PostgreSQL이 쿼리를 끝낼 때까지 쿼리가 계속 실행될 수 있었습니다. 단, COPY SQL 문이 실행되기 전에 PostgreSQL에 도달한 취소 요청은 여전히 무시될 수 있습니다. #113150 (groeneai).
  • 클러스터 테이블 함수(s3Cluster, urlCluster, fileCluster) 기반의 SQL SECURITY DEFINER 또는 SQL SECURITY NONE 뷰를 remote나 clusterAllReplicas 등을 통해 보조 쿼리로 읽을 때 발생하던 LOGICAL_ERROR(Next task callback is not set for query)를 수정했습니다. 이제 지원되지 않는 중첩은 debug 및 새니타이저 빌드에서 서버를 중단시키지 않고 일반 쿼리 오류로 거부됩니다. #113371 (groeneai).
  • analyzer_compatibility_join_using_top_level_identifier = 1 설정에서 view(...) 인수를 사용하는 remote 계열 테이블 함수를 SELECT 목록 별칭을 키로 하는 JOIN ... USING의 왼쪽에 사용할 때 발생하던 논리 오류 IDENTIFIER is not a table expression을 수정했습니다. #113400 (groeneai).
  • indexHint 내부의 서브쿼리로 system.databases의 name 컬럼을 필터링하는 쿼리(예: SELECT count() FROM system.databases WHERE indexHint(name IN (SELECT 'foo')))에서 발생하던 Not-ready Set is passed as the second argument for function 'in' 오류를 수정했습니다. 이러한 쿼리는 릴리스 빌드에서는 LOGICAL_ERROR로 거부되었고, debug 및 새니타이저 빌드에서는 서버를 중단시켰습니다. #113556 (groeneai).
  • Variant 컬럼에 대한 쿼리가 max_execution_time 및 KILL QUERY를 무시하던 문제를 수정했습니다. 여러 Variant 인수로 함수를 호출하면 각 인수의 모든 대안마다 함수를 한 번씩 해석했는데, 이 작업을 수행하는 두 루프 모두 취소 여부를 확인하지 않아 해당 쿼리가 끝날 때까지 중지할 수 없었습니다. #113612 (groeneai).
  • 하나의 SQL 문에서 ALIAS 컬럼을 물리 컬럼(DEFAULT 또는 MATERIALIZED)으로 변경하면서 CODEC도 함께 지정하면 ALTER TABLE ... MODIFY COLUMN이 Cannot specify codec for column type ALIAS 오류로 실패하던 문제를 수정했습니다. #113853 (groeneai).
  • 상수 ON 표현식으로 ARRAY JOIN이 포함된 오른쪽 테이블과 조인할 때 발생하던 서버 크래시를 수정했습니다. 지연 복제된 오른쪽 컬럼을 읽을 때 이미 해제된 ColumnReplicated에 접근하는 문제가 있었습니다. #113901 (groeneai).
  • 테이블의 정렬 키가 GROUP BY 키의 진부분 접두사(strict prefix)이고 quantileDD처럼 상태가 힙 메모리를 소유하는 집계 함수를 사용할 때 optimize_aggregation_in_order = 1에서 발생하던 메모리 누수를 수정했습니다. 이러한 쿼리가 실행될 때마다 서버를 재시작하기 전까지 메모리 사용량이 계속 증가했습니다. #114010 (groeneai).
  • UInt128/UInt256에 대한 isProbablePrime이 max_execution_time 및 KILL QUERY를 무시하던 문제를 수정했습니다. 큰 값으로 이루어진 블록이 취소 지점 없이 단일 함수 호출 안에서 끝까지 실행되었기 때문에, 쿼리가 제한 시간을 넘겨 수 분 동안 계속 실행될 수 있었습니다. #114032 (groeneai).
  • PREWHERE 절에 IN (subquery) 프레디케이트가 포함되어 있고 rewrite_in_to_join = 1(또는 이를 강제로 활성화하는 make_distributed_plan = 1)이 설정된 경우 Code: 46. DB::Exception: Unknown function exists. (UNKNOWN_FUNCTION) 오류가 발생하던 문제를 수정했습니다. 동일한 쿼리를 WHERE로 작성하면 정상적으로 동작했습니다. #114067 (RohithPariki).
  • 인수가 원소 타입이 Nothing인 비어 있지 않은 배열일 때(예: SELECT arrayAutocorrelation([arrayMax([])])) arrayAutocorrelation에서 발생하던 LOGICAL_ERROR를 수정했습니다. 이제 이러한 인수는 ILLEGAL_COLUMN 오류와 함께 거부됩니다. 빈 배열 리터럴 []는 기존과 같이 []를 반환합니다. #114249 (groeneai).
  • 이제 CREATE TABLE 및 ALTER TABLE에서 정렬 키에 사용되는 컬럼에 SZ3와 같은 손실 코덱을 지정하면 거부됩니다. #114531 (groeneai).
  • 인터벌 인수의 초 단위 길이가 2^32의 배수일 때(예: toIntervalDay(2147483648)) hop 및 windowID 함수에서 발생하던 취소 불가능한 무한 루프를 수정했습니다. 오버플로된 뺄셈이 시간 오버플로 검사를 우회했고, 인수가 상수이면 루프가 분석 단계에서 실행되어 쿼리를 kill할 수조차 없었습니다. 같은 인터벌로 인해 WINDOW VIEW의 백그라운드 스레드가 무한히 반복 실행될 수도 있었으며, 이제 이러한 윈도우 뷰는 생성 시점에 거부됩니다. #114607 (alexey-milovidov).
  • 원격 클러스터에서 데이터를 읽는 IN 서브쿼리가 포함된 쿼리에서 발생하던 논리 오류 Not-ready Set is passed as the second argument for function 'in'를 수정했습니다. 이제 쿼리는 연결 실패 등 서브쿼리에서 발생한 실제 오류를 반환하며 실패합니다. #114983 (alexey-milovidov).
  • Log, TinyLog 또는 StripeLog 테이블에 대한 INSERT가 기록된 파일 크기를 커밋하는 중에 실패하는 문제를 수정했습니다. 이러한 삽입은 오류를 보고했음에도 행이 테이블에 남아 있거나, 배열 컬럼의 데이터 파일 간 정합성이 깨질 수 있었습니다. 이제 오프셋상으로는 원소가 있다고 표시되지만 실제로는 원소가 없는 배열 컬럼을 가진 Log 또는 TinyLog 테이블을 읽으면, 원소의 끝을 넘어 읽는 대신 해당 컬럼 이름을 명시한 오류가 발생합니다. 부분적으로 기록된 원소 컬럼은 이전부터 거부되었습니다. #115027 (groeneai).
  • has([map('k', 'v')], m)처럼 Array(Map(...)) 타입의 상수를 포함한 쿼리를 Distributed 테이블에서 실행하거나 병렬 레플리카로 실행할 때 발생하던 TYPE_MISMATCH(“CAST AS Array can only be performed between same-dimensional array types”) 오류를 수정했습니다. #115883 (alexey-milovidov).
  • 투영된 컬럼의 이름이 자신의 내부 관계 중 하나에 속한 컬럼 이름과 같은 뷰 또는 view()와 조인할 때 잘못된 결과가 반환되던 문제를 수정했습니다. 예: SELECT expr(x.c0) AS c0 FROM a AS x, b AS y. 조인 순서 최적화기가 이러한 표현식을 평탄화된 조인 그래프에 병합한 뒤 두 번 적용하는 바람에, 쿼리가 오류 없이 왜곡된 값을 반환했습니다. 표현식이 컬럼 타입까지 변경하는 경우에는 같은 원인으로 플랜 생성 시점에 AMBIGUOUS_COLUMN_NAME이 대신 발생했습니다. #116152 (groeneai).
  • ROLLUP/CUBE와 함께 group_by_use_nulls를 사용할 때 외부 컬럼이 Nullable이 되면서 상관 서브쿼리(correlated subquery)에서 예외가 발생하던 문제를 수정했습니다. #100365 (alexey-milovidov).
  • 이제 Replicated 데이터베이스에서 max_replication_lag_to_enqueue = 0을 허용하지 않습니다. 이 값을 사용하면 복구 후 미동기화 검사가 항상 참이 되어, 디버그 및 새니타이저 빌드에서 LOGICAL_ERROR로 서버가 중단되었습니다. 이제 0은 모든 경로(CREATE DATABASE ... SETTINGS, <database_replicated> 서버 설정 블록, ATTACH 재실행, 업그레이드 시 기존 메타데이터 재실행)에서 파싱 시점에 BAD_ARGUMENTS로 거부됩니다. 허용되는 최솟값은 1입니다. #106006 (groeneai).
  • 서로 다른 타입이 섞인 배열을 삽입할 때 NO_COMMON_TYPE 예외가 발생하지 않도록 JSON(Object) 컬럼에 minmax 스킵 인덱스를 생성할 수 없게 했습니다. 대신 타입이 지정된 서브컬럼을 사용하십시오(예: INDEX idx json.field TYPE minmax). #106094 (linhaojie).
  • Dynamic 인수가 주어졌을 때 JSON_QUERY/JSON_VALUE/JSON_EXISTS가 String/UInt8 대신 Dynamic을 반환하던 문제를 수정했습니다. #106877 (Avogar).
  • interactive_delay와 같은 대기 타임아웃 설정을 매우 큰 값으로 지정했을 때 발생하던 부호 있는 정수 오버플로를 수정했습니다. 이 문제로 인해 대기 없이 즉시 타임아웃되거나, Undefined Behavior Sanitizer 환경에서 서버가 중단될 수 있었습니다. #106961 (groeneai).
  • geohashesInBox 함수의 좌표 인수에 상수와 비상수 값이 섞여 있거나 좌표가 BFloat16일 때 발생하던 LOGICAL_ERROR(“Unsupported argument types”)를 수정했습니다. 이제 상수/비상수가 섞인 Float32 인수가 정상적으로 동작하며, BFloat16 인수는 명확한 오류 메시지와 함께 거부됩니다. #107063 (groeneai).
  • output_format_csv_serialize_tuple_into_separate_columns가 활성화된 경우(기본값) CSVWithNames 및 CSVWithNamesAndTypes 헤더의 컬럼 수가 데이터보다 적던 문제를 수정했습니다. 이제 헤더(및 타입 행)는 Tuple 컬럼을 점으로 구분된 이름(예: t.a, t.b)의 리프 필드로 평탄화하므로, 헤더의 컬럼 수가 데이터와 일치합니다. 새 설정 output_format_csv_header_serialize_tuple_into_separate_columns(기본값 1)로 이 동작을 제어할 수 있으며, 0으로 설정하면 이전처럼 단일 이름 헤더를 사용합니다. #107371 (groeneai).
  • MongoDB에서 데이터를 읽을 때(예: MongoDB 딕셔너리 또는 mongodb 테이블 함수 사용 시) 재시도 가능한 읽기 오류 이후 재시도용 서버 선택까지 실패하면, 번들된 mongo-c-driver에서 메모리 누수가 발생할 수 있던 문제를 수정했습니다. #107448 (groeneai).
  • pointInPolygon이 Variant 또는 Dynamic과 같은 래퍼 타입의 상수 폴리곤 인수로 호출될 때(예: pointInPolygon((x, y), if(c, [(0, 0), ...], NULL))) 기본 키 분석 중에 발생하던 논리 오류(WhichDataType(const_type).isArray()) 및 서버 비정상 종료를 수정했습니다. #107589 (groeneai).
  • Variant 및 Dynamic 컬럼 내부에 중첩된 LowCardinality가 일관성 없이 제거되어 concat, format, 기본 키 분석 등에서 발생하던 논리 오류(Bad cast)를 수정했습니다. #107773 (Avogar).
  • 실행형 사용자 정의 함수의 명령 매개변수 파싱을 수정하여, 이름이 비어 있거나 유효하지 않은 플레이스홀더가 매개변수로 허용되지 않도록 했습니다. #107983 (goutamadwant).
  • 원소가 Dynamic/Variant인 Tuple에 accurateCastOrNull을 적용할 때 원본의 실제 NULL이 변환 실패로 처리되던 문제를 수정했습니다. 이제 대상 원소가 Nullable이면 원본 NULL은 원소 NULL로 유지되며(일반 Tuple(Nullable(...)) 원본과 동일), 대상 원소가 Nullable이 아니면 원소 기본값을 생성하는 대신 튜플 전체가 null이 됩니다(Dynamic이 아닌 경우의 동작과 동일). 파싱/오버플로 실패 시에는 이전과 같이 튜플 전체가 null이 됩니다. #108023 (groeneai).
  • 이제 mongodb 테이블 함수는 명명된 인수로 전달된 oid_columns(예: oid_columns='_id')를 BAD_ARGUMENTS로 거부하지 않고 허용합니다. #108039 (alexey-milovidov).
  • DateTime64, Decimal 또는 부동소수점 범위를 사용하는 range_hashed 또는 complex_key_range_hashed 딕셔너리를 타입이 일치하는 인수와 함께 dictGet/dictHas로 조회할 수 있도록 했습니다. 이전에는 이러한 쿼리가 must be convertible to Int64 오류로 실패했으며, Decimal/DateTime64 범위에서 한쪽 끝이 열린 구간은 기본값을 잘못 반환했습니다. #108052 (alexey-milovidov).
  • accurateCastOrNull로 Array(Dynamic) 또는 Array(Variant)를 QBit로 캐스팅할 때(예: accurateCastOrNull(CAST(range(114), 'Array(Dynamic)'), 'QBit(Float32, 114)')) 발생하던 서버 비정상 종료(IColumn::insertFrom의 Logical error)를 수정했습니다. #108288 (groeneai).
  • 형식이 잘못되었거나 동기화가 어긋난 네이티브 TCP 프로토콜 스트림으로 인해 발생할 수 있던 서버 크래시(Received signal 4, 잘못된 명령어)를 수정했습니다. 이제 ClientInfo의 initial_address 필드가 파싱 전에 숫자 형식의 host:port인지 검증하므로, 숫자가 아닌 포트가 트랩 처리된 libc 함수 getservbyname에 전달되지 않습니다. #108410 (groeneai).
  • mannWhitneyUTest, rankCorr, largestTriangleThreeBuckets, quantileGK, sequenceMatch/sequenceCount, groupArrayIntersect의 조작된 집계 함수 상태를 역직렬화할 때 발생하던 과도한 메모리 할당 문제를 수정했습니다. 잘못된 형식의 상태가 매우 큰 원소 개수를 선언하면 서버가 단 몇 바이트의 입력만으로 수십 기가바이트를 할당하려 할 수 있었습니다. 이제 이러한 상태는 TOO_LARGE_ARRAY_SIZE 오류로 거부됩니다. #108465 (groeneai).
  • GROUPING SETS/ROLLUP/CUBE에서 LowCardinality 상수 그룹화 키와 함께 group_by_use_nulls를 사용할 때 발생하던 논리 오류(Bad cast from type DB::ColumnNullable to DB::ColumnString)와 잘못된 결과가 반환될 수 있던 문제를 수정했습니다. #108771 (alexey-milovidov).
  • Map 값에 LowCardinality를 포함하는 중첩 Map이 있을 때 mapFilter, mapSort, mapReverseSort, mapPartialSort, mapConcat에서 발생하던 TYPE_MISMATCH를 수정했습니다. 예: mapFilter((k, v) -> 1, map('a'::LowCardinality(String), map('x'::LowCardinality(String), 'y'))). #108798 (groeneai).
  • 이름이 있는 원소와 이름이 없는 원소가 섞인 Tuple 데이터 타입(예: Tuple(a UInt8, UInt16))을 포맷할 때 debug 및 새니타이저 빌드에서 서버가 중단되던 LOGICAL_ERROR(“Inconsistent AST formatting”)를 수정했습니다. #108915 (groeneai).
  • 이제 JSONExtract는 문자열 JSON 값을 DateTime/DateTime64로 변환할 때 CAST와 마찬가지로 cast_string_to_date_time_mode 설정을 따릅니다. #109252 (Utkal059).
  • 오른쪽 인수에 배열 컬럼만 단독으로 지정한 IN이 아무런 경고 없이 잘못된(항상 false인) 결과를 반환하거나 예외를 발생시키던 문제를 수정했습니다. 이제 x IN arr는 has(arr, x)와 동일하게 동작합니다. #109416 (alexey-milovidov).
  • 상수가 아닌 Array(LowCardinality(T)) 인수에 대해 arrayFold를 실행할 때(예: arrayFold((acc, x) -> acc + x, materialize([1, 2, 3]::Array(LowCardinality(Int64))), toInt64(0))) “Arguments of ‘plus’ have incorrect data types” 오류와 함께 실패하던(debug 및 새니타이저 빌드에서는 서버 중단) LOGICAL_ERROR를 수정했습니다. #109462 (groeneai).
  • FixedString 인수를 String으로 올바르게 캐스팅하도록 개선하여 conv에서 발생하던 ILLEGAL_COLUMN 예외를 수정했습니다. #109771 (hp77-creator).
  • serialize_query_plan = 1 설정에서 FINAL / SAMPLE을 사용한 테이블 함수 읽기가 잘못된 결과를 반환하던 문제를 수정하고, 테이블 함수의 집계 해시 테이블 통계 캐시 키도 수정했습니다(이전에는 모든 테이블 함수가 사전 할당 항목 하나를 공유했습니다). #109847 (azat).
  • 컨테이너 타입(예: Array(Bool), Tuple(Bool, ...)) 안에서 숫자 1/0을 Bool 값으로 파싱하지 못하던 문제를 수정했습니다. 이전에는 [true,false]는 정상 동작했지만 [1,0]은 CANNOT_READ_ARRAY_FROM_TEXT 오류와 함께 실패했습니다. #109976 (groeneai).
  • Array(LowCardinality(Nullable(String)))(이 방식으로 저장된 Nested 필드 포함)에 text 인덱스를 구축할 때 인덱싱된 배열에 NULL 원소가 있으면 발생하던 NOT_IMPLEMENTED 오류(Method getDataAt is not supported for Nullable(String) in case if value is NULL)를 수정했습니다. 이제 Array(Nullable(String))과 마찬가지로 인덱스 구축 시 NULL 배열 원소를 건너뜁니다. #110055 (groeneai).
  • 아직 작은 표현(small representation)으로 유지되고 있는 비트맵에서 subBitmap, bitmapSubsetInRange, bitmapSubsetLimit이 잘못된 결과를 반환하던 문제를 수정했습니다. 여기에는 2^32보다 큰 UInt64 및 Int64 원소 값이 32비트로 잘리던 문제도 포함됩니다. 이제 부호 있는(signed) 원소 타입에 대한 비트맵 함수의 비교는 일관되게 해당 원소 타입의 부호 없는 값을 사용합니다. 따라서 Int8 비트맵에서 원소 -1은 부호 확장된 4294967295가 아니라 255로 비교됩니다. 이 변경으로 작은 표현을 넘어 커진 비트맵에서 bitmapMin, bitmapMax, bitmapContains, bitmapTransform이 잘못 동작하던 문제도 함께 수정되었습니다. 부호 확장된 임계값을 전달하던 쿼리는 수정해야 합니다. 예를 들어 Int8 비트맵에서 bitmapSubsetInRange(bm, 4294967168, 4294967296)은 bitmapSubsetInRange(bm, 128, 256)으로 바꿔야 합니다. 또한 groupNumericIndexedVector가 Int8 및 Int16 인덱스 컬럼에 대해 더 넓은 인덱스 유형과 다른 결과를 반환하던 문제와, numericIndexedVectorGetValue가 음수 인덱스에 대해 0을 반환하던 문제도 수정했습니다. 아울러 1부터 시작하는 인덱싱을 사용한다고 잘못 설명되어 있던 부분 집합 함수와 부호 있는 타입에 대한 bitmapBuild / bitmapToArray 지원 내용을 포함하여 비트맵 함수 문서를 바로잡았습니다. #110072 (RamiDarwiche).
  • 인터벌 종류의 WITH FILL STEP과 극단적인 델타를 사용하는 add* / subtract* 날짜/시간 인터벌 함수에서, 인터벌 연산 중 정의되지 않은 동작인 부호 있는 오버플로우가 발생할 수 있던 경로를 수정했습니다. 이제 극단적인 인터벌 값도 부호 있는 오버플로우에 의존하지 않고 결정적으로 동작합니다. 또한 매우 큰 YEAR 간격을 사용하는 인터벌 종류의 WITH FILL이 달력을 거꾸로 진행시키며 멈추던 문제도 수정했습니다. #110158 (groeneai).
  • 정렬 순서가 그룹화 키의 접두사에 불과한 상태에서 여러 키로 그룹화할 때, 순서 기반 집계(aggregation in order)의 처리 시간이 이차 시간 복잡도로 급증하던 문제(및 max_execution_time에 응답하지 않던 문제)를 수정했습니다. #110159 (alexey-milovidov).
  • 피연산자에 최소 공통 상위 타입(least common supertype)이 없을 때 ILLEGAL_TYPE_OF_ARGUMENT 오류가 발생하던 비교 문제를 수정했습니다. 이제 Array(Int64)와 Array(UInt64), Array(Int256)와 Array(UInt256) 같은 배열을 =, !=, <, <=, >, >=, IS DISTINCT FROM, IS NOT DISTINCT FROM으로 사전식 비교할 수 있습니다. 또한 isDistinctFrom / isNotDistinctFrom 같은 NULL-안전 비교에서도 지원되는 배열 외의 숫자 또는 decimal 쌍을 예외 없이 값으로 비교합니다. 중첩된 Tuple(Nullable(...)) 원소를 가진 배열에 대해서도 동등 비교가 가능합니다. #110245 (diegomestre2).
  • 음수 오프셋을 가진 시간대에서 극단적인 DateTime64 값(예: INT64_MIN)을 Time/Time64로 변환할 때 발생하던 부호 있는 정수 오버플로우(UBSan)를 수정했습니다. #110451 (groeneai).
  • 범위를 벗어난 부동소수점 값(BFloat16, Float32, Float64)과 Int64::max()보다 큰 UInt64 값을 DateTime 및 Time으로 변환할 때, 이제 모든 아키텍처에서 일관되게 범위 경계값으로 포화(saturate)됩니다(이전에는 범위를 벗어난 변환 결과가 아키텍처마다 달랐으며, x86-64에서는 값이 순환(wrap around)될 수 있었습니다). 또한 유한하지 않은 값(NaN, inf)은 이제 임의의 결과를 생성하지 않고 예외를 발생시킵니다. 같은 수정 사항이 toDate의 부동소수점→Date 변환 경로에도 적용되었으며, 포화되지 않고 epoch 이전 날짜를 반환할 수 있었던 UInt64 및 wide 정수((U)Int128, (U)Int256)의 Date, Date32 변환에도 적용되었습니다. 숫자를 Time으로 변환할 때도 이제 모든 숫자 소스 타입에 대해 해당 타입의 범위로 포화됩니다(이전에는 좁은 부호 없는 정수나 wide 정수 소스의 값이 제한되지 않은 채 저장되었다가 출력할 때만 제한되었습니다). 또한 Time으로의 정확한 캐스트(accurate cast)는 더 이상 Time이 지원하는 음수 값을 거부하지 않으며, 범위에 맞지 않는 값을 조용히 포화시키지도 않습니다. 숫자를 Date32로 정확하게 캐스트할 때(accurateCast, accurateCastOrNull) 범위를 벗어나거나 유한하지 않은 값을 더 이상 조용히 포화시키지 않고, 기존 Date 및 DateTime과 마찬가지로 예외를 발생시키거나 NULL을 반환합니다. OrDefault 변형은 이러한 입력에 대해 Date32의 기본값을 반환합니다. 정수가 아닌 부동소수점 숫자를 Date, Date32, DateTime 또는 Time으로 정확하게 캐스트하면 이제 조용히 잘라내지 않고 거부합니다. 아울러 toDateTime64 예시를 잘못 보여 주고 DateTime64 값 범위를 설명하던 toDateTime32 함수 문서도 수정했습니다. #110459 (alexey-milovidov).
  • 맵 키가 딕셔너리 인코딩된 ORC 파일을 읽을 때 Map cannot have a key of type LowCardinality(Nullable(String)) 오류와 함께 스키마 추론이 실패하는 문제를 수정했습니다. Spark로 작성한 ORC 파일과 output_format_orc_dictionary_key_size_threshold를 활성화한 상태에서 ClickHouse 자체로 작성한 파일도 이에 해당합니다. #110492 (tiandiwonder).
  • optimize_or_like_chain이 활성화된 상태에서 OR 체인 내 LIKE/ILIKE/match의 좌변에 집계 함수나 윈도 함수가 있을 때 발생할 수 있던 논리 오류(Function node with name '...' is not resolved as ordinary function)를 수정했습니다. #110641 (groeneai).
  • Date/Date32/DateTime64 값에 극단적인 MONTH, WEEK, DAY 인터벌 개수를 사용할 때 toStartOfInterval에서 발생하던 부호 있는 정수 오버플로우를 수정했습니다. #110688 (groeneai).
  • readWKT와 readWKTPoint가 POINT EMPTY에 대해 초기화되지 않은 좌표(스칼라) 또는 이전 행의 오래된 좌표(벡터화)를 반환하던 문제를 수정했습니다. ClickHouse의 Point는 빈 표현이 없는 고정된 Tuple(Float64, Float64)이므로, 이제 POINT EMPTY는 CANNOT_PARSE_TEXT 오류와 함께 거부됩니다. #110692 (groeneai).
  • flipCoordinates에서 Geometry 타입이 유실되던 문제를 수정했습니다. 이제 Geometry 인수를 전달하면 내부의 Variant(...)가 아닌 Geometry 타입으로 결과가 반환되므로, areaCartesian 같은 함수에 바로 전달할 수 있습니다. #110694 (groeneai).
  • 빈 폴리곤의 WKB 직렬화가 정규 형식이 아니던 문제를 수정했습니다. 이제 wkb(POLYGON EMPTY)는 불필요한 점 0개짜리 단일 링 대신 numRings = 0을 출력하므로, 표준 빈 폴리곤을 WKB로 왕복 변환해도 아이덴티티가 보존됩니다. #110796 (groeneai).
  • JSON Bool 파싱 시 숫자 1/0이 이제 allow_special_bool_values 설정을 따릅니다. 이전에는 JSON Bool 파서가 이 설정을 무시했고 Bool의 Variant 역직렬화 우선순위가 정수 타입보다 높았기 때문에, allow_special_bool_values_inside_variant = 0으로 설정해도 Variant(Bool, UInt32)에 대한 {"v":1} 같은 JSON 입력이 Bool로 읽혔습니다. #110835 (groeneai).
  • col이 LowCardinality일 때 throwIf(notLike(col, pattern))(및 함수를 인자로 받는 다른 throwIf)가 무조건 예외를 발생시키던 문제를 수정했습니다. 기본 LowCardinality 구현은 딕셔너리 전체에 대해 throwIf를 실행했는데, 이 딕셔너리에는 이를 참조하는 행이 없더라도 예약된 기본값이 항상 포함되어 있습니다. 따라서 사용되지 않는 이 슬롯의 값이 0이 아니면 조건을 만족하지 않는 데이터에 대해서도 throwIf가 예외를 발생시켰습니다. #110864 (groeneai).
  • -Tuple 컴비네이터를 적용한 집계 함수를 RESPECT NULLS와 함께 사용하여 중간 상태(-State, 분산 집계, WITH ROLLUP/WITH CUBE)를 생성할 때 발생하던 크래시를 수정했습니다. 결합된 함수의 이름이 잘못된 상태 변형을 기준으로 지정되어, 직렬화된 AggregateFunction 타입을 다시 읽어 들일 때 호환되지 않는 메모리 내 레이아웃으로 재해석되었습니다. #110930 (groeneai).
  • mysql 테이블 함수 또는 MySQL 테이블/데이터베이스 엔진을 통해 널 허용 MySQL 공간 컬럼(LINESTRING, POLYGON, MULTILINESTRING, MULTIPOLYGON, MULTIPOINT 또는 범용 GEOMETRY)을 읽을 때 발생하던 Nested type LineString cannot be inside Nullable type (ILLEGAL_TYPE_OF_ARGUMENT) 오류를 수정했습니다. 이제 이러한 컬럼은 MySQL이 반환한 값(4바이트 SRID 접두사 뒤에 WKB 페이로드가 이어지는 형태)을 그대로 담는 Nullable(String)으로 대체됩니다. POINT는 기존과 같이 Nullable(Point)로 매핑됩니다. #110943 (groeneai).
  • 버전이 지정된 집계 상태를 포함하는 SimpleAggregateFunction 래퍼를 이전 버전의 피어로 보낼 때의 Native 직렬화 문제를 수정했습니다. #110997 (groeneai).
  • 분산 쿼리 및 병렬 레플리카를 사용하는 쿼리에서 Variant 타입(Geometry 포함) 상수에 대해 발생하던 CANNOT_CONVERT_TYPE 오류를 수정했습니다. #111136 (fm4v).
  • 고차 함수의 람다 본문이 Bool 리터럴 분기와 UInt8 비교 분기가 섞인 상수 조건 if/multiIf일 때(예: arrayFilter(p -> multiIf(false, true, p = 'ALL'), ['ALL'])) 발생하던 LOGICAL_ERROR(“Lambda resolved type … is not equal to type from actions DAG …”)를 수정했습니다. #111245 (groeneai).
  • 1초 미만 인터벌을 사용하는 toStartOfInterval에서 발생하던 부호 있는 정수 오버플로우를 수정했습니다. Int64 하한에서 한 인터벌 이내에 있는 DateTime64 값은 내림한 결과가 경고 없이 양수 쓰레기 값으로 래핑되었으나, 이제는 함수가 DECIMAL_OVERFLOW 예외를 발생시킵니다. #111370 (alexey-milovidov).
  • 중첩된 컴비네이터 하에서 -Tuple 컴비네이터를 RESPECT NULLS / IGNORE NULLS 수정자와 함께 사용하는 분산 쿼리(예: anyRespectNullsStateTuple(...) IGNORE NULLS)에서 발생하던 예외(CANNOT_CONVERT_TYPE 또는 논리 오류)를 수정했습니다. #111570 (alexey-milovidov).
  • 파싱이 실패했을 때 일부만 추가된 바이트가 컬럼에 남는 FixedString 텍스트 try-parse 문제를 수정했습니다. 이 문제로 인해 Variant/Array/Nullable 컬럼을 직렬화하는 과정에서 Sizes of nested column and null map of Nullable column are not equal 논리 오류가 발생하거나, 결과 바이트가 아무런 경고 없이 밀릴 수 있었습니다. #111908 (groeneai).
  • Buffer 테이블을 통해 동적 서브컬럼(JSON 또는 Dynamic 컬럼 내부의 경로)을 읽을 때 예외가 발생하고 데이터가 아무런 경고 없이 누락되던 문제를 수정했습니다. #111948 (alexey-milovidov).
  • countSubstringsCaseInsensitiveUTF8의 이차 복잡도 문제를 수정했습니다. 이 문제로 인해 일치 항목이 많은 수 메가바이트 크기의 haystack에서는 함수 실행에 수 분이 걸렸습니다. 이제 각 일치 항목의 문자 오프셋을 매번 행의 시작부터 다시 계산하지 않고 점진적으로 갱신합니다. #112003 (groeneai).
  • 인수 3개를 받는 toStartOfInterval 오버로드에서 발생하던 부호 있는 정수 오버플로를 수정했습니다. origin 인수가 Int64의 하한에 가까우면 함수가 오류를 보고하지 않고 랩어라운드된 값을 반환했습니다. #112045 (alexey-milovidov).
  • 집계 상태(aggregate state)는 테이블 함수 매개변수에서 전혀 지원되지 않으므로 사용할 수 없도록 했습니다. #112087 (PedroTadim).
  • values 테이블 함수가 String/텍스트 컬럼에 삽입된 비리터럴 Bool 상수(예: CAST(true, 'Nullable(Bool)'))를 true/false가 아닌 1/0으로 렌더링하던 문제를 수정했습니다. #112308 (yakov-olkhovskiy).
  • 상태 표현은 같지만 최종 결과 타입이 서로 다른 함수들에서 나온 집계 상태가 담긴 컬럼에 finalizeAggregation을 적용할 때 발생하던 논리 오류(디버그 및 새니타이저 빌드에서는 프로세스가 중단됨)를 수정했습니다. UNION으로 합쳐지거나 arrayReduce로 생성된 quantileState와 quantilesState(0.9)가 그 예입니다. 이제 이러한 쿼리는 크래시 대신 일반 오류를 발생시킵니다. #112662 (zainulabidin302).
  • JSON 숫자를 읽는 데 사용되는 Poco::NumberParser에서 대상 타입의 범위를 벗어나는 정수를 잘못 파싱하던 문제를 수정했습니다. 이러한 숫자는 거부되지 않고 아무런 경고 없이 잘못된 값으로 파싱되었으며(예: 18446744073709551617이 1이 됨), Int64 최댓값을 초과하는 UInt64 숫자는 AST JSON 왕복 변환 후 값이 보존되지 않았습니다. #112904 (alexey-milovidov).
  • IN 오른쪽의 Bool 상수가 String 타입의 왼쪽 값에 맞춰 변환될 때 표준 값인 'true'/'false'가 아닌 '1'/'0'으로 변환되던 문제를 수정했습니다(이제 CAST 및 values 테이블 함수와 일관되게 동작합니다). #113051 (yakov-olkhovskiy).
  • viewIfPermitted의 AST 포맷팅이 일관되지 않던 문제를 수정했습니다. 테이블 함수 형식의 ELSE 분기에서 보통 연산자로 작성되는 함수(예: not)가 잘못 포맷팅되던 문제와, 표현식 형식 viewIfPermitted(...)가 ELSE와 함께 잘못 포맷팅되던 문제가 이에 해당합니다. #113652 (alexey-milovidov).
  • Date/DateTime/DateTime64/Time/Time64에 대한 avg에서 발생하던 정의되지 않은 동작과 잘못된 결과를 수정했습니다. 이제 평균을 정수 공간에서 정확하게 계산하므로, Int64 경계 오버플로우(UB, x86에서 잘못된 결과 발생)와 2^53을 초과하는 값에서의 Float64 정밀도 손실(나노초 단위에서 드러남)이 모두 해결됩니다. #113912 (alexey-milovidov).
  • Experimental SZ3 압축 코덱의 메모리 누수를 수정했습니다. 압축이 잘 되지 않거나 손상된 데이터를 압축하다가 예외가 발생하여 실패하면 임시 스크래치 버퍼가 해제되지 않고 남아 있었습니다. #113916 (alexey-milovidov).
  • bloom_filter 인덱스를 FixedString 상수로 조회할 때 hasAny, hasAll, has, indexOf, mapContainsKey, mapContainsValue, mapContains가 실제보다 적은 행을 반환하거나 TOO_LARGE_STRING_SIZE 오류로 실패하던 문제를 수정했습니다. 인덱스는 패딩된 형태의 상수를 해시하는 반면 함수는 패딩되지 않은 형태로 비교하기 때문에, 일치하는 그래뉼을 건너뛰는 문제가 있었습니다. #114089 (alexey-milovidov).
  • 집계가 JIT 컴파일되고 데이터에 1970년 이전의 타임스탬프가 포함된 경우 DateTime64 컬럼에 대한 min과 max가 잘못된 결과를 반환하던 문제를 수정했습니다. Decimal64에서 파생된 DateTime64와 Time64에 대해 is_signed가 특수화되지 않아 생성된 코드가 틱 수를 부호 없는 정수로 비교했고, 그 결과 1970년 이전 타임스탬프가 max에서는 선택되고 min에서는 제외되었습니다. #114168 (groeneai).
  • 배열 원소와 검색 패턴의 문자열 타입이 서로 다른 경우(예: Array(FixedString(N)) 원소와 String 검색 패턴을 비교하는 경우) arrayExists(x -> x = needle, arr)가 잘못된 결과를 반환하거나 TOO_LARGE_STRING_SIZE 오류로 실패하던 문제를 수정했습니다. 기본으로 활성화된 optimize_rewrite_array_exists_to_has 최적화가 이러한 호출을 has로 재작성했는데, has는 =와 달리 0 패딩을 고려하여 비교하지 않습니다. #114496 (groeneai).
  • Map 또는 JSON 컨테이너에 적용된 LIKE/ILIKE 연산자의 텍스트 인덱스 평가 문제를 수정했습니다. #114544 (ahmadov).
  • DateTime64 및 넓은 Decimal 값에 대한 quantile과 quantiles에서 발생하던 정의되지 않은 동작과 경계값의 잘못된 결과를 수정했습니다. #114919 (alexey-milovidov).
  • Time 분기가 Time64, DateTime 또는 DateTime64와 함께 사용되고 표현식이 JIT 컴파일될 때 if와 multiIf가 음수 대신 큰 양수 값을 반환하던 문제를 수정했습니다. #115146 (groeneai).
  • 국제 날짜 변경선을 넘은 이후의 Pacific/Kiritimati, Pacific/Apia처럼 UTC 오프셋이 1970-01-01 시점의 오프셋과 정확히 하루 차이가 나는 시간대와 1970년 이전의 대부분의 시간대에서 timezoneOffset(별칭 timeZoneOffset)이 정확히 하루만큼 어긋난 오프셋을 반환하던 문제를 수정했습니다. 이에 따라 해당 오프셋을 사용하는 parseDateTime, parseDateTimeOrNull, parseDateTime64, parseDateTimeInJodaSyntax, EXTRACT(TIMEZONE_HOUR / TIMEZONE_MINUTE ...), formatDateTime’의 %z, toUTCTimestamp, fromUTCTimestamp의 동작도 함께 수정됩니다. #115332 (groeneai).
  • has 또는 notHas 프레디케이트에 NULL 배열 원소가 포함되어 있고 프라이머리 키가 String, Array(String) 또는 Map(String, String)인 경우 Code: 349. Cannot convert NULL value to non-Nullable type 오류가 발생하던 문제를 수정했습니다. 또한 해당 원소가 NULL 값을 가진 Dynamic 또는 Variant일 때 잘못된 결과가 반환되던 문제도 수정했습니다. 이제 다른 키 타입과 마찬가지로 키 분석 단계에서 NULL이 집합에서 제외됩니다. #115647 (groeneai).
  • 대상 타입이 LowCardinality일 때 cast_keep_nullable이 널 허용 여부를 유지하지 못하던 문제를 수정했습니다. 기존에는 NULL을 가질 수 있는 값을 LowCardinality(T)로 캐스팅하면 LowCardinality(Nullable(T))가 반환되지 않고 CANNOT_INSERT_NULL_IN_ORDINARY_COLUMN 오류가 발생했습니다. #115851 (groeneai).

인덱스 및 쿼리 캐시 관련 수정 사항

  • DEFAULT 표현식이 있으면서 파트에 구체화되지 않은 컬럼(예: ALTER TABLE ADD COLUMN 이후 또는 ALTER TABLE MATERIALIZE COLUMN 수행 중)의 서브컬럼을 읽을 때 발생하던 문제를 수정했습니다. 해당 서브컬럼이 평가된 DEFAULT 표현식 값 대신 타입 기본값으로 채워졌으며, 이러한 QBit 컬럼에 전치(transposed) 벡터 거리 함수(cosineDistanceTransposed 등)를 실행하면 SIZES_OF_ARRAYS_DONT_MATCH 오류가 발생했습니다. #110636 (alexey-milovidov).
  • 프라이머리 키 분석 중 IN 서브쿼리 집합 빌드가 아무런 알림 없이 실패하면(예: overflow_mode = 'break'에서 서브쿼리 시간 초과) 쿼리 파이프라인에서 해당 집합이 계속 빌드되지 않은 상태로 남아 Not-ready Set is passed as the second argument 예외가 발생할 수 있던 문제를 수정했습니다. #107924 (alexey-milovidov).
  • set 데이터 스키핑 인덱스가 있는 테이블에서 행 정책(row policy)이 항상 참인 조건과 인덱싱되지 않은 컬럼에 대한 검사를 조합해 필터링할 때 SELECT가 NOT_FOUND_COLUMN_IN_BLOCK 오류로 실패하던 문제를 수정했습니다. #107971 (tiandiwonder).
  • 이제 getClientHTTPHeader가 비결정적 함수로 올바르게 처리되므로, 해당 결과가 쿼리 결과 캐시에서 더 이상 잘못 재사용되지 않습니다. #108029 (alexey-milovidov).
  • 쿼리 조건 캐시(use_query_condition_cache = 1)가 스킵 인덱스에서 도출된 마크 제외 정보를, 다른 스킵 인덱스 집합을 실행한 쿼리(예: use_skip_indexes = 0, ignore_data_skipping_indices 또는 다른 use_skip_indexes_for_disjunctions 모드 사용 시)에 재사용하여 잘못된 결과가 반환되던 문제를 수정했습니다. 이제 스킵 인덱스에서 도출된 캐시 엔트리는 실제로 실행된 스킵 인덱스 집합을 키로 사용하며, 행 수준의 쿼리 조건 캐시 엔트리는 이러한 모든 경우에 계속 재사용할 수 있습니다. #108548 (groeneai).
  • 파일 시스템 캐시를 통해 읽는 쿼리가 KILL QUERY로 취소된 후에도 진행 중인 다운로드를 계속 기다릴 수 있던 멈춤 현상과, 갱신 작업이 이러한 대기 상태에 멈춘 갱신 가능 구체화 뷰를 삭제하거나 SYSTEM STOP VIEW를 실행하면 작업이 차단되던 문제를 수정했습니다. #109116 (murphy-4o).
  • 파트에 최종 마크가 없는 경우(비적응형 세분화 수준, index_granularity_bytes = 0) 역순(DESC) 키 컬럼이 있는 테이블에서 프라이머리 키 인덱스가 그래뉼을 잘못 제외하여 잘못된 쿼리 결과가 반환되던 문제를 수정했습니다. #109901 (nihalzp).
  • 서브쿼리에 상관 서브쿼리가 포함되어 있고 인덱스 분석 중에 집합이 빌드되는 IN (subquery)에서 발생하던 논리 오류 Expected CommonSubplanReferenceStep to reference CommonSubplanStep, 오류 Subplan cannot be used to build pipeline, 논리 오류 Trying to extract chunk from ChunkBuffer before all inputs are finished를 수정했습니다. #110491 (alexey-milovidov).
  • 병렬 레플리카가 활성화된 상태에서 스칼라 서브쿼리 또는 상수 참조 벡터를 사용하여 QBit 컬럼에 대한 전치 거리 함수(예: cosineDistanceTransposed)를 호출할 때 발생하던 NOT_FOUND_COLUMN_IN_BLOCK 오류를 수정했습니다. #110729 (alexey-milovidov).
  • 텍스트 인덱스의 표현식에 arrayFilter(s -> s != '', ...)와 같은 빈 문자열 비교가 포함된 경우, optimize_empty_string_comparisons 설정이 쿼리 쪽에서만 해당 비교를 notEmpty로 재작성하는 탓에 텍스트 인덱스가 사용되지 않던 문제를 수정했습니다. #112115 (Ergus).
  • 컬럼이 텍스트 인덱스 가상 컬럼으로 재작성되더라도 PREWHERE와 WHERE 필터 조건 모두에서 참조되는 경우에는 해당 컬럼을 제거하지 않도록 수정했습니다. #114460 (ahmadov).
  • 지연 포스팅 리스트 적용 모드에서 텍스트 인덱스가 있는 테이블에 대한 쿼리가 읽기 도중 취소될 때 발생하던 논리 오류 Multi-block postings must be compressed를 수정했습니다. #114636 (CurtizJ).
  • WHERE 절에서 NOT 안에 NULL 표현식이 포함된 경우(예: SELECT count() FROM t WHERE NOT (id >= 20 AND NULL)) 잘못된 결과가 반환되던 문제를 수정했습니다. 인덱스 분석이 이러한 조건을 전체 범위에서 항상 참으로 간주해 필터를 건너뛰었기 때문에, count()가 쿼리에서 제외되어야 할 행까지 반환하고 해당 조건을 사용한 ALTER TABLE ... DELETE가 유지되어야 할 행까지 삭제했습니다. #115152 (groeneai).
  • query_plan_join_shard_by_pk_ranges가 활성화된 full_sorting_merge JOIN에서 한쪽이 프라이머리 키나 컬럼 통계에 의해, 또는 테이블이 비어 있어서 파트가 하나도 남지 않을 때 발생하던 LOGICAL_ERROR(Join is supported only for pipelines with one output port)를 수정했습니다. #115352 (alexey-milovidov).
  • _part_starting_offset에 대한 필터에서는 쿼리 조건 캐시를 사용하지 않도록 했습니다. #115358 (azat).
  • 암시적 minmax 인덱스(add_minmax_index_for_numeric_columns 등)가 있는 테이블에서 하나의 ALTER TABLE SQL 문에 RENAME COLUMN과 MODIFY SETTING 같은 다른 명령을 함께 사용할 때 발생하던 LOGICAL_ERROR: Index with name auto_minmax_index_<column> already exists를 수정했습니다. 또한 일반 컬럼의 이름을 변경한 뒤 이어서 실행한 DROP COLUMN이 UNKNOWN_IDENTIFIER로 실패하거나, 이어서 실행한 ADD COLUMN에 암시적 인덱스가 생성되지 않는 문제도 더 이상 발생하지 않습니다. #116063 (groeneai).
  • 와일드카드(%, _)가 없는 LIKE/NOT LIKE 패턴이 이제 정확한 프라이머리 키 범위를 사용합니다. 따라서 더 넓은 접두사 범위 대신, 동등한 =/!= 프레디케이트와 같은 수의 그래뉼만 읽습니다. #107077 (groeneai).
  • 프라이머리 키에 대한 IN/NOT IN 조건이 키를 상수로 나누는 intDiv로 감싸고 있고, 키가 부호 없는 정수이면서 그 값이 intDiv 결과 타입의 부호 있는 범위 경계를 넘는 경우(예: intDiv(uint64_column, -9223372036854775807)) 발생하던 LOGICAL_ERROR(Invalid binary search result in MergeTreeSetIndex)와 릴리스 빌드에서 인덱스 프루닝이 누락되던 문제를 수정했습니다. #107586 (groeneai).
  • 모든 원소가 1이면서 BSI 비트 구성이 다른 벡터를 곱할 때 numericIndexedVectorPointwiseMultiply가 빈 결과를 반환하던 문제를 수정했습니다. #108027 (alexey-milovidov).
  • 서로 다른 짧은 토큰이 많은 데이터에 positions = 1로 텍스트 인덱스를 빌드할 때 발생하던 heap-buffer-overflow를 수정했습니다. #108659 (groeneai).
  • 텍스트 인덱스의 preprocessor 및 postprocessor 표현식에서 ALIAS 컬럼을 참조할 수 있도록 했습니다. #110014 (Ergus).
  • LIMIT ... WITH TIES를 사용할 때는 벡터 검색 최적화를 건너뛰도록 수정했습니다. 이 최적화는 ANN 검색 대상을 정확히 n개의 후보로 제한하므로, n번째 행과 동률인 행이 누락되기 때문입니다. #110453 (tamish560).
  • 인덱스가 단순 컬럼이 아닌 표현식(예: lower(...) 전처리기를 사용하는 assumeNotNull(col))에 정의된 경우 ILIKE에서 텍스트 인덱스가 사용되지 않던 문제를 수정했습니다. 이제 이러한 쿼리는 모든 그래뉼을 읽지 않고 인덱스를 사용합니다. #110595 (ahmadov).
  • vector_search_with_rescoring = 1과 지연 머티리얼라이즈(lazy materialization)를 함께 사용하는 벡터 검색 쿼리에서 여러 거리 값이 동률일 때 발생할 수 있던 LOGICAL_ERROR(LazyMaterializingTransform: Number of rows in lazy chunk N does not match number of offsets M)를 수정했습니다. #111003 (groeneai).
  • i8 양자화를 사용하는 vector_similarity 인덱스에서 크기의 제곱이 무한대로 오버플로우되는 벡터를 거부하도록 수정했습니다. 이전에는 이러한 벡터가 usearch에서 정의되지 않은 동작을 유발하여, 오류 없이 무의미한 값을 생성했습니다. #111085 (groeneai).
  • 페이지 캐시가 활성화된 plain_rewritable 디스크에서 오래된 데이터를 읽던 문제를 수정했습니다. #111105 (Michicosun).
  • String(또는 더 짧은 FixedString) 키나 minmax 스킵 인덱스를 더 긴 FixedString 상수와 비교하여 필터링할 때(예: toFixedString('abc', 257) = string_col) count() 결과가 잘못되고 행이 누락되던 문제를 수정했습니다. 기본 키 및 minmax 프루닝이 NUL로 채워진 상수를 기준으로 범위를 구성하는 바람에 조건에 맞는 그래뉼까지 잘못 건너뛰었습니다. #111106 (groeneai).
  • 오프셋 인덱스가 0번 행에서 시작하지 않는 Parquet 파일을 읽을 때 발생하던 문제를 수정했습니다. 이러한 파일로 인해 네이티브 Parquet 리더가 잘못된 행을 반환하거나 INCORRECT_DATA 대신 LOGICAL_ERROR를 보고할 수 있었습니다. 이제 오프셋 인덱스를 읽을 때 유효성을 검사합니다. #114530 (groeneai).

보안, 액세스, 백업 및 복원 관련 수정 사항

  • 이제 대상 테이블에 fsync_after_insert가 활성화되어 있으면 RESTORE가 복원된 파트 파일을 fsync하므로, 복원된 파트도 삽입된 파트와 마찬가지로 정전 시 내구성이 보장됩니다. 이전에는 복원된 파일을 쓰고 닫기만 할 뿐 fsync하지 않았기 때문에, RESTORE가 RESTORED를 반환한 직후 정전이 발생하면 파트가 손상되어 테이블이 비어 있을 수 있었습니다. #111378 (groeneai).
  • 인증되지 않은 TCP 클라이언트가 interserver 포트를 통해 테이블 존재 여부와 복제 상태를 탐지할 수 있던 보안 문제를 수정했습니다. #99854 (tiandiwonder).
  • DELETE FROM(경량한 삭제)이 ALTER DELETE 외에 ALTER UPDATE 권한까지 요구하던 문제를 수정했습니다. 이제 문서에 명시된 대로 ALTER DELETE 권한만 부여받은 사용자도 DELETE FROM을 실행할 수 있습니다. #107491 (tiandiwonder).
  • Atomic 데이터베이스에서 CREATE TABLE ... AS SELECT 쿼리가 실패하면(예: 서브쿼리에서 참조하는 테이블에 사용자의 액세스 권한이 없는 경우) 빈 테이블이 남던 문제를 수정했습니다. 이전에는 재시도하면 원래 오류 대신 테이블이 이미 존재한다는 오류가 보고되었습니다. 이제 테이블은 임시 테이블을 거쳐 생성되며, 데이터가 모두 채워진 후에야 표시됩니다. #108048 (alexey-milovidov).
  • 사용자에게 ALIAS 컬럼에 대한 SELECT 액세스만 부여된 테이블에서 SELECT count()(또는 기타 단순 쿼리)를 실행하면 LOGICAL_ERROR(No available columns)가 발생하던 문제를 수정했습니다. #108056 (alexey-milovidov).
  • 인증되지 않은 요청으로 인해 ClickHouse가 전달된(forwarded) 클라이언트 주소 헤더에 포함된 호스트 이름을 해석할 수 있던 문제를 수정했습니다. 이제 ClickHouse는 이러한 헤더에서 숫자 형식의 IP 주소만 허용합니다. 유효하지 않은 값은 DNS 해석 없이 전달 주소 기반 쿼터 집계에서 무시됩니다. auth_use_forwarded_address가 활성화된 경우, 유효하지 않은 전달 주소는 인증 단계에서 거부됩니다. 거부 내역은 debug 수준으로 로그에 기록됩니다. #111060 (otselnik).
  • 분석기가 비활성화된 경우(enable_analyzer = 0) 매개변수화된 뷰(parameterized view)에 SQL SECURITY DEFINER(및 SQL SECURITY NONE)가 적용되지 않던 문제를 수정했습니다. 이전에는 기본 테이블에 대한 권한이 없는 사용자가 이러한 뷰를 조회하면 ACCESS_DENIED 오류로 실패했습니다. 분석기를 활성화한 상태에서는 동일한 뷰가 정상적으로 동작했습니다. #111458 (groeneai).
  • MySQL 통합에서 명명된 컬렉션이 자격 증명을 내용(contents) 형식으로 저장한 경우, 빈 ssl_ca_pem/ssl_cert_pem/ssl_key_pem 값으로 TLS 자격 증명을 재정의하려 하면 이를 거부하지 않고 받아들여, 구성된 CA 또는 클라이언트 인증서가 별도의 알림 없이 삭제되던 결함을 수정했습니다. #113947 (alexey-milovidov).
  • 본문에 JOIN이 포함되어 있고 SQL SECURITY DEFINER 또는 SQL SECURITY NONE으로 선언된 뷰에서 EXPLAIN ANALYZE가 조인 통계를 누락하던 문제를 수정했습니다. debug 및 sanitizer 빌드에서는 해당 쿼리가 논리 오류 JoinStep analyzed without the analyze mode를 일으키며 중단되었습니다. #115156 (groeneai).
  • RESTORE ... AS <new name> 실행 후 갱신 가능 구체화 뷰의 REFRESH ... DEPENDS ON 목록이 계속 원래 데이터베이스를 가리키던 문제를 수정했습니다. 이로 인해 복원된 뷰는 더 이상 읽지 않는 테이블에 반응하여 갱신되고, 정작 자신의 상위 테이블 갱신은 무시했으며, 원래 데이터베이스가 삭제되면 갱신이 아예 중단되었습니다. #115689 (groeneai).
  • 삭제와 재생성이 동시에 진행 중인 Replicated 데이터베이스를 백업할 때 발생하던 LOGICAL_ERROR 예외를 수정했습니다. 이제 이러한 백업은 CANNOT_GET_REPLICATED_DATABASE_SNAPSHOT 오류를 반환하며 깔끔하게 실패합니다. #100651 (alexey-milovidov).
  • 동일한 역할에 대해 GRANT role TO role을 실행하면 이제 system.role_grants에 자기 자신을 참조하는 엔트리가 아무런 알림 없이 생성되는 대신 BAD_ARGUMENTS 오류와 함께 거부됩니다. #103315 (zxuhan).
  • MaterializedPostgreSQL 데이터베이스의 BACKUP이 더 이상 “Table … were created or changed its definition during scanning” 메시지와 함께 무한정 멈추지 않으며, 이제 테이블 데이터를 실제로 백업합니다(기반 ReplacingMergeTree에 위임). 이 백업은 독립형 ReplacingMergeTree로 복원할 수 있습니다. #107433 (alexey-milovidov).
  • 딕셔너리에 대해 SHOW DICTIONARIES 권한만 있는 사용자도 EXISTS <dictionary>를 실행할 수 있도록 했습니다(이전에는 SHOW TABLES 권한이 필요했습니다). #108084 (alexey-milovidov).
  • 마무리 단계 전에 실패한 BACKUP ... TO Memory(...)가 제대로 정리되지 않던 문제를 수정했습니다. 이전에는 실패한 백업이 등록된 상태로 남아 있어 해당 이름을 재사용할 수 없었습니다. #109947 (jkartseva).
  • 동일한 zip 아카이브에 대한 이전 읽기가 스트림 도중 실패한 후 해당 아카이브를 다시 읽을 때(예: zip 백업에서 RESTORE하는 경우) 발생할 수 있던 ReadBuffer is canceled. Can't read from it. 논리 오류(debug/새니타이저 빌드에서는 서버 중단)를 수정했습니다. #110197 (groeneai).
  • const 메서드인 AccessRights::getFilters가 동시에 실행되는 쿼리들이 공유하는 액세스 권한 트리를 변경하여 발생하던 힙 손상 문제를 수정했습니다. 이 문제로 인해 서버 종료 시 크래시가 발생할 수 있었습니다. #112692 (groeneai).

분산 실행, 테이블, 뷰 및 딕셔너리

  • ALTER TABLE ... MOVE PART ... TO SHARD '<path>'에서 불필요한 Inconsistent AST formatting 오류가 발생하던 문제를 수정했습니다. 쿼리 포매터가 SHARD 키워드를 누락하는 바람에 재포맷된 쿼리를 다시 파싱할 수 없었고, 그 결과 LOGICAL_ERROR가 발생했습니다(릴리스 빌드에서는 처리된 예외로, 디버그 및 sanitizer 빌드에서는 abort로 이어짐). #109060 (groeneai).
  • 원격 데이터베이스 이름을 비워 둔 채 정의한 Distributed 테이블을 distributed_product_mode = 'local' 설정에서 JOIN에 사용할 때 발생하던 논리 오류(!part.empty())를 수정했습니다. #110677 (groeneai).
  • DISTINCT 조기 중단 limit 힌트로 결과의 앞부분을 한정할 수 없는 경우, 정렬된 LIMIT/OFFSET과 함께 사용한 DISTINCT가 잘못된 행을 반환하던 문제를 수정했습니다. 해당하는 경우는 음수 LIMIT(끝부분 대신 앞부분을 반환), 소수 LIMIT/OFFSET(소수 값은 전체를 읽은 후에야 결정됨), LIMIT 없이 단독으로 사용한 OFFSET(offset 이후의 끝부분이 누락됨)입니다. 예를 들어 여러 파트로 구성된 테이블에서 SELECT DISTINCT intDiv(x, 100) FROM t ORDER BY intDiv(x, 100) LIMIT -1을 실행하면 가장 큰 고유 값 대신 가장 작은 고유 값이 반환되었습니다. #111326 (groeneai).
  • DESCRIBE TABLE에서 서브쿼리 뒤에 오는 별칭을 파서가 인식하지 못해 구문 오류가 발생하던 문제를 수정했습니다. https://github.com/ClickHouse/ClickHouse/issues/100031 을 해결합니다. #100205 (yariks5s).
  • DETACH DATABASE / ATTACH DATABASE 이후 lazy_load_tables = 1이 설정된 Atomic 데이터베이스에서 ALTER RENAME COLUMN이 진행되는 도중 INSERT를 동시에 수행하면 서버 abort(Logical error: 'Block structure mismatch')가 발생할 수 있던 문제를 수정했습니다. #104852 (groeneai).
  • inject_random_order_for_select_without_order_by 설정으로 인해 컬럼명이 손상되고 BAD_ARGUMENTS 예외가 발생하던 문제를 수정했습니다. 이제 이 설정을 활성화해도 여러 컬럼을 조회하는 SELECT가 실패하지 않으며, 출력 컬럼명(예: CREATE TABLE AS SELECT, CREATE VIEW AS SELECT, JSONEachRow)이 내부 __subquery_column_<UUID> 별칭으로 바뀌지 않고 그대로 유지됩니다. #105896 (groeneai).
  • 서버 재시작(또는 DETACH/ATTACH DATABASE) 후 이미 삭제된 테이블을 다시 삭제하려 하면, 방금 삭제한 이름을 대안으로 제시하는 혼란스러운 “Maybe you meant X?” 힌트가 표시되던 문제를 수정했습니다. 이제 분리 시 DatabaseOrdinary::startup_table 및 load_table에서 비동기 로드 작업이 정리됩니다. #106238 (groeneai).
  • MaterializedPostgreSQL 테이블 및 데이터베이스 엔진을 수정하여, 기본값이 아닌 PostgreSQL 스키마(materialized_postgresql_schema)에서도 단일 테이블 또는 데이터베이스를 복제할 수 있도록 했습니다. 같은 데이터베이스의 여러 스키마에 동일한 이름의 테이블이 있는 경우도 지원합니다(이전에는 이러한 테이블이 publication과 replication slot을 공유하여 서로 간섭했습니다). #107425 (alexey-milovidov).
  • 병렬 레플리카를 사용하는 쿼리가 GLOBAL JOIN 임시 테이블로 전송된 테이블의 ALIAS 컬럼을 조회할 때 발생하던 NO_SUCH_COLUMN_IN_TABLE, 분산 JOIN의 양쪽에서 같은 이름의 ALIAS 컬럼을 선언할 때 발생하던 MULTIPLE_EXPRESSIONS_FOR_ALIAS, Distributed 테이블에서 다른 ALIAS 컬럼을 참조하는 ALIAS 컬럼을 선언할 때(JOIN USING 키로 사용하는 경우 포함) 발생하던 UNKNOWN_IDENTIFIER 오류를 수정했습니다. #107700 (yakov-olkhovskiy).
  • 갱신 가능 구체화 뷰(Refreshable Materialized View)가 refresh_retries를 매우 큰 값(Int64 최댓값 근처)으로 설정한 상태에서 실패한 갱신을 재시도할 때 발생하던 부호 있는 정수 오버플로우를 수정했습니다. 이 오버플로우로 인해 정의되지 않은 동작(undefined behavior) 새니타이저가 적용된 빌드에서 서버가 비정상 종료될 수 있었습니다. #108005 (groeneai).
  • 키 컬럼이 딕셔너리 정의의 앞부분에 위치하지 않는 복합 키 딕셔너리를, 명시적 쿼리를 사용하는 로컬 ClickHouse 소스로 로드할 때 발생하던 예외(CANNOT_PARSE_TEXT)를 수정했습니다. 이제 원본 컬럼은 위치가 아닌 이름을 기준으로 딕셔너리 구조와 매칭됩니다. #108053 (alexey-milovidov).
  • WHERE 절 없이 Hive 테이블을 쿼리할 때(예: SELECT * FROM hive_table) 발생하던 크래시(널 포인터 역참조)를 수정했습니다. #108094 (alexey-milovidov).
  • 분산 쿼리가 아직 구체화되지 않은 MATERIALIZED CTE를 외부 테이블로 참조하고 원격 소스가 지연 생성(delayed source)될 때 발생할 수 있던 서버 크래시(세그멘테이션 폴트)를 수정했습니다. 이 크래시는 RemoteQueryExecutor::sendExternalTables() 내부에서 널 Logger를 역참조하여 발생했습니다. #108547 (groeneai).
  • STREAM 읽기(SELECT DISTINCT ... FROM table STREAM)에서 DISTINCT를 실행할 때 발생하던 논리 오류(Equal values are not contiguous within the range assumed to be sorted)를 수정했습니다. STREAM 읽기는 정렬 키 순서가 아닌 커밋 순서로 행을 생성하므로, 이제 순서 기반 읽기(read-in-order) 최적화를 적용하지 않습니다. #108568 (groeneai).
  • optimize_skip_unused_shards = 1 설정에서 Distributed 테이블의 세그먼트 분할 키가 분석기에 의해 상수 폴딩되는 표현식(예: if(1, toInt32(id), toInt32(id) + 1))일 때 발생하던 예외(Cannot find sharding key column, debug/새니타이저 빌드에서는 서버 비정상 종료)를 수정했습니다. #108737 (groeneai).
  • Alias 테이블을 통한 INSERT ... SELECT가 예외 없이 취소될 때(예: timeout_overflow_mode = 'break') 발생하던 서버 비정상 종료(debug 및 새니타이저 빌드에서의 LOGICAL_ERROR / assertion)를 수정했습니다. #108783 (groeneai).
  • TimeSeries 테이블에 대한 INSERT ... SELECT가 예외 없이 취소될 때(예: timeout_overflow_mode = 'break') 발생하던 서버 비정상 종료(debug 및 새니타이저 빌드에서의 LOGICAL_ERROR / assertion)를 수정했습니다. #108796 (tiandiwonder).
  • 이전에 취소된 쿼리로 인해 동기화가 어긋난 연결이 풀에서 재사용될 때 분산 쿼리가 간헐적으로 UNEXPECTED_PACKET_FROM_SERVER(“expected TablesStatusResponse, got ProfileInfo”) 오류로 실패하던 문제를 수정했습니다. #108854 (alexey-milovidov).
  • Distributed 테이블에 대한 쿼리에서 MATERIALIZED CTE가 조인 트리의 여러 위치(예: 조인된 서브쿼리 2개, 또는 조인된 서브쿼리와 WHERE 절의 스칼라 서브쿼리)에서 참조될 때 발생하던 LOGICAL_ERROR(CTE '...' does not have query tree, but was not planned yet)를 수정했습니다. 이제 해당 쿼리는 예외 없이 정상적으로 실행됩니다(이전에는 debug/새니타이저 빌드에서 서버가 비정상 종료되었습니다). #108924 (groeneai).
  • materialized view 처리 중에 예약된 비동기 작업이 쿼리가 종료된 후에도 쿼리 수준의 리소스 추적 정보를 계속 사용할 수 있던 메모리 안전성 문제를 수정했습니다. #108988 (filimonov).
  • analyzer를 사용하지 않는 상태에서 UNION ALL/INTERSECT/EXCEPT의 한 브랜치는 병렬 레플리카와 함께 GROUP BY GROUPING SETS를 사용하고 다른 브랜치는 FINAL을 사용할 때 발생할 수 있던 LOGICAL_ERROR(“Cannot find __grouping_set column in header of MergingAggregatedTransform with grouping sets” 또는 “Chunk info was not set for chunk in MergingAggregatedTransform”)를 수정했습니다. #109003 (groeneai).
  • Replicated 데이터베이스에서 CREATE TABLE ... AS SELECT FROM s3Cluster(...)(및 fileCluster/urlCluster 등 다른 클러스터 테이블 함수)가 NOT_FOUND_COLUMN_IN_BLOCK 오류로 실패하던 문제를 수정했습니다. #109266 (groeneai).
  • 샤드가 2개 이상인 클러스터에서 Distributed 테이블을 읽는 CREATE TABLE ... ON CLUSTER ... AS SELECT를 실행할 때 발생하던 오류(NOT_FOUND_COLUMN_IN_BLOCK, 이전 버전에서는 std::bad_function_call)를 수정했습니다. #109407 (alexey-milovidov).
  • 테이블 표현식을 IN 연산자의 왼쪽 인수로 사용할 때 발생하던, 이해하기 어려운 내부 오류(Method getResultType is not supported for TABLE query tree node)를 수정했습니다. 이제 이러한 쿼리는 명확한 오류 메시지를 반환합니다. #109412 (alexey-milovidov).
  • optimize_const_name_size 값이 낮게 설정된 상태에서 Distributed 테이블에 대해 SELECT ... ORDER BY ... WITH FILL을 실행할 때 발생하던 Bad cast from type DB::FunctionNode to DB::ConstantNode 논리 오류(debug/새니타이저 빌드에서는 서버 중단)를 수정했습니다. #109938 (groeneai).
  • query_plan_merge_expression_into_join이 활성화된 상태에서 여러 테이블로 구성된 뷰에 쉼표 조인을 수행하면 조인 순서 최적화기에서 발생할 수 있던 LOGICAL_ERROR(Left and right columns have same names)를 수정했습니다. #110227 (groeneai).
  • LIMIT이 포함된 유효한 분산 쿼리에서 드물게 Logical error: 'No more packets are available.'가 발생하여 debug 및 새니타이저 빌드에서 서버가 중단되던 문제를 수정했습니다. #110334 (groeneai).
  • SELECT 쿼리가 별칭 없는 테이블 식별자 바로 뒤에서 끝날 때(예: ... FROM t COMMENT 'x') COMMENT가 암시적 별칭으로 잘못 해석되어, 코멘트가 뷰/테이블에 적용되지 않고 오해를 일으키는 구문 오류가 발생하던 파서 버그를 수정했습니다. #110372 (adityaksolves).
  • 선택도가 높은 필터가 있는 쿼리를 병렬 레플리카로 실행할 때 FixedString 컬럼에 대한 length()(및 QBit 차원)가 고정 크기 N 대신 0을 반환하던 잘못된 결과 문제를 수정했습니다. #110427 (groeneai).
  • 병렬 레플리카가 custom_key_sampling / custom_key_range 모드로 실행될 때 FROM에 서브쿼리가 포함된 쿼리에서 발생하던 NOT_FOUND_COLUMN_IN_BLOCK 오류를 수정했습니다. 이전에는 이러한 쿼리(예: SELECT * FROM (SELECT id, k, v FROM t WHERE id < 20) ORDER BY k)가 Not found column __table2.id in block ... 오류로 실패했습니다. #110690 (groeneai).
  • 일반적인 최상위 테이블 표현식이 아닌 스트리밍(FROM ... STREAM) 읽기가 포함된 쿼리에 대해 EXPLAIN ANALYZE를 실행할 때 발생하던 Logical error: 'clock' 문제를 수정했습니다(debug/sanitizer 빌드에서는 서버가 종료되고, 릴리스 빌드에서는 무한 대기 상태에 빠짐). 이는 스트리밍 읽기가 서브쿼리 안에 중첩되어 있거나(예: WHERE ... IN (...) 내부 또는 CTE) 일반 뷰나 매개변수화된 뷰 뒤에 가려져 있는 경우에 해당합니다. 이제 EXPLAIN ANALYZE는 최상위 스트리밍 읽기와 마찬가지로 이러한 쿼리도 NOT_IMPLEMENTED로 거부합니다. #110935 (groeneai).
  • 테이블 이름이 데이터베이스 이름과 같을 때 분석기가 db.table.column과 같은 정규화된 컬럼 이름을 올바르게 해석하지 못하던 문제를 수정했습니다. #110976 (alexey-milovidov).
  • parallel_replicas_min_number_of_rows_per_replica가 설정되어 있고 왼쪽 테이블의 컬럼을 프로젝션하는 경우 RIGHT JOIN에서 발생하던 NOT_FOUND_COLUMN_IN_BLOCK / THERE_IS_NO_COLUMN 오류(일부 릴리스에서는 오류 없이 잘못된 결과 반환)를 수정했습니다. #111332 (groeneai).
  • 실행형 UDF, executable 테이블 엔진, 실행형 딕셔너리에서 이미 닫힌 파일 디스크립터에 fcntl을 호출하면 동시에 실행 중인 다른 쿼리의 무관한 디스크립터가 손상되어(O_NONBLOCK 플래그 제거) 쿼리가 무기한 멈출 수 있던 경쟁 상태를 수정했습니다. #111779 (Algunenano).
  • 2개 이상의 세그먼트로 구성된 Distributed 테이블, clusterAllReplicas, 또는 사용자 지정 키 기반 병렬 레플리카에 대해 ORDER BY ... WITH FILL ... INTERPOLATE를 실행할 때(결과가 비어 있는 경우 포함) 발생하던 LOGICAL_ERROR(“Invalid number of rows in Chunk”)와, 강화(hardened) 빌드에서 이와 관련해 발생하던 범위 초과로 인한 비정상 종료를 수정했습니다. 이제 WITH FILL은 최종 결과를 생성하는 노드에서만 적용되므로, 생성된 채우기 행이 세그먼트/레플리카 간에 중복되던 문제도 함께 해결되었습니다. #111919 (yakov-olkhovskiy).
  • system.replicas에 대한 쿼리가 상태 요청이 처리되기 전에 종료(kill)되면 DROP TABLE ... SYNC가 끝없이 멈춰 있던 문제를 수정했습니다. #112164 (evillique).
  • 두 하위 조인이 모두 출력 컬럼을 생성하지 않는 다중 테이블 조인에서 발생하던 LOGICAL_ERROR 예외(Block structure mismatch in joined block stream)를 수정했습니다. 예를 들어 query_plan_optimize_join_order_limit를 0 또는 1로 설정한 상태에서 SELECT count() FROM t1, t2, t3, t4 WHERE (t1.b = t2.b) AND (t3.a = t4.a)를 실행하면 이 문제가 발생했습니다. #112205 (groeneai).
  • FINAL, PREWHERE 필터, 작은 LIMIT, make_distributed_plan = 1을 사용하는 쿼리에서 선택한 컬럼의 순서가 테이블의 컬럼 순서와 다를 때 발생하던 논리 오류 Cannot add step Expression to QueryPlan because it has incompatible header with root step JoinLazyColumnsStep을 수정했습니다. 지연 materialization이 계획 노드를 교체하면서 해당 노드의 출력 헤더를 유지하지 않아 쿼리 계획의 일관성이 깨지는 문제가 있었습니다. #112303 (groeneai).
  • 이전 분석기를 사용할 때 toDecimal32의 스케일이나 toDateTime의 시간대처럼 상수여야 하는 인수를 스칼라 서브쿼리로 전달하면 잘못된 결과와 논리 오류가 발생하던 문제를 수정했습니다. 이러한 인수는 값이 0이거나 비어 있는 것으로 간주되어 분석되었기 때문에 선언된 결과 유형과 실제 계산된 값이 일치하지 않았고, CREATE VIEW 및 CREATE MATERIALIZED VIEW에서는 잘못된 컬럼 유형이 저장되었습니다. #112492 (groeneai).
  • 일반 VIEW 본문이 CREATE VIEW v AS SELECT x FROM {db:Identifier}.t와 같이 쿼리 매개변수를 통해 테이블 또는 딕셔너리를 참조할 때 발생하던 논리 오류와 잘못된 의존성 기록 문제를 수정했습니다. 이제 이러한 뷰는 현재 데이터베이스에 있는 같은 이름의 테이블에 대한 참조 의존성을 기록하지 않으므로, 관련 없는 테이블을 다시 삭제할 수 있습니다. #112704 (groeneai).
  • Join 테이블 엔진을 JOIN의 오른쪽에 사용하고, 해당 JOIN의 ON 절에 ON (t.key = j.key) AND (t.a < j.a)처럼 두 테이블의 컬럼을 모두 참조하는 조건이 포함된 경우 발생하던 논리 오류를 수정했습니다. 이제 이러한 쿼리는 required columns: ... but not found any in left table 또는 std::bad_variant_access를 발생시키는 대신 명확한 예외와 함께 거부됩니다. #112815 (groeneai).
  • REFRESH AFTER 주기가 매우 긴 갱신 가능 구체화 뷰처럼 백그라운드 작업이 매우 큰 지연 시간으로 예약될 때 발생하던 정의되지 않은 동작과, 아무런 알림 없이 발생하던 스케줄링 오류를 수정했습니다. 이제 지연 시간은 오버플로되지 않고 표현 가능한 최댓값으로 제한됩니다. #113041 (groeneai).
  • Distributed 테이블에 대한 비동기 INSERT에 255바이트 파일 시스템 제한을 초과하는 이름의 큐 디렉터리가 필요할 때(use_compact_format_in_distributed_parts_names = 0에서 발생 가능) 보고되던 오류를 수정했습니다. 기존에는 internal_replication이 설정된 샤드(shard)에서는 LOGICAL_ERROR가, 그 외에는 출처를 알 수 없는 Code: 1001. std::exception이 보고되었으나, 이제 두 경우 모두 테이블, 클러스터, 제한 값을 명시한 ARGUMENT_OUT_OF_BOUND를 보고합니다. #113083 (groeneai).
  • 이제 UNDROP TABLE이 실행 중인 쿼리가 삭제된 테이블을 해제하기를 기다리는 동안 KILL QUERY로 중단할 수 있습니다. #113263 (alexey-milovidov).
  • materialized CTE를 사용하는 쿼리가 실패한 후 DROP TABLE이 영구적으로 멈추고 메모리 누수가 발생하던 문제를 수정했습니다. 기존에는 해당 테이블이 서버를 재시작할 때까지 삭제 큐에 남아 있었습니다. #113397 (tiandiwonder).
  • make_distributed_plan 사용 시 서브쿼리가 자체 SETTINGS 절에서 distributed_plan_execute_locally를 설정하면 발생하던 세그멘테이션 오류(segfault)와 LOGICAL_ERROR(No host found for exchange stream final_result__0_0)를 수정했습니다. 분산 실행 계획과 이를 실행하는 코드가 서로 다른 컨텍스트에서 설정을 읽어 값이 어긋날 수 있었기 때문에, 이니시에이터가 자기모순적인 파이프라인을 구성했습니다. #113422 (groeneai).
  • database_atomic_wait_for_drop_and_detach_synchronously가 활성화된 상태에서 데이터를 채우는 SELECT가 실패하면 CREATE TABLE ... AS SELECT를 강제 종료할 수 없게 되던 문제를 수정했습니다. 임시 테이블을 정리하는 내부 DROP이 백그라운드 삭제 큐를 기다리면서 KILL QUERY와 max_execution_time을 모두 무시했습니다. #113504 (groeneai).
  • join_use_nulls가 활성화된 상태에서 ON (t.key = d.key) AND (t.a * 10 < d.a)처럼 ON 절에 두 테이블에 걸친 비등가 조건이 있는 딕셔너리 대상 JOIN이 잘못된 결과를 반환하고, 어서션이 활성화된 빌드에서는 어서션 실패로 중단되던 문제를 수정했습니다. 일치하지 않는 타입으로 읽은 컬럼에 대해 조건이 평가되어 행이 임의로 매칭될 수 있었습니다. #113534 (alexey-milovidov).
  • 매개변수화된 뷰(parameterized view)를 데이터베이스 이름 없이 참조하는 쿼리가 세그먼트로 전송될 때 뷰의 데이터베이스 정보가 유실되어, 세그먼트가 자신의 기본 데이터베이스를 기준으로 이름을 해석하던 문제를 수정했습니다. 해당 데이터베이스의 내용에 따라 쿼리가 UNKNOWN_FUNCTION 오류로 실패하거나, 아무런 경고 없이 다른 뷰의 행을 반환했습니다. Distributed 테이블을 통한 IN, JOIN, remote()에 영향을 줍니다. #113550 (groeneai).
  • 키가 복합 키(여러 컬럼)이거나 UUID, Int256, FixedString(4)처럼 16/32바이트 단일 값인 Join 엔진 테이블을 읽을 때 Unsupported JOIN keys of type keys256 in StorageJoin 오류가 발생하던 문제를 수정했습니다. 이러한 테이블은 생성, 쓰기, 조인은 가능했지만 SELECT로 다시 읽을 수는 없었습니다. #113578 (groeneai).
  • 원격 세그먼트를 대상으로 하는 구조 정의 없는 Distributed 테이블을 attach하거나, 이전 버전 서버가 기록한 메타데이터에서 로드할 때 Sending a distributed query with unknown (zero) client version 논리 오류가 발생하던 문제를 수정했습니다. #113675 (alexey-milovidov).
  • SELECT에서 이름이 지정된 테이블에 STREAM 수정자를 사용하면서 read-tasks 모드의 병렬 레플리카를 함께 사용할 때 LOGICAL_ERROR가 발생하던 문제를 수정했습니다. 구체화된 CTE(materialized CTE)를 PREWHERE의 IN 집합으로 사용하면 서버에서 Reading from materialized CTE ... DelayedPortsProcessor gate is missing in the query plan 오류가 발생했습니다(debug 및 새니타이저 빌드에서는 서버가 비정상 종료됨). 이제 병렬 레플리카가 요청되면 STREAM이 지정된 테이블은 거부됩니다. enable_parallel_replicas = 2이면 쿼리가 SUPPORT_IS_DISABLED로 실패하고, 1이면 병렬 레플리카 없이 실행됩니다. 이는 기존 FINAL의 동작과 동일합니다. #113754 (groeneai).
  • remote, mysql 등 테이블 함수의 주소 인수를 파싱할 때 2차 시간 복잡도가 발생하던 문제를 수정했습니다. 매우 긴 주소(예: 0으로 채워진 메가바이트 크기의 FixedString)가 주어지면 쿼리가 분석 단계에서 멈췄으며, 이 단계에서는 쿼리를 취소할 수도 없었습니다. #113918 (alexey-milovidov).
  • database_atomic_wait_for_drop_and_detach_synchronously가 활성화된 상태에서 갱신 가능 구체화 뷰의 갱신이 취소될 때(예: 서버 종료) Failed to drop temporary table after refresh. Table ... is left behind and requires manual cleanup. 오류가 잘못 기록되던 문제를 수정했습니다. 실제로는 임시 테이블이 정상적으로 삭제되었으므로 수동 정리가 필요한 경우는 없었습니다. #113957 (groeneai).
  • materialized_views_ignore_errors가 활성화된 상태에서 의존성 수집 중 실패한 materialized view에 대해 system.query_views_log 행이 누락되던 문제를 수정했습니다. debug 및 새니타이저 빌드에서는 해당 뷰를 로그에 기록하는 대신 std::out_of_range로 서버가 비정상 종료되기도 했습니다. #114064 (groeneai).
  • 오른쪽 테이블의 키가 아닌 컬럼에 대한 필터가 ANY INNER JOIN 아래로 푸시다운될 때 결과가 일관되지 않던 문제를 수정했습니다. #114313 (kirillshokhin).
  • ignore_drop_queries_probability가 설정되어 있으면 CREATE OR REPLACE가 내부 _tmp_replace_* 테이블을 남기고, CREATE OR REPLACE VIEW가 NOT_IMPLEMENTED로 실패하던 문제를 수정했습니다. 내부적으로 실행되는 DROP은 하나의 사용자 구문을 구성하는 단계이므로, 이제 DROP 장애 주입이 적용되지 않습니다. #114420 (groeneai).
  • metaData.partitionColumns에 metaData.schemaString에서 선언되지 않은 컬럼이 지정된 Delta Lake 테이블을 읽을 때 LOGICAL_ERROR가 발생하던 문제를 수정했습니다. 이제 이러한 메타데이터는 쿼리에 프레디케이트가 포함된 경우뿐만 아니라 테이블이나 스키마를 스냅샷에서 읽을 때마다 거부되며, delta-kernel 리더에서는 BAD_ARGUMENTS, 레거시 리더에서는 INCORRECT_DATA 오류가 반환됩니다. #114538 (groeneai).
  • 지연 FINAL 최적화(query_plan_optimize_lazy_final)를 사용하는 쿼리가 서버 시작 후 처음 실행되는 집계일 때, 해시 테이블 통계와 이에 따른 집계 해시 테이블 사전 할당이 서버 전체에서 아무런 알림 없이 영구적으로 비활성화되던 문제를 수정했습니다. #114597 (alexey-milovidov).
  • ignore_drop_queries_probability가 활성화된 경우 갱신 가능 구체화 뷰에서 교체되어 빠진 target table이 삭제되지 않고 남던(누수) 문제를 수정했습니다. 갱신 과정에서 이전 target을 정리하기 위해 실행하는 DROP은 사용자가 요청한 DROP이 아니라 갱신의 한 단계이므로, 이제 여기에는 장애 주입이 적용되지 않습니다. #114622 (groeneai).
  • ON 절에 OR로 연결된 조건이 여러 개 있을 때 ANY RIGHT JOIN 및 SEMI RIGHT JOIN이 오른쪽 테이블의 일부 행을 중복 반환하고 다른 행의 매칭은 누락하던 문제를 수정했습니다. 플래너가 테이블 순서를 바꿔 ANY RIGHT JOIN으로 실행할 수 있으므로, 직접 작성한 ANY LEFT JOIN도 영향을 받았습니다. #114676 (vdimir).
  • 텍스트 인덱스가 적용된 컬럼이 PREWHERE와 WHERE 텍스트 검색 프레디케이트에 모두 사용되는 테이블 위에 JOIN이 있는 쿼리에서 LOGICAL_ERROR(Cannot find input column ... on its position in inputs of expression actions DAG)가 발생하던 문제를 수정했습니다. #114771 (groeneai).
  • ALIAS 또는 EPHEMERAL 컬럼에 STATISTICS(...)를 선언한 테이블에 INSERT할 때마다 NOT_FOUND_COLUMN_IN_BLOCK이 발생하여 해당 테이블이 사실상 읽기 전용이 되던 문제를 수정했습니다. #115231 (groeneai).
  • 분산 쿼리에서 dictGet 및 관련 변형 함수의 동작을 수정했습니다. 이제 데이터베이스가 지정되지 않은 딕셔너리 이름은 각 샤드의 현재 데이터베이스가 아니라 initiator의 현재 데이터베이스를 기준으로 바인딩됩니다. 기존에는 샤드에서 딕셔너리를 찾지 못하거나 같은 이름의 다른 딕셔너리로 해석되는 문제가 있었습니다. #115541 (alexey-milovidov).
  • 데이터베이스나 테이블을 새 이름으로 복원할 때 저장된 뷰 본문에서 테이블 별칭이 누락되어, 복원된 뷰를 읽으면 UNKNOWN_IDENTIFIER 오류가 발생하던 버그를 수정했습니다. #115645 (groeneai).
  • Distributed 테이블에 대한 IN 서브쿼리 내부에서 MATERIALIZED CTE를 읽을 때 LOGICAL_ERROR “Reading from materialized CTE ‘X’ before its materialization completed - DelayedPortsProcessor gate is missing in the query plan”이 발생하던 문제를 수정했습니다. #115740 (groeneai).
  • 의존성 검사(HAVE_DEPENDENT_OBJECTS)로 인해 DETACH DICTIONARY … PERMANENTLY가 거부된 후 dictGet에서 BAD_ARGUMENTS “Dictionary not found” 오류가 발생하던 문제를 수정했습니다. 이제 분리가 거부되면 딕셔너리를 그대로 정상 사용할 수 있습니다. #105259 (groeneai).
  • 백그라운드 테이블 삭제 큐에서 발생하던 Logical error: 'removed'(디버그 빌드에서는 서버 중단)를 수정했습니다. 이 오류는 동일한 명시적 UUID를 여러 CREATE OR REPLACE TABLE 쿼리에서 재사용할 때 발생할 수 있었으며, 이 경우 같은 UUID를 공유하는 삭제된 테이블이 두 개 이상 큐에 추가되었습니다. #107031 (groeneai).
  • 서버가 중단된 동안 복제된 테이블 하나의 구조가 변경되면 MaterializedPostgreSQL이 데이터베이스 전체의 복제를 중지하던(LOGICAL_ERROR: Columns number mismatch 발생) 문제를 수정했습니다. 이제 영향을 받은 테이블만 건너뛰며, 해당 테이블은 DETACH/ATTACH로 복구할 수 있습니다. #107427 (alexey-milovidov).
  • 클러스터에 비활성 레플리카(예: 오토스케일링 후 남은 오래된 항목)가 있을 때 병렬 레플리카의 작업 분배가 심하게 편중되던 문제를 수정했습니다. 이제 읽기 코디네이터가 이러한 레플리카를 집계하지 않으므로, 작업이 한 레플리카에 몰리지 않고 온라인 레플리카 전체에 고르게 분배됩니다. #107805 (alexey-milovidov).
  • XML로 정의된 여러 MySQL 딕셔너리가 share_connection을 통해 하나의 연결 풀을 공유할 때 SYSTEM RELOAD DICTIONARIES(및 RELOAD DICTIONARY)가 멈추던 문제를 수정했습니다. 이제 이러한 풀은 이름이 지정된 컬렉션으로 정의된 딕셔너리와 마찬가지로 구성의 connection_pool_size 및 connection_wait_timeout(기본값 5초)을 따릅니다. #108083 (alexey-milovidov).
  • 리더가 실행하는 복제된 분산 DDL의 재시도 횟수가 소진되어도 이후의 ON CLUSTER DDL 쿼리가 영구적으로 차단되지 않도록 수정했습니다. #108505 (ahaanlimaye).
  • 동일한 Distributed 테이블에 대해 SYSTEM FLUSH DISTRIBUTED와 DROP TABLE이 동시에 실행될 때 발생할 수 있던 크래시(use-after-free)를 수정했습니다. #108684 (groeneai).
  • automatic_parallel_replicas_mode를 활성화하고 parallel_replicas_min_number_of_rows_per_replica를 0보다 큰 값으로 설정했을 때 자동 병렬 레플리카 플래너에서 발생할 수 있던 LOGICAL_ERROR(local_replica_plan_reading_step->getAnalyzedResult() == nullptr)를 수정했습니다. #109011 (groeneai).
  • 비트랜잭션 TRUNCATE가 같은 테이블에 데이터를 삽입한 미커밋 트랜잭션과 동시에 실행될 때 발생할 수 있던 LOGICAL_ERROR(creation_csn is not set while removal_csn is set to 1)를 수정했습니다. 이제 이러한 TRUNCATE는 아직 커밋되지 않은 트랜잭션이 생성한 파트를 제거하지 않습니다. #109598 (tuanpach).
  • 외부 데이터베이스 엔진(예: PostgreSQL)이 더 이상 UUID 컬럼에 대한 범위 비교(>=, >, <=, <)를 푸시다운하지 않습니다. ClickHouse와 외부 데이터베이스는 UUID 정렬 방식이 서로 달라, 이러한 비교를 푸시다운하면 결과에서 행이 아무런 경고 없이 누락되었습니다. 이제 이러한 조건식은 ClickHouse에서 평가합니다. #109833 (vismaytiwari).
  • 동기화 대기 중인 테이블이 분리되거나 구조가 변경될 때 MaterializedPostgreSQL 데이터베이스 엔진에서 발생할 수 있던 서버 크래시를 수정했습니다. #110596 (alexey-milovidov).
  • 서버의 query_masking_rules로 인해 EPHEMERAL 컬럼의 유형이 변경되던 문제를 수정했습니다. 유형 내부와 일치하는 규칙이 있으면 CREATE TABLE이 잘못된 유형을 저장하거나 실패했습니다. #112048 (alexey-milovidov).
  • 테이블 이름 길이 검사에서 발생하던 부호 없는 정수 언더플로(underflow)를 수정했습니다. 이 문제로 인해 삭제할 수 없는 테이블이 생성될 수 있었습니다. 이스케이프된 데이터베이스 이름이 214바이트에 도달하면 metadata_dropped 파일 이름에 대해 계산된 제한 값이 랩어라운드되어, CREATE TABLE은 허용되지만 이후의 DROP TABLE 또는 DROP DATABASE는 File name too long 오류로 실패했습니다. 이제 이러한 이름은 해당 경계 바로 아래에서 이미 반환되던 것과 동일한 ARGUMENT_OUT_OF_BOUND 오류로 거부됩니다. #112527 (groeneai).
  • RENAME TABLE이 최대 테이블 이름 길이를 대상 데이터베이스가 아닌 원본 데이터베이스 기준으로 검사하던 문제를 수정했습니다. 이름이 긴 데이터베이스로 테이블을 옮기며 이름을 변경하면 DROP TABLE로 제거할 수 없는 테이블이 생성될 수 있었고, 반대로 그러한 데이터베이스에서 테이블을 다른 데이터베이스로 옮기는 이름 변경은 잘못 거부되었습니다. #113019 (groeneai).
  • 대상 테이블이 materialized view를 트리거하는 Alias 테이블에 삽입할 때 query_log의 views 컬럼이 항상 비어 있던 문제를 수정했습니다. #113076 (eclbg).
  • tuple() 또는 (x, y)와 같은 잘못된 parallel_replicas_custom_key 표현식은 이제 사용자 정의 키 타입 목록의 범위를 넘어 읽는 대신 ILLEGAL_TYPE_OF_COLUMN_FOR_FILTER 오류로 거부됩니다. #113359 (nickitat).
  • RENAME DATABASE가 데이터베이스의 테이블을 삭제할 수 없게 만들 만큼 긴 대상 이름을 허용하던 문제를 수정했습니다. 이제 테이블 이름 길이 검사는 check_table_dependencies와 관계없이 실행되며, 분리된 테이블(detached table)도 검사 대상에 포함됩니다. 분리된 테이블은 이전에는 전혀 검사되지 않아 기본 설정에서도 이 문제의 영향을 받았습니다. #113557 (groeneai).
  • Distributed 엔진을 사용하는 테이블에 백그라운드 삽입을 수행할 때, 원격 샤드(shard)로 데이터를 전송하는 중 반복된 오류로 인해 발생한 지연이 이제 오류가 해소되면 감소합니다. 이전에는 지연이 증가하기만 하고 초기화되지 않았습니다. #87378 (Blackmorse).
  • 알 수 없는 클러스터 또는 <secret> 없이 구성된 클러스터에 대해 USER_INTERSERVER_MARKER를 사용하는 native protocol 핸드셰이크를 거부합니다. 이전에는 이러한 핸드셰이크를 통해 인증되지 않은 클라이언트가 서버 간(interserver) 모드에 진입하여 fake_interserver_context 기반의 인증 전 프로토콜 패킷(예: TablesStatusRequest)을 실행할 수 있었으며, 클러스터 시크릿을 알고 있음을 증명하지 않고도 로컬 테이블 정보를 알아낼 수 있었습니다. #99675 (MillaFleurs).

SQL, 분석기 및 JOIN 관련 수정 사항

  • 이름이 지정된 WINDOW 절의 정의 내부에서 쿼리 매개변수 치환이 이루어지지 않던 문제를 수정했습니다. 이전에는 이 위치의 매개변수가 아무런 알림 없이 치환되지 않은 채 남아 있었으며, 설정되지 않은 Identifier 매개변수로 인해 EXPLAIN SYNTAX 실행 중 Logical error: '!part.empty()' 예외가 발생할 수 있었습니다. #110506 (alexey-milovidov).
  • 갱신 가능 구체화 뷰(Refreshable Materialized View)가 동시에 삭제되거나 교체될 때 드물게 서버가 비정상 종료되던 문제를 수정했습니다. 스케줄링 코드가 일시적으로 뮤텍스를 해제한 사이에 다른 스레드가 작업의 view를 nullptr로 설정하면 RefreshTask::doScheduling에서 널 포인터 역참조가 발생했습니다. #105588 (groeneai).
  • 피연산자가 UNION 체인인 EXCEPT 또는 INTERSECT로 정의된 뷰가 DETACH/ATTACH 또는 서버 재시작 후 잘못된 결과를 반환하던 문제를 수정했습니다. 포매터가 INTERSECT/EXCEPT의 하위 UNION 항목을 괄호로 감싸지 않아, 저장된 SQL을 다시 파싱할 때 연산자 우선순위가 뒤바뀌었습니다. #105935 (groeneai).
  • 동일한 키에 대해 WITH CUBE, WITH ROLLUP 또는 GROUPING SETS를 사용하는 GROUP BY 결과에 SELECT DISTINCT를 적용할 때 잘못된 결과(중복 행)가 반환되던 문제를 수정했습니다. 그룹화 수정자는 키 컬럼이 기본값으로 채워진 추가 행을 생성하며, 이 행이 실제 그룹 값과 충돌할 수 있습니다. 따라서 이제 query_plan_remove_redundant_distinct 최적화는 이러한 경우 DISTINCT를 제거하지 않습니다. #107072 (groeneai).
  • WHERE 필터가 상수 항을 포함하는 논리곱일 때(예: p AND 1, 또는 QUALIFY NULL이 WHERE에 병합되는 WHERE p QUALIFY NULL) OUTER JOIN이 잘못된 결과를 반환하던 문제를 수정했습니다. 상수 논리곱 항이 조인의 비보존 측으로 푸시다운되면서 조인 후 필터에서 제거될 수 있었고, 그 결과 조인이 해당 측 컬럼이 기본값으로 채워진 비매칭 행을 생성했으며 이 행들이 필터를 잘못 통과했습니다. #107084 (groeneai).
  • correlated_subqueries_default_join_kind = 'left'일 때, 동일한 컬럼 식별자를 두 번 프로젝션하는 소스(예: SELECT number, *)에 대한 상관 스칼라 서브쿼리로 인해 서버가 중단되던 LOGICAL_ERROR(“Cannot find input column … on its position in inputs of expression actions DAG”)를 수정했습니다. #107112 (groeneai).
  • 이전 분석기(enable_analyzer = 0) 사용 시, JOIN에서 널 안전 비교 연산자(<=> / IS NOT DISTINCT FROM)를 사용하고 키 중 하나가 스칼라 서브쿼리일 때(예: ... JOIN t2 ON (SELECT x FROM t1) <=> t2.k) 발생하던 LOGICAL_ERROR(디버그/새니타이저 빌드에서 서버 중단)를 수정했습니다. 이제 이러한 쿼리는 논리 오류 대신 일반적인 NOT_FOUND_COLUMN_IN_BLOCK 오류를 반환합니다. #108123 (groeneai).
  • SEMI/ANTI 조인(EXISTS 상관 서브쿼리의 비상관화로 생성된 조인 포함)에 join_algorithm = 'full_sorting_merge'를 사용할 때 발생하던 LOGICAL_ERROR(Join is supported only for pipelines with one output port) 및 NOT_IMPLEMENTED(MergeJoinAlgorithm is not implemented for strictness Semi) 예외를 수정했습니다. 이제 full_sorting_merge는 실행할 수 없는 엄격성/종류 조합을 거부하므로, 플래너는 활성화된 다른 알고리즘으로 대체하거나 조인을 실행할 수 없다고 보고합니다. #108658 (groeneai).
  • 조인의 한쪽에 상수 서브쿼리가 있을 때 JOIN의 WITH TOTALS 행에 상수 서브쿼리의 상수 값 대신 기본값(예: 0)이 포함될 수 있던 버그를 수정했습니다. 이 잘못된 결과는 일부 조인 순서에서만 나타나거나 query_plan_join_swap_table 설정을 사용할 때만 나타났습니다. #108807 (vdimir).
  • 시그널 스택 크기가 큰 CPU(예: AMX를 인식하는 커널을 사용하는 Intel Sapphire Rapids / Granite Rapids)에서 실행되는 glibc 빌드에서 aligned_alloc 호출 전에 시그널 대체 스택 크기가 페이지 크기의 배수로 올림되지 않아 시작 시 비정상 종료(Cannot allocate ThreadStack, EINVAL)되던 문제를 수정했습니다. #108813 (groeneai).
  • 상관 서브쿼리가 조인으로 비상관화되고 소스 릴레이션에 동일한 컬럼명이 두 번 이상 포함된 경우(예: correlated_subqueries_default_join_kind = 'right' 설정에서 WITH t AS (SELECT number, * FROM numbers(3)) SELECT *, (SELECT t.number WHERE t.number >= 0) FROM t 실행) 발생하던 Block structure mismatch in JoinStep 논리 오류(debug/새니타이저 빌드에서 서버 비정상 종료)를 수정했습니다. #109114 (groeneai).
  • CREATE USER ... HOST LIKE 'a', 'b'(및 이에 상응하는 ALTER USER)가 아무런 알림 없이 첫 번째 패턴만 유지하던 문제를 수정했습니다. 이제 지정된 모든 HOST LIKE 패턴이 사용자의 호스트 허용 목록에 저장됩니다. #109187 (groeneai).
  • 상수 ON 조건을 사용하는 ANY JOIN(예: t1 ANY INNER JOIN t2 ON 1)에서 쿼리가 ANY 조인 결과 대신 전체 카테시안 곱을 반환하던 문제를 수정했습니다 #109207 (vdimir).
  • parallel_hash 조인 알고리즘에서 전역 max_rows_in_join / max_bytes_in_join 제한이 적용되지 않아, join_overflow_mode = 'throw'를 사용하는 쿼리가 SET_SIZE_LIMIT_EXCEEDED를 발생시키지 않고 그대로 성공할 수 있던 문제를 수정했습니다. #109488 (m-selmi).
  • 서버 측 인라인 삽입 파싱 경로(send_table_structure_on_insert_with_inline_data = 0)에서 다중 쿼리 스트림의 INSERT ... VALUES 뒤에 후행 SQL 주석(예: VALUES (1) -- comment)이 오는 경우 데이터가 알림 없이 손실되던 문제를 수정했습니다. 후행 주석이 종료 문자 ; 이후까지 행 데이터로 스캔되어, 스트림의 후속 쿼리가 아무런 알림 없이 건너뛰어졌습니다. #109643 (groeneai).
  • PREWHERE가 FINAL 이후에 실행될 때 optimize_move_to_prewhere = 1과 함께 사용되는 지연된 PREWHERE의 동작을 수정했습니다. 이제 WHERE 조건이 지연된 ROW POLICY보다 앞으로 이동하지 않습니다. 기존에는 이로 인해 쿼리 결과가 달라질 수 있었습니다. #109703 (yariks5s).
  • 재귀 CTE가 외부 스코프의 식별자를 상관 컬럼으로 해석할 때(allow_experimental_correlated_subqueries = 1 사용 시) 발생하던 LOGICAL_ERROR(query tree node does not have valid source node)를 수정했습니다. 이제 이러한 쿼리는 명확한 UNSUPPORTED_METHOD 오류를 반환합니다. #109863 (groeneai).
  • ORDER BY ... WITH FILL이 Int64/UInt64 컬럼에서 매우 큰 공백을 건너뛸 때(예: 2^63 부근의 공백을 간격 2로 건너뛰는 경우) 발생하던 부호 있는 정수 오버플로우를 수정했습니다. 이 오버플로우는 새니타이저에서 정의되지 않은 동작(undefined behavior)으로 감지되었으며, 릴리스 빌드에서는 알림 없이 랩어라운드되었습니다. #109937 (groeneai).
  • 이전 분석기(enable_analyzer = 0)를 사용할 때 INTERPOLATE 대상이 WITH FILL 컬럼의 별칭이면 발생하던 Invalid number of rows in Chunk 논리 오류를 수정했습니다. 이제 이러한 쿼리는 명확한 INVALID_WITH_FILL_EXPRESSION 오류와 함께 거부됩니다. #110103 (groeneai).
  • 상관 서브쿼리(예: exists((SELECT ...)))를 포함하는 필터가 convert_query_to_cnf 또는 optimize_and_compare_chain으로 최적화될 때 발생하던 논리 오류(Unexpected number of columns in result sample block)를 수정했습니다. #110187 (alexey-milovidov).
  • 바로 바깥의 외부 쿼리를 넘어 더 상위 범위의 컬럼을 참조하는(중간 범위를 건너뛰는) 중첩 상관 EXISTS 서브쿼리는 이제 내부 오류인 NOT_FOUND_COLUMN_IN_BLOCK 대신 명확한 NOT_IMPLEMENTED 오류와 함께 실패합니다. #110310 (groeneai).
  • 외부 쿼리의 상관 컬럼에 중복 값이 있고 서브쿼리가 CROSS JOIN 경로를 통해 비상관화될 때 상관 스칼라 서브쿼리가 잘못된 결과를 반환하던 문제를 수정했습니다. 이전에는 count(), sum() 같은 집계 결과에 중복 개수가 곱해졌습니다. 이 문제는 Experimental 기능인 allow_experimental_correlated_subqueries에 해당합니다. #110311 (groeneai).
  • 큰 채우기 범위를 생성할 때(특히 INTERPOLATE 사용 시) ORDER BY ... WITH FILL이 max_execution_time을 준수하지 않고 취소에 오랜 시간이 걸리던 문제를 수정했습니다. #110332 (alexey-milovidov).
  • 지연 실행 FINAL 최적화(query_plan_optimize_lazy_final, 기본값은 비활성화)는 이제 쿼리가 정렬 키 순서로 데이터를 읽을 때 적용되지 않습니다. 이 최적화의 대체 계획은 정렬 키 순서로 행을 생성하지 않지만, 상위 계획은 read-in-order 최적화 이후 이미 해당 순서에 의존하고 있을 수 있어 결과가 잘못된 순서로 반환될 수 있기 때문입니다. 또한 읽을 행 수보다 작은 LIMIT이 읽기 단계에 직접 적용되는 경우에도 이 최적화가 적용되지 않습니다. 이 경우 필수적인 집합 구성 단계 때문에 조기 종료의 이점이 사라지기 때문입니다. #110576 (KochetovNicolai).
  • 이제 백그라운드 비동기 insert 플러시를 KILL QUERY로 종료하면 즉시 중지됩니다. 이전에는 버퍼링된 대용량 페이로드를 플러시하는 경우 취소를 무시하고 끝까지 파싱을 계속했습니다. #110652 (tiandiwonder).
  • partial_merge JOIN 위에 배치된 GROUP BY ... optimize_aggregation_in_order 및 DISTINCT ... optimize_distinct_in_order가 잘못된 결과를 반환하던 문제를 수정했습니다. read-in-order 최적화가 PartialMergeJoin을 통해 전파되었는데, PartialMergeJoin은 왼쪽 입력을 조인 키 기준으로 다시 정렬하므로 왼쪽 스트림의 원래 순서가 유지되지 않아 행이 잘못 그룹화되었습니다. #110671 (groeneai).
  • INTERSECT 또는 EXCEPT 쿼리에서 CTE 컬럼 별칭을 사용할 때(예: WITH t (a, b) AS (SELECT 1, 2 INTERSECT SELECT 1, 2) SELECT a, b FROM t) 쿼리가 UNKNOWN_IDENTIFIER 오류로 실패하던 문제를 수정했습니다. #110885 (yariks5s).
  • 여러 스레드가 리더를 공유하는 상황에서 스필된 블록을 읽는 도중 실패하면 grace_hash 조인에서 발생할 수 있던 LOGICAL_ERROR: ReadBuffer is canceled. Can't read from it. 오류를 수정했습니다. #111056 (groeneai).
  • *_hash JOIN 수행 중 우측(right-side) 컬럼을 구체화할 때 잘못된 시간대가 적용되던 버그를 수정했습니다. #111074 (yariks5s).
  • COMMENT 절이 포함된 CREATE 문에서 주석 문자열 리터럴이 누락되면, 잘못 파싱된 쿼리를 오류 없이 허용하는 대신 구문 오류를 발생시키도록 수정했습니다(예: CREATE VIEW v COMMENT AS SELECT 1은 더 이상 주석 없는 뷰를 생성하지 않습니다). #111159 (tiandiwonder).
  • 재사용되는 구체화된 CTE(enable_materialized_cte)를 WITH TOTALS 또는 extremes 출력이 버려지는 브랜치에서 읽을 때 발생하던 LOGICAL_ERROR(Reading from materialized CTE '...' before its materialization completed - DelayedPortsProcessor gate is missing in the query plan)를 수정했습니다. 외부 집계, INSERT ... SELECT, 집합 연산, EXPLAIN ANALYZE에서 발생하던 경우도 함께 수정되었습니다. #111194 (groeneai).
  • join_algorithm = 'full_sorting_merge' 사용 시 LEFT/RIGHT/FULL/ASOFJOIN에서 조인되지 않은 행을 컬럼 타입 기본값 대신 원시 0으로 채우던 문제를 수정했습니다. 기본값이 0이 아니라 첫 번째 원소인 Enum 컬럼에서는 이로 인해 잘못된 결과가 발생했으며(채워진 값에 대한 필터가 매칭되지 않은 행을 제거하여 외부 조인이 경고 없이 내부 조인처럼 동작함), 해당 컬럼을 선택하면 UNKNOWN_ELEMENT_OF_ENUM 오류가 발생했습니다. #111197 (groeneai).
  • optimize_move_to_prewhere_if_final = 1이고 WHERE 절이 정렬 키 컬럼에 대한 암시적 불리언 조건(예: WHERE k)일 때, FINAL을 사용한 SummingMergeTree(및 CoalescingMergeTree)가 잘못된 결과를 반환하던 문제를 수정했습니다. 키 컬럼이 원래 값을 유지하지 않고 머지되지 않은 파트들에 걸쳐 합산된 값으로 반환되었습니다. #111342 (groeneai).
  • 좌측에 UNION ALL을 거쳐서도 남아 있는 동일한 이름의 중복 컬럼(예: 1 AS b, 1 AS b)이 있을 때 RIGHT/FULL JOIN에서 발생할 수 있던 논리 오류(Unexpected number of columns in result sample block)를 수정했습니다. #111554 (groeneai).
  • AST fuzzer처럼 AST의 자식 노드가 교체된 EXECUTE AS 쿼리를 포맷팅할 때 클라이언트가 크래시되던 문제를 수정했습니다. 이제 ASTExecuteAsQuery는 children을 가리키는 비소유 포인터를 보유하는 대신 target_user 및 subquery 자식을 직접 소유합니다. #111725 (groeneai).
  • join_any_take_last_row = 1인 상태에서 query_plan_join_swap_table이 ANY JOIN을 스왑하면 잘못된 결과가 반환되던 문제를 수정했습니다. 이제 ClickHouse는 원래의 조인 측 순서를 유지하므로 ANY JOIN이 계속 마지막으로 매칭된 행을 반환합니다. #112458 (vdimir).
  • 서브쿼리 내부에서 getClientHTTPHeader를 사용할 때 발생하던 Context has expired 예외를 수정했습니다. #112533 (alexey-milovidov).
  • ON 절에 혼합 조건, 즉 ON (t1.key = t2.key) AND (t1.a * 10 < t2.a)와 같이 양측에 걸친 비등가 잔여 조건이 포함된 JOIN이 잘못된 결과를 반환하던 문제를 수정했습니다. 이러한 조건은 해시 계열 알고리즘만 평가할 수 있지만, full_sorting_merge, partial_merge 및 직접 키-값 조인이 해당 조인을 실행할 수 있다고 응답한 뒤 잔여 조건을 경고 없이 무시하여 불필요한 행까지 반환했습니다. 이제 이들 알고리즘은 실행을 거부하며, 대신 해시 알고리즘이 사용됩니다. #112831 (groeneai).
  • WHERE가 rand와 같은 비결정적 표현식으로 두 테이블의 컬럼을 비교하는 쉼표 조인 또는 CROSS 조인에서 잘못된 결과가 반환되던 문제를 수정했습니다. 조인을 INNER 조인으로 재작성하는 과정에서 해당 표현식이 조인 키로 옮겨졌고, 조인 키에서는 양쪽의 행마다 표현식이 다시 평가됩니다. 이 때문에 쿼리가 자신의 WHERE 절과 모순되는 행을 반환할 수 있었습니다. #112938 (groeneai).
  • 인식되지 않는 문자가 길게 이어지는 PromQL 쿼리(예: NUL 바이트로 채워진 FixedString 값)를 파싱할 때 처리 시간이 2차적으로 증가하던 문제를 수정했습니다. 이 파싱은 쿼리 분석 단계에서 수행되므로, 메가바이트 크기의 잘못된 입력을 파싱하면 스레드가 수십 분 동안 점유되었고 취소할 수도 없었습니다. 이제 파서는 첫 번째 오류에서 바로 중단됩니다. #112944 (alexey-milovidov).
  • 상수가 아닌 컬럼을 상수 -1로 나누는 intDiv가 부호 있는 정수의 최솟값에 대한 나눗셈(예: intDiv(-9223372036854775808, -1))에서 다른 실행 경로처럼 ILLEGAL_DIVISION 예외를 발생시키지 않고 오류 없이 오버플로(wrap)되던 문제를 수정했습니다. 순서 기반 읽기(read-in-order) 최적화는 음수 상수로 나누는 intDiv를 단조 함수로 올바르게 취급하는데, 오버플로된 값이 이에 따른 정렬 순서를 깨뜨리기 때문에 ORDER BY/DISTINCT 결과가 잘못될 수도 있었습니다. #113048 (alexey-milovidov).
  • enable_analyzer = 0 설정에서 WHERE가 서브쿼리 내부의 untuple로 생성된 컬럼을 참조하면 UNKNOWN_IDENTIFIER가 발생하던 문제를 수정했습니다(예: SELECT t.keys FROM (SELECT untuple(arrayJoin(m)) AS t FROM ...) WHERE t.values > 0). enable_optimize_predicate_expression 재작성 과정에서 이러한 프레디케이트가 서브쿼리 안의 HAVING으로 푸시되었는데, 그 위치에서는 해당 이름이 아직 존재하지 않았습니다. #113760 (groeneai).
  • 오른쪽에 합계(totals)가 포함된 경우 join_algorithm = 'partial_merge'를 사용하는 JOIN에서 잘못된 결과가 반환되던 문제를 수정했습니다. 오른쪽 입력이 머지되지 않은 상태로 남을 수 있어, LEFT 조인은 실제로 일치하는 값 대신 기본값을 채웠고 INNER/RIGHT 조인은 행을 전혀 반환하지 않았습니다. 또한 RIGHT/FULL의 비조인 경로에서는 같은 상태로 인해 널 포인터가 역참조되어 서버가 비정상 종료되었습니다. #113936 (groeneai).
  • 전체 입력을 읽어야 하는 LIMIT가 포함된 SELECT DISTINCT에서 잘못된 결과가 반환되던 문제를 수정했습니다. LIMIT n WITH TIES는 동점 행을 누락했고, exact_rows_before_limit = 1은 실제보다 작은 rows_before_limit_at_least 값을 보고했으며, GROUP BY ... WITH TOTALS는 스트림의 앞부분만으로 합계 행을 계산했습니다. #114025 (groeneai).
  • PREWHERE에서 FINAL이 머지에 필요로 하는 컬럼(ver, is_deleted, sign)을 사용하면서 해당 컬럼은 선택하지 않는 SELECT ... FINAL 쿼리에서 LOGICAL_ERROR(“Unexpected number of kept output positions after removing unused columns from ReadFromMergeTree”)가 발생하던 문제를 수정했습니다. #114746 (groeneai).
  • 비동기 INSERT 플러시, 구체화된 뷰(Materialized View) 처리, EXPLAIN ANALYZE에서 이미 만료된 쿼리 추적 상태에 접근할 수 있던 수명(lifetime) 관련 문제를 수정했습니다. #114940 (azat).
  • 인터벌 사이의 구분 쉼표를 생략하면 CREATE QUOTA와 ALTER QUOTA가 마지막 FOR INTERVAL 블록을 제외한 나머지를 모두 경고 없이 버리던 문제를 수정했습니다. 이 경우 SQL 문은 성공했지만 앞선 제한은 하나도 적용되지 않았습니다. 이제 2020년 이전과 마찬가지로 인터벌이 다시 누적됩니다. #115320 (groeneai).
  • randConstant 호출에 서로 다른 별칭이 지정되면 하나의 쿼리에서 서로 다른 두 값을 반환하던 문제를 수정했습니다. 문서상 randConstant는 쿼리 전체에서 하나의 값을 유지하며 SELECT randConstant() = randConstant()도 이미 1을 반환했지만, SELECT randConstant() AS a, randConstant() AS b처럼 별칭을 붙이면 서로 무관한 두 값이 생성되었습니다. #115384 (alexey-milovidov).
  • 손상된 MsgPack 또는 ProtobufList 파일에서 SELECT count()가 끝나지 않거나 실제와 다른 행 수를 반환하던 문제를 수정했습니다. optimize_count_from_files 고속 경로(fast path)는 읽기 위치가 실제로 진행되는지 확인하지 않고 행을 셌기 때문에, 2바이트짜리 ProtobufList 파일에서 수십억 개의 행이 생성되어 쿼리가 끝나지 않았습니다. 이제 이러한 입력은 일반 읽기 경로와 동일한 오류를 반환하며 거부됩니다. #115884 (groeneai).
  • system.distribution_queue의 broken_data_files와 BrokenDistributedFilesToInsert 메트릭이 항상 0으로 보고되던 문제를 수정했습니다. 서버 시작 시 비동기 삽입 큐를 스캔할 때 DistributedAsyncInsertDirectoryQueue::initializeFilesFromDisk가 손상된 바이트 수는 집계했지만 손상된 파일 카운터는 증가시키지 않았습니다. #92124 (squalfof).

기타 버그 수정

  • 내부 쿼리의 일부로 실행되는 보조 쿼리가 이제 내부 쿼리로 기록됩니다. #108506 (mstetsyuk).
  • PREWHERE 조건이 여러 읽기 단계로 분할될 때, 파트에 없는 DEFAULT 컬럼이 DEFAULT 표현식 대신 해당 유형의 기본값으로 채워지던 문제를 수정했습니다. #111795 (yariks5s).
  • normalized_query_hash를 키로 하는 쿼터가 이제 모든 리소스(read_rows, read_bytes, result_rows, result_bytes, execution_time, written_bytes, errors)를 사용자별 단일 공유 버킷에 합산하지 않고, 쿼리 수 카운터와 마찬가지로 쿼리 패턴별로 집계합니다. #107681 (alexey-milovidov).
  • MySQL connect_timeout 및 읽기/쓰기 타임아웃이 적용되지 않던 문제를 수정했습니다. 샘플링 쿼리 프로파일러의 주기적 시그널이 MySQL 클라이언트의 내부 폴링 기한을 계속 재설정했기 때문에, connect_timeout = 1로 설정하더라도 응답하지 않는 MySQL 서버에 연결을 시도하면 2분 이상 멈춰 있을 수 있었습니다. #109592 (tiandiwonder).
  • 쿼리 프로파일러가 활성화된 상태에서 스트리밍 삽입의 블록 대기 타임아웃(input_format_max_block_wait_ms)이 만료되지 않을 수 있던 문제를 수정했습니다. 프로파일러 시그널이 발생할 때마다 파일 디스크립터 폴링이 전체 타임아웃으로 다시 시작되었기 때문에, 입력 소스가 멈추면 대기 한도에 도달해도 부분 블록이 플러시되지 않고 무기한 지연될 수 있었습니다. #109602 (tiandiwonder).
  • Experimental 설정 make_distributed_plan = 1을 사용하는 쿼리에서 distributed_plan_default_reader_bucket_count 또는 distributed_plan_default_shuffle_join_bucket_count에 매우 큰 값을 지정하면 발생하던 LOGICAL_ERROR(std::length_error)를 수정했습니다. 이제 이러한 값은 INVALID_SETTING_VALUE 오류와 함께 거부됩니다. #109770 (groeneai).
  • distinct_overflow_mode = 'break' 동작을 수정했습니다. 이제 문서에 명시된 대로 DISTINCT가 한도까지 누적된 부분 결과를 반환하고 소스 읽기를 중단합니다. 이전에는 max_rows_in_distinct / max_bytes_in_distinct를 초과한 청크가 버려졌고(결과가 잘리거나 비어 있음), 쿼리는 입력이 끝날 때까지 계속 읽으면서 해시 세트에 삽입했기 때문에 MEMORY_LIMIT_EXCEEDED가 발생할 수 있었습니다. #110075 (skuznetsov-clickhouse).
  • optimize_aggregation_in_order가 쿼리 취소를 무시하던 문제를 수정했습니다. 이제 AggregatingInOrderTransform이 청크를 집계하는 도중에도 취소 여부를 확인하므로, KILL QUERY 또는 max_execution_time(기본값인 timeout_overflow_mode = 'throw' 기준)으로 중지된 쿼리가 청크 전체를 끝까지 처리하지 않고 즉시 중단됩니다. #110104 (groeneai).
  • mysql/postgresql/sqlite 계열 PostgreSQL 소스의 값을 파싱할 수 없는 유형으로 선언된 컬럼에 읽어 들일 때(예: text 컬럼을 Int32로 선언한 경우) 발생하던 서버 중단(디버그 및 새니타이저 빌드)을 수정했습니다. 이제 이러한 유형 불일치는 서버를 중단시키지 않고 쿼리 오류로 보고됩니다. #110264 (groeneai).
  • 특정 PRQL 쿼리(SET dialect = 'prql')를 파싱할 때 발생하던 서버 중단을 수정했습니다. 그동안 prqlc 컴파일러 내부에서 발생한 패닉이 쿼리 오류로 보고되지 않고 프로세스를 중단시켰습니다. #110316 (groeneai).
  • 행 정책(row policy)과 additional_table_filters가 쿼리에서 따로 선택하지 않은 동일한 컬럼을 참조할 때 발생하던 NOT_FOUND_COLUMN_IN_BLOCK 오류를 수정했습니다. #111099 (groeneai).
  • 극단적인 매개변수를 사용할 때 randChiSquared, randStudentT, randFisherF, randBinomial이 멈추는 문제를 수정했습니다. 이 경우 max_execution_time이나 KILL QUERY로도 쿼리를 중단할 수 없었습니다. 이제 max_rand_distribution_parameter 또는 max_rand_distribution_trials가 0으로 설정되어 있어도 이러한 매개변수는 거부되며, randBinomial에서는 max_rand_distribution_trials를 기본값인 10^9보다 높게 설정할 수 없습니다. #111909 (alexey-milovidov).
  • 문서에 명시된 기본값 0이 무한 타임아웃을 의미하도록 connection_pool_max_wait_ms를 수정했습니다. 이전에는 연결 풀이 가득 찬 상태에서 쿼리가 쉴 새 없이 재시도하면서 CPU를 소모하고, 반복할 때마다 No free connections in pool. Waiting 0 ms.를 로그에 기록했습니다. 이제는 연결이 풀에 반환될 때까지 대기합니다. #112380 (groeneai).
  • replaceOne, replaceAll, replaceRegexpOne, replaceRegexpAll이 max_execution_time과 KILL QUERY를 무시하는 문제를 수정했습니다. 이제 단일 호출도 작업 도중 취소 여부를 확인하므로, 큰 값이나 많은 행에 대한 장기 실행 대체 작업이 끝날 때까지 서버 스레드를 점유하지 않고 중단됩니다. 이러한 호출은 반환할 부분 결과가 없으므로, timeout_overflow_mode = 'break'에서는 기한 초과를 오류로 발생시킵니다. 상수 폴딩(constant folding)된 경우에는 항상 오류가 발생하며, 파이프라인에서는 실행기의 블록 간 검사보다 이 체크포인트에 먼저 도달할 때마다 오류가 발생합니다. 블록 간 검사에서는 기존과 같이 쿼리가 오류 없이 중단됩니다. #112483 (groeneai).
  • countSubstrings, countSubstringsCaseInsensitive, countSubstringsCaseInsensitiveUTF8이 KILL QUERY와 max_execution_time을 무시하는 문제를 수정했습니다. 행이나 일치 항목이 많으면 쿼리가 취소된 후에도 호출이 수 분간 계속 실행될 수 있었습니다. #113369 (groeneai).
  • initiator에서 쿼리가 매우 빠르게 완료되면 쿼리가 (receive_timeout초 동안) 멈출 수 있는 문제를 수정했습니다. #113551 (nickitat).
  • countMatches와 countMatchesCaseInsensitive가 하나의 큰 값에서 일치 항목을 세는 동안 max_execution_time과 KILL QUERY를 무시하여, 취소된 쿼리가 수 분간 계속 실행되던 문제를 수정했습니다. 인수가 상수이면 호출이 쿼리 분석 단계에서 이루어지므로 이를 취소할 파이프라인이 존재하지 않습니다. #113886 (groeneai).
  • 쿼리가 max_execution_time에 도달하기 최대 1ms 전에 취소되어 Timeout exceeded: elapsed 999.672 ms, maximum: 1000 ms라는 모순된 오류로 실패할 수 있던 문제를 수정했습니다. #114559 (alexey-milovidov).
  • 경계 상자가 무한한 상수 폴리곤(예: 좌표가 +-DBL_MAX에 도달하는 경우)을 사용할 때 pointInPolygon에서 범위를 벗어난 읽기가 발생하던 문제를 수정했습니다. 이제 이러한 폴리곤은 BAD_ARGUMENTS로 거부되며, 빈 링이 있는 폴리곤은 내부가 없는 것으로 처리됩니다. 이전에는 쿼리가 잘못된 결과를 반환하거나, 하드닝 또는 새니타이저가 활성화된 빌드에서 서버가 비정상 종료될 수 있었습니다. #115035 (groeneai).
  • STREAM BOUNDED 쿼리가 시작 전에 커밋된 행보다 적은 수의 행(대개 0개)을 반환할 수 있던 경쟁 상태를 수정했습니다. #115543 (alexey-milovidov).
  • make_distributed_plan = 1 설정에서 윈도우 쿼리의 정렬 컬럼이 해당 컬럼을 참조하지 않는 Expression 단계를 거칠 때, 쿼리 계획 최적화 중 Unknown identifier 오류가 발생하던 문제를 수정했습니다. #115890 (groeneai).
  • h3kRing, h3HexRing, h3Line, h3ToChildren이 행 블록을 확장하는 동안 max_execution_time 및 KILL QUERY를 무시하던 문제를 수정했습니다. #115893 (alexey-milovidov).
  • PREWHERE의 조건절(conjunct)들이 공통 중간 표현식을 공유할 때 네이티브 Parquet V3 리더에서 NOT_FOUND_COLUMN_IN_BLOCK이 발생하던 문제(이전 회귀로 인해 발생)를 수정했습니다. #107059 (groeneai).
  • output_format_parquet_parallel_encoding이 활성화되어 있고(기본값) max_threads가 1보다 클 때 Parquet 쓰기가 멈추던 문제를 수정했습니다. 인코더가 추가 스레드 예약에 실패하면 활성 스레드 카운터에 언더플로가 발생하여, 쓰기가 완료되거나 오류를 보고하지 못하고 영구적으로 멈출 수 있었습니다. #112959 (groeneai).
  • Thrift 메타데이터에 선언된 컨테이너 또는 문자열 길이가 메타데이터 자체보다 큰 Parquet 파일을 읽을 때 메모리가 무제한으로 할당되던 문제를 수정했습니다. 이제 이러한 길이는 메모리를 할당하지 않고 거부합니다. #113212 (groeneai).
  • 필터 평가에만 필요한 컬럼이 출력 슬롯이 이미 삭제된 후에 디코딩되도록 예약된 경우, Parquet v3 리더에서 std::out_of_range 예외(Logical error: 'std::exception. Code: 1001, type: std::out_of_range', 디버그 및 새니타이저 빌드에서는 서버가 중단되기도 함)가 발생하던 문제를 수정했습니다. #113956 (groeneai).
  • 프로필 이벤트와 메모리 트래커에서 발생하던 데이터 경쟁(data race)을 수정했습니다. #112466 (mstetsyuk).
  • trace_profile_events_list 설정으로 특정 프로필 이벤트의 스택 트레이스를 system.trace_log에 기록할 때 프로필 이벤트에서 이론적으로 발생할 수 있는 데이터 경쟁을 수정했습니다. #113553 (mstetsyuk).
  • 나눗셈에서 부동 소수점 예외(0으로 나누기 또는 INT_MIN / -1)가 발생할 때, 부호 있는/부호 없는 인수가 혼합된 경우를 포함하여 intDivOrNull, moduloOrNull, positiveModuloOrNull이 NULL 대신 0을 반환하고, intDivOrNull 및 intDivOrZero가 NULL / 0을 반환하지 않고 예외를 발생시키던 문제를 수정했습니다. #101976 (yariks5s).
  • Array 및 Map 값을 NULL과 비교할 때 IS DISTINCT FROM이 잘못 동작하던 문제를 수정했습니다. #103162 (ylw510).
  • groupConcat(',', 2)(x, '/')처럼 매개변수 방식과 2-인수 방식을 혼용할 때 groupConcat이 잘못 동작하던 문제를 수정했습니다. 행 제한 매개변수가 별도의 알림 없이 무시되어 요청한 개수 대신 모든 행이 반환되었습니다. 이제 두 번째 인수의 구분자가 매개변수를 올바르게 재정의합니다. #104882 (yariks5s).
  • 작은 인터벌 단위에서 큰 인터벌 단위로 CAST할 때 발생하던 버그를 수정했습니다. #105058 (yariks5s).
  • 읽기 순서(read-in-order) 파이프라인(optimize_read_in_order = 1 및 read_in_order_use_virtual_row_per_block = 1)으로 실행되는 LIMIT ... WITH TIES 쿼리에서 논리 오류(Assertion 'row < chunk.getNumRows()' failed)가 발생하던 문제를 수정했습니다. #105102 (groeneai).
  • enable_sharding_aggregator = 1을 UNION ALL과 함께 사용하고 max_streams_for_union_step이 파이프라인 폭보다 작은 쿼리에서 발생하던 Logical error: 'Pipeline stuck'을 수정했습니다. 이제 BufferedShardByHashTransform은 입력이 소진되는 즉시 비어 있는 큐의 출력 포트를 종료하며, 요청된 빈 포트에 내보낼 데이터가 없으면 형제 큐가 백프레셔 한도에 도달했더라도 계속 입력을 가져옵니다. #106251 (groeneai).
  • plain 객체 스토리지 디스크(예: s3_plain)에서 removeDirectory가 비어 있지 않은 디렉터리 내부의 모든 파일을 재귀 삭제처럼 제거하던 문제를 수정했습니다. 이제 비어 있지 않은 디렉터리를 삭제하면 CANNOT_RMDIR 오류로 실패하며, 재귀 삭제는 내용물을 명시적으로 처리합니다. #106281 (RinChanNOWWW).
  • <lifetime>이 설정된 executable_pool 사용자 정의 함수가 기반 스크립트의 변경 사항을 반영하지 않던 문제를 수정했습니다. 이전에는 SYSTEM RELOAD FUNCTIONS를 실행해야만 수정된 스크립트를 다시 읽었으며, <lifetime>에 따른 주기적 다시 로드에서는 이전 버전이 계속 실행되었습니다. #107087 (groeneai).
  • 워커 스레드가 프로파일러를 시작하는 과정과 서버 종료 과정 사이에서 서버 전역 트레이스 collector에 발생하던 데이터 경합을 수정했습니다. #107307 (groeneai).
  • threadPoolCallbackRunnerUnsafe를 통해 예약된 작업이 실행되기 전에 스레드 풀 큐에서 제거되면서 종료 중에 드물게 서버가 비정상 종료되던 문제(std::future_error, “The associated promise has been destructed prior to the associated state becoming ready”)를 수정했습니다. #107383 (groeneai).
  • 감시 중인 파일이 삭제된 뒤 동일한 inode를 재사용해 다시 생성될 때 발생할 수 있던 FileLog 논리 오류(Last stored last_written_position in meta file ... is bigger than current last_written_pos)를 수정했습니다. #107617 (groeneai).
  • saturate 및 ignore 오버플로우 모드에서 toTime64와 CAST(... AS Time64)가 범위를 벗어난 값을 Time64 범위로 제한하지 않아, 표시는 같지만 비교하면 서로 다른 값이 생성될 수 있던 문제를 수정했습니다. #108028 (alexey-milovidov).
  • 정규식 「전체 매칭」 함수인 extractAll, extractAllGroupsVertical, extractAllGroupsHorizontal, countMatches, splitByRegexp에서 너비가 0인 어서션(\b, ^, $)을 잘못 처리하던 문제를 수정했습니다. 예를 들어 extractAll('new york is the greatest', '\b(\w)')는 이제 모든 글자가 아닌 각 단어의 첫 글자를 올바르게 반환합니다. #108047 (alexey-milovidov).
  • splitByNonAlpha가 아닌 토크나이저를 사용하는 텍스트 인덱스에서 hasToken을 사용하면 잘못된 결과가 반환되던 문제를 수정했습니다. #108066 (rschu1ze).
  • 입력값의 정밀도가 인터벌 단위보다 세밀할 때 toStartOfInterval과 dateTrunc가 해당 값이 속한 인터벌의 시작 대신 반올림된 값을 반환하던 문제를 수정했습니다. 예를 들어 toStartOfInterval(toDateTime64('2023-10-09 10:11:12.000999', 6), INTERVAL 1 millisecond)가 10:11:12.000 대신 10:11:12.001을 반환했습니다. 명시적 기준점(origin)을 지정하는 오버로드에도 같은 문제가 있었습니다. #108186 (yariks5s).
  • replaceRegexpOne과 replaceRegexpAll에서 다른 정규식 함수와 마찬가지로 .가 기본적으로 개행 문자와도 일치하도록 수정했습니다. #108265 (linjiayu1025-collab).
  • 경량 UPDATE/DELETE의 조건이 두 번 평가되던 문제를 수정했습니다. #108323 (ofeliacode).
  • 상수가 아닌 limit 인수를 사용할 때 arrayPartialSort()가 올바르게 동작하지 않던 문제를 수정했습니다. #108327 (vitlibar).
  • 패턴에 NUL(\0) 바이트가 포함된 경우 정규식 함수(match, extract, extractAll, replaceRegexpOne, replaceRegexpAll 등)가 오류 없이 잘못된 결과를 반환하던 문제를 수정했습니다. 이제 NUL은 RE2와 동일하게 일반 리터럴 바이트로 처리됩니다. #108427 (alexey-milovidov).
  • DateTime64(N) 인수에 changeYear/changeMonth/changeDay/changeHour/changeMinute/changeSecond를 적용하면 N 대신 하드코딩된 기본 scale(3)로 결과 컬럼이 생성되던 문제를 수정했습니다. 값은 scale N으로 계산되었지만 컬럼 객체는 scale 3으로 선언되어 타입과 구조적으로 일치하지 않았습니다. #108551 (groeneai).
  • correlated_subqueries_default_join_kind = 'left'로 설정된 상태에서 집합 연산(INTERSECT / UNION ALL / EXCEPT)이 상관 서브쿼리(correlated subquery)를 사용하는 분기를 결합할 때 발생하던 LOGICAL_ERROR(“Trying to extract chunk from ChunkBuffer before all inputs are finished”)를 수정했습니다. #108554 (groeneai).
  • changeYear, changeMonth, changeDay, changeHour, changeMinute, changeSecond의 DateTime64 관련 버그를 수정했습니다. 이제 나노초 정밀도(scale 9) 입력에서 DECIMAL_OVERFLOW가 발생하지 않으며, epoch 이전의 1초 미만 단위 입력에 대해서도 올바른 달력상의 초를 반환합니다. #108681 (takumihara).
  • 매우 큰 정규식(예: 와일드카드가 수십만 개 포함된 LIKE 또는 match 패턴)을 컴파일할 때 서버 로그가 과도하게 출력되고 오류 메시지가 지나치게 커지는 문제를 방지했습니다. 이제 이러한 패턴은 명확한 CANNOT_COMPILE_REGEXP 오류와 함께 실패합니다. #108821 (Algunenano).
  • 소스와 대상의 물리적 타입이 같을 때 reinterpret(x, 'Decimal128(scale)')(및 Decimal32/Decimal64/Decimal256/DateTime64 대상)가 요청한 대상 scale이 아닌 소스 scale을 내부 scale로 갖는 결과 컬럼을 생성하던 문제를 수정했습니다. 값 자체는 올바랐지만 컬럼 객체가 선언된 타입과 구조적으로 일치하지 않았습니다. #108878 (groeneai).
  • 동기화가 어긋났거나 퍼징된 연결에서 범위를 벗어난 프로토콜 패킷 유형을 문자열로 변환할 때(예: “Unexpected packet from server” / “Received … packet” 오류 메시지) 발생하던 정의되지 않은 동작을 수정했습니다. #108885 (groeneai).
  • DateTime64(N)에 대한 changeYear/changeMonth/changeDay/changeHour/changeMinute/changeSecond가 결과 컬럼을 N이 아닌 하드코딩된 기본 scale 3으로 생성하던 문제와, DateTime64에 대한 timeSlots가 선언된 반환 타입에 선택적 Size 인수의 scale을 반영하지 않던 문제를 수정했습니다. 두 경우 모두 물리적 scale이 선언된 타입과 다른 컬럼이 생성되어, 결과를 arrayPushBack/arrayPushFront/arrayConcat에 전달하면 LOGICAL_ERROR(writeSlice expects same column types)가 발생했습니다. 또한 Size에 가장 큰 scale을 지정한 timeSlots는 잘못된 타임스탬프를 반환했습니다. #108994 (groeneai).
  • ProfileEvents 값이 단조 증가하지 않던 문제를 수정했습니다. #109180 (azat).
  • 지수의 크기가 Int32 범위를 넘어 오버플로우되는 SAMPLE 비율(예: SAMPLE 1e-3000000000)이 경고 없이 SAMPLE 1로 처리되던 문제를 수정했습니다. #109197 (Algunenano).
  • toUTCTimestamp/fromUTCTimestamp(및 별칭 to_utc_timestamp/from_utc_timestamp)와 toTime64의 DateTime64 처리 경로에서 발생하던 두 가지 버그를 수정했습니다. 첫째, Int64 경계 근처에서 발생하던 부호 있는 정수 오버플로우를 수정했습니다(이제 Int128로 계산한 후 표현 가능한 범위로 제한합니다). 둘째, 시간대 오프셋 경계 근처의 음수 소수 값에 대해 잘못된 결과가 반환되던 문제를 수정했습니다. 초 단위 분리 시 0 방향으로 절사되어 timezoneOffset()이 다음 초를 검사했고, 이로 인해 DST/오프셋 변경 시점의 반대편 값을 잘못 선택할 수 있었습니다. #109738 (groeneai).
  • row policy 필터 표현식에서 arrayJoin을 사용할 때 발생하던 논리 오류(column->size() == num_rows)를 수정했습니다. 이제 이러한 필터는 허용되지 않습니다. #109753 (Algunenano).
  • 타입 중첩이 내부 깊이 제한을 초과할 때 generateRandomStructure()가 두 데이터 타입이 붙어 있는 잘못된 structure 문자열(예: Decimal32(7)IPv4)을 간헐적으로 생성하여 결과를 파싱할 수 없던 문제를 수정했습니다. #109928 (groeneai).
  • accurateCastOrDefault에서 쿼리 설정이 전달되지 않던 문제와 Dynamic 및 Variant로 인코딩된 원본 NULL 값이 보존되지 않던 문제를 수정했습니다. #109946 (Avogar). #114912 (alexey-milovidov).
  • max_bytes_in_distinct 및 max_bytes_in_set을 수정했습니다. 문자열 키는 제한 검사에 집계되지 않는 arena에 저장되므로, 문자열 키에 대한 DISTINCT / IN이 전체 키 페이로드만큼(키 길이에 비례해 제한 없이) 바이트 제한을 초과하여 메모리를 점유할 수 있었습니다. 이제 문서에 명시된 대로 제한 계산에 arena가 포함됩니다. 따라서 바이트 제한에 근접한 문자열 키를 사용하는 쿼리는 (올바르게) 이전보다 일찍 제한에 걸릴 수 있습니다. #110120 (skuznetsov-clickhouse).
  • 내부 차원의 크기가 0인 Npy 파일을 읽을 때 구체화된 행과 최적화 및 비최적화 count() 결과가 서로 일치하도록 수정했습니다. #110146 (qiuyanjun888).
  • indexHint/ignore/isZeroOrNull 함수에 타입이 Nothing으로 결정되는 인수가 전달될 때(예: indexHint(assumeNotNull(materialize(NULL)))와 같은 표현식 내부) 발생하던 논리 오류(디버그/sanitizer 빌드에서 서버 중단)를 수정했습니다. #110192 (groeneai).
  • 기존 경로를 크기가 다른 내용으로 재작성한 후 plain_rewritable 디스크에서 파일을 읽을 때 발생하던 문제를 수정했습니다. 인메모리 메타데이터에 이전 파일 크기가 그대로 남아 있어 UNEXPECTED_END_OF_FILE 오류와 함께 읽기가 실패할 수 있었습니다. #110304 (thevar1able).
  • 계산된 fetch 개수가 0으로 잘려 ANN 검색 결과가 비는 문제를 방지하기 위해, 이제 1.0 미만의 vector_search_index_fetch_multiplier 값을 거부합니다. #110452 (tamish560).
  • initializeAggregation('sumState', 0::UInt64)와 같이 숫자 캐스트가 포함된 표현식을 사용하는 값을 삽입할 때 간헐적으로 발생하던 Cannot parse string ... as UInt64 ... While executing ValuesBlockInputFormat 오류를 수정했습니다. #110637 (groeneai).
  • readWKT가 선행 공백이 있는 WKT 문자열(예: readWKT(' POINT(1 2)'))을 거부하던 문제를 수정했습니다. 이러한 문자열은 타입별 readWKTPoint/readWKTPolygon/… 리더와 WKT 문법에서는 허용됩니다. #110706 (groeneai).
  • 길이가 0인 인터벌을 가진 쿼터(예: CREATE QUOTA q FOR INTERVAL 0 SECOND MAX queries = 1000)를 소비할 때 발생하던 서버 크래시(정수를 0으로 나누기)를 수정했습니다. 이제 쿼터 생성 시 0 이하의 쿼터 인터벌 기간은 거부됩니다. #110846 (PedroTadim).
  • FIPS 빌드에서 Ed25519 SSH 키(CREATE USER ... IDENTIFIED WITH ssh_key ... TYPE 'ssh-ed25519' 또는 users.xml에 지정된 해당 키)를 사용할 때 발생하던 크래시를 수정했습니다. Ed25519는 FIPS 승인 알고리즘이 아니므로, 이제 이러한 키는 명확한 LIBSSH_ERROR 오류와 함께 거부됩니다. #110891 (thevar1able).
  • QBit에 대한 전치(transposed) 거리 함수(cosineDistanceTransposed, L2DistanceTransposed, dotProductTransposed)는 이제 precision개의 비트 평면으로 잘린 값을 거친 셀의 하한 경계로 재구성(삭제된 비트를 0으로 채움)하지 않고, 범위가 제한된 저정밀도 재구성을 사용합니다. 0으로 채우는 방식은 재구성된 모든 값을 0 쪽으로 편향시켰고 낮은 정밀도에서는 제대로 동작하지 않았습니다. 예를 들어 정밀도 1의 QBit(BFloat16)에서는 부호 비트만 남기 때문에 모든 값이 ±0.0으로 재구성되었고, 거리가 모든 행에서 동일한 상수가 되어 순위 정보를 전혀 제공하지 못했습니다. 이제 재구성 방식은 어떤 비트가 삭제되는지에 따라 달라집니다. 원시 Int8 코드는 셀 중심으로 재구성되며(...TransposedQuantized 경로에서 이미 사용하던 Lloyd-Max 재구성과 동일), 정밀도 1의 부동소수점 값은 올바른 부호 양자화로 처리됩니다. 지수 전체를 유지하고 가수 비트만 삭제하는 부동소수점 값은 해당 binade 내에서 범위가 제한된 중간점으로 재구성됩니다(실제 0 또는 ±0.0은 정확히 0으로 유지되고, 비유한(non-finite) 셀은 별도로 분리되어 ±inf는 정확히 무한대로 유지됩니다. 모호한 NaN 셀에 대해서는 아래 참고 사항을 참조하십시오). 지수 비트가 아직 잘리는 단계에서는 범위가 제한된 하한 경계를 유지하므로, precision을 낮추면 값의 크기가 수십 배로 부풀려지는 일 없이 정확도를 낮추는 대신 속도를 높일 수 있습니다. 전체 정밀도 결과는 변경되지 않습니다. #110911 (alexey-milovidov).
  • 타입 트리에 선언된 컬럼 수가 스트라이프 푸터의 컬럼 인코딩 수보다 많은 손상된 ORC 파일에 대해 스키마 추론을 수행할 때, 네이티브 ORC 리더에서 발생하던 범위 초과 읽기를 수정했습니다. 이제 debug/새니타이저 빌드에서 서버가 중단되지 않고 CANNOT_EXTRACT_TABLE_STRUCTURE 오류와 함께 거부됩니다. #110967 (groeneai).
  • 이제 각 SSH 키가 max_authentication_methods_per_user 한도에 개별적으로 계산되므로, 구문과 관계없이 한도가 일관되게 적용됩니다. 이전에는 단일 ssh_key 메서드에 포함된 여러 키가 하나로 계산되었습니다. #111181 (TheMC47).
  • 이제 Iceberg REST 카탈로그는 자격 증명이 만료된 경우 별다른 안내 없이 UNKNOWN_TABLE을 보고하는 대신 근본 원인이 되는 오류와 함께 보고합니다. #111379 (alesapin).
  • POINT M EMPTY와 같이 차원 태그가 지정된 빈 포인트에 대해 readWKTPoint/readWKT가 초기화되지 않은 좌표(스칼라) 또는 이전 행의 좌표(벡터화)를 반환하던 문제를 수정했습니다. 이제 이러한 입력은 POINT EMPTY와 마찬가지로 CANNOT_PARSE_TEXT 오류와 함께 거부됩니다. #111517 (groeneai).
  • 이제 minmax 통계를 생성할 때 예외를 발생시키는 대신 경고를 출력합니다. #111785 (hanfei1991).
  • 시행 횟수와 관계없이 퇴화 확률 0 및 1에서도 randBinomial을 사용할 수 있도록 했습니다. #112021 (alexey-milovidov).
  • system.s3_queue_settings가 bucketing_mode, partitioning_mode, partition_regex, partition_component에 대해 잘못된 값을 보고하던 문제를 수정했습니다. #112300 (bharatnc).
  • PromQL 쿼리에서 발생한 오류의 위치를 올바르게 보고하도록 했습니다. #112494 (fallintoplace).
  • 이제 SYSTEM DISABLE FAILPOINT는 존재하지 않는 fail point 이름을 거부하며, SYSTEM ENABLE FAILPOINT와 마찬가지로 BAD_ARGUMENTS를 발생시킵니다. 이전에는 이름을 잘못 입력해도 성공으로 보고되어 의도한 fail point가 활성화된 상태로 남았으며, 아무것도 비활성화되지 않았다는 사실도 알 수 없었습니다. #112680 (groeneai).
  • 컬럼이 삭제된 후 다시 추가된 Nested 원소 서브컬럼을 잘못된 타입으로 읽던 문제를 수정했습니다. 이러한 서브컬럼을 해당 상위 컬럼과 함께 선택하면, 블록에는 여전히 원소 타입이 선언된 상태에서 서브컬럼 자리에 원소 전체가 반환되어 릴리스 빌드에서는 임의의 값이, 디버그 및 새니타이저 빌드에서는 논리 오류가 발생했습니다. #112769 (groeneai).
  • 단위가 반복되거나 큰 단위에서 작은 단위 순으로 정렬되지 않은 PromQL 기간 값을 거부하도록 했습니다. #112954 (fallintoplace).
  • 대체 문자열이 매치에 참여하지 않은 캡처 그룹을 참조할 때 replaceRegexpOne/replaceRegexpAll에서 발생하던 정의되지 않은 동작(memcpy에 null 포인터 전달)을 수정했습니다. 예: replaceRegexpAll('abc', '(a)|(b)', '\\2'). #113012 (alexey-milovidov).
  • ClickHouse 26.3에서 unicode_word 토크나이저로 생성한 텍스트 인덱스를 이후 버전에서 로드할 수 없던 호환성 문제를 수정했습니다 #113061 (rschu1ze).
  • PromQL 문자열 이스케이프에서 유효하지 않은 유니코드 서로게이트 코드 포인트를 거부하도록 했습니다. #113203 (fallintoplace).
  • PromQL 문자열에서 유효하지 않은 교차 구분자 이스케이프를 거부하도록 했습니다. #113587 (fallintoplace).
  • 첫 번째 인수가 윈도우 프레임 내에서 상수일 때 해당 프레임에 대한 theilsU가 0 대신 임의의 값을 반환하던 문제를 수정했습니다. #113691 (alexey-milovidov).
  • Native protocol로 수신된 일부 잘못된 형식의 Replicated 직렬화 컬럼에 대해 보고되는 오류 코드를 수정했습니다. 이제 이러한 컬럼은 LOGICAL_ERROR(디버그 및 새니타이저 빌드에서 서버를 중단시킴) 대신 INCORRECT_DATA로 거부됩니다. #114186 (Avogar).
  • 더 낮은 스케일의 Decimal64을 재조정하는 과정에서 Int64 오버플로우가 발생하면 잘못된(종종 부호가 뒤바뀐) Time64 리터럴과 IN 목록 상수가 생성되던 문제를 수정했습니다. 이제 이러한 변환은 DateTime64 분기 및 명시적 CAST와 마찬가지로 DECIMAL_OVERFLOW를 보고합니다. #114546 (groeneai).
  • PromQL 셀렉터에서 따옴표로 묶인 메트릭 이름과 레이블 이름을 지원합니다. #114551 (fallintoplace).
  • attach 스레드를 통해 실행된 시작 시도가 실패한 후 ReplicatedMergeTree 테이블이 무기한 읽기 전용 상태로 남아 있던 문제를 수정했습니다. 이제 재시작 재시도가 올바르게 예약되므로 자동 복구와 세션 검사가 다시 정상적으로 동작합니다. #114802 (azat).
  • timeSeriesRange와 timeSeriesFromGrid가 시작/종료 타임스탬프를 부호 없는 값으로 읽는 바람에 1970년 이전 타임스탬프에 대해 잘못된 DECIMAL_OVERFLOW를 발생시키던 문제를 수정했습니다. 또한 DateTime/UInt32 타임스탬프에서는 step이 경고 없이 하위 32비트로 잘렸습니다. 이제 모든 계산은 Int64로 수행됩니다. #114815 (vitlibar).
  • 쿼리가 MEMORY_LIMIT_EXCEEDED로 실패한 후 비동기 삽입에서 발생할 수 있던 예외를 수정했으며, 서버 종료 시 큐에 남아 있는 삽입이 플러시되도록 async_insert_queue_flush_on_shutdown을 수정했습니다. #114839 (azat).
  • sequenceMatch, sequenceCount 또는 sequenceMatchEvents 패턴에 이벤트 번호 0이 포함된 경우(예: sequenceMatch('(?0)')) out_of_range 예외가 내부 Code: 1001 오류로 발생하던 문제를 수정했습니다. 이제 이러한 패턴은 BAD_ARGUMENTS로 거부됩니다. 또한 sequenceMatch('(?1)(?t>+)(?2)')처럼 부호만 있는 시간 조건은 경고 없이 (?t>0)으로 처리되었으나, 이제 SYNTAX_ERROR로 거부됩니다. #115056 (groeneai).
  • 좌표가 Float64가 아닐 때 geoToH3의 오류 메시지에 잘못된 인수 위치와 잘못된 유형이 표시되던 문제를 수정했습니다. 기본값인 geotoh3_argument_order = 'lat_lon'에서는 오류 메시지가 다른 인수를 가리키고 그 인수의 유형을 출력했습니다. #115503 (groeneai).
  • text, tokenbf_v1 및 ngrambf_v1 인덱스에서 잘못된 백슬래시 이스케이프 문자를 수정했습니다. #115634 (ahmadov).
  • TZ 환경 변수가 비어 있으면 서버가 시작되지 않던 문제를 수정했습니다. #68921 (ardenwick).
마지막 수정일 2026년 10월 14일