Обратно несовместимые изменения
Изменения в запросах, функциях и синтаксисе
- Для представлений, тело которых представляет собой простой
SELECTнад одной таблицейDistributed, весь внешний запрос теперь передаётся на сегменты (новая настройкаoptimize_trivial_view_pushdown_to_distributed, включена по умолчанию). Это изменяет наблюдаемое поведение таких представлений:FINALиSAMPLE, указанные при обращении к представлению, теперь передаются в локальную таблицу сегмента, а не игнорируются, аextremesне возвращается в кластерах из одного сегмента. Чтобы вернуть прежнее поведение, установитеoptimize_trivial_view_pushdown_to_distributed = 0. #101791 (simonmichal). - Патч-части облегчённых
UPDATEтеперь хранятся на диске в новом формате v2: они отсортированы по (sorting_key..., _block_number, _block_offset) и применяются с помощью нового алгоритма слияния. Пиковое потребление памяти ограничено размером наибольшей последовательности строк с одинаковым ключом сортировки, а не всего патча, а обновления, пересекающие границы слияний, больше не переключаются на применение через 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_deduplication_window_seconds(по умолчанию один час; окна по умолчанию хранят единые хеши всех вставок за этот период, чего считается достаточно для цикла повторных попыток вставки). Для нереплицируемых таблиц с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). - Модели наивного байесовского классификатора (используемые
naiveBayesClassifier) теперь настраиваются как словарь с макетомNAIVE_BAYES, который строится при загрузке из таблицы предварительно агрегированных частот n-грамм по классам. Прежняя конфигурация на стороне сервера (конфигурационный XML-файл со ссылками на сериализованные файлы моделей.bin) больше не поддерживается — существующие модели необходимо пересоздать в виде словарей. Наряду сnaiveBayesClassifierдобавлены три новые функции:naiveBayesClassifierWithProbвозвращает предсказанный класс вместе с его вероятностью,naiveBayesClassifierWithAllProbsвозвращает все классы с их вероятностями, аnaiveBayesNgramsразбивает текст на n-граммы так же, как это делает словарь, что позволяет формировать обучающие данные из необработанного размеченного текста. Кроме того, применён ряд оптимизаций производительности: на языковой модели триграмм кодовых точек размером 9,7 МиБ потребление памяти снизилось примерно в 49 раз (с 1,84 ГиБ до 38 МиБ), а загрузка и классификация ускорились примерно в 11 раз. #108773 (nihalzp). - Значение по умолчанию настройки
max_insert_threadsизменено с1(без параллелизма) на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 обычный
Tupleтеперь в любой позиции принимает по одному полю на каждый элемент, поэтому\Nв поле элемента верхнего уровня относится именно к этому элементу, и к нему применяетсяinput_format_null_as_default. Ранее начальный\Nтрактовался как NULL для всего столбца, из-за чего строка заменялась значением столбца по умолчанию, а оставшиеся ячейки элементов затем не удавалось разобрать. Это изменение нарушает обратную совместимость для строк, в которых для всего обычногоTupleуказано одно поле: теперь в такой строке не хватает оставшихся элементов, и она отклоняется; а дляTupleиз одного элемента, где число полей в обоих случаях одинаково, вместоDEFAULTстолбца молча подставляется значение элемента по умолчанию. Чтобы снова читать такое поле как весь столбец, установитеinput_format_csv_deserialize_separate_columns_into_tuple = 0. #109744 (groeneai). - В
CREATE USERиALTER USERдобавлена конструкцияVALID FOR <interval>как сокращённая формаVALID UNTIL. Срок действия вычисляется в момент выполнения запроса как текущее время плюс заданный интервал и сохраняется в формеVALID UNTIL. Столбецvalid_untilтаблицыsystem.usersтеперь имеет типArray(DateTime64(0))вместоArray(DateTime), чтобы точно представлять сроки после 2106 года; инструменты, читающие этот столбец, должны поддерживать новый тип. #110171 (alexey-milovidov). EXPLAIN SYNTAXтеперь возвращает переформатированный запрос в виде одной записи типаString(со встроенными переводами строк) вместо отдельной записи для каждой строки, поэтому результат представляет собой одну строку, пригодную для непосредственного использования (например,SELECT count() FROM (EXPLAIN SYNTAX ...)возвращает1). Это поведение управляется новой опциейsingle_record, которая по умолчанию равна1; чтобы вернуть прежний вывод по одной записи на строку, установитеsingle_record = 0. Другие видыEXPLAIN(PLAN/PIPELINE/AST) по-прежнему выводят дерево построчно. #110479 (alexey-milovidov).- Функция
hasColumnInTableбольше не принимает необязательные аргументыhostname,usernameиpasswordдля проверки наличия столбца на произвольном удалённом сервере; осталась только формаhasColumnInTable(database, table, column). Удалённый режим убран из соображений безопасности: он позволял любому пользователю инициировать исходящие подключения к произвольным хостам, приводил к утечке учётных данных в журналы запросов и не требовал никакой привилегии. #110881 (alexey-milovidov). - Движки баз данных
PostgreSQLиMaterializedPostgreSQLтеперь учитывают параметр конфигурации сервераremote_url_allow_hosts— так же, как это уже делают табличный движокPostgreSQL, табличная функцияpostgresqlи словари, созданные через DDL. Ограничение применяется приCREATE DATABASEи при выполнении пользователемATTACH DATABASE: если на сервере настроенremote_url_allow_hosts, попытка создать или подключить базу данныхPostgreSQLилиMaterializedPostgreSQL, указывающую на хост вне белого списка, теперь завершается ошибкойUNACCEPTABLE_URL. Уже существующие базы данных по-прежнему загружаются при запуске сервера, поэтому после обновления сервер гарантированно сможет запуститься. #111135 (alexey-milovidov). - Удалены основанные на библиотеке Apache Arrow считыватель и модуль записи для форматов
ArrowиArrowStream. Нативная реализация ClickHouse, используемая по умолчанию начиная с версии 26.7, теперь единственная. Настройкиinput_format_arrow_use_native_readerиoutput_format_arrow_use_native_writerустарели: они по-прежнему принимаются, но ни на что не влияют, поэтому запрос, в котором им присваивалось значение0для принудительного использования реализации Apache Arrow, теперь использует нативную реализацию. #111996 (alexey-milovidov). - Учётные данные TLS для источника MySQL (
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).- Оконные
PARTITION BYиORDER BYпо столбцу типаAggregateFunctionтеперь отклоняются с ошибкойILLEGAL_COLUMN— так же, как уже отклонялсяORDER BYверхнего уровня по такому столбцу. Ранее такой запрос принимался как минимум одним анализатором, а оконный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 ON CLUSTERбез привилегииSYSTEM SYNC FILESYSTEM CACHE. #114042 (groeneai). - Движок таблицы
NATSтеперь принимает учётные данные непосредственно в новой настройкеnats_credentials(в том же формате, что и содержимое файла.creds) и больше не принимаетnats_credential_fileиз SQL: этот путь указывает на файл в файловой системе сервера, который сервер открывает со своими собственными привилегиями, поэтому его можно задать только в именованной коллекции, определённой в файле конфигурации сервера, либо какnats.credential_fileнепосредственно в конфигурации сервера. Запрос может заменить такой заданный в конфигурации путь встроеннымиnats_credentials, если только администратор не зафиксировал его с помощью<nats_credential_file overridable="false">. Таблицы, созданные до введения этого ограничения, продолжат работать после обновления. #114644 (alexey-milovidov).
Изменения типов данных и форматов
- Формат архивов резервных копий
zip/zipxтеперь отклоняется для резервных копий, хранящихся в объектном хранилище, — как для прямых пунктов назначенияS3(...)/AzureBlobStorage(...), так и для пунктов назначенияDisk(...), размещённых в S3 или Azure, — при выполнении какBACKUP, так иRESTORE. Для чтения центрального каталога zip-архива требуется произвольный доступ (seek), который в объектном хранилище выполняется очень медленно. Вместо него используйте формат на основе tar, напримерtar.gz. #101770 (Onyx2406). - Поддерживаемый диапазон
DateTime64расширен с[1900-01-01, 2299-12-31]до[0000-01-01, 9999-12-31]. Значения за пределами прежнего диапазона теперь вычисляются корректно (с помощью cctz), а не усекаются до граничного значения. При точности 8 или 9 диапазон остаётся более узким, поскольку такты хранятся в видеInt64(при наносекундной точности максимальным значением по-прежнему остаётся2262-04-11). Обратная совместимость: если ранее вы использовали значения даты и времени вне диапазона, но полагались на весьма специфические правила насыщения внутри старого диапазона, учтите, что теперь результаты будут более корректными. #107907 (alexey-milovidov). - Число JSON без кавычек для столбца
DateTime64/DateTimeвJSONEachRowи аналогичных форматах теперь интерпретируется как Unix-временная метка (секунды с начала эпохи) с необязательной точностью до долей секунды — так же, как в форматеValues,CASTиtoDateTime64. Ранее число с дробной частью (например,1703363853.035) отклонялось с ошибкойCANNOT_PARSE_INPUT_ASSERTION_FAILED, а целое число без кавычек (например,1703363853) считывалось как необработанное масштабированное значениеDateTime64, что давало временную метку вида1970-.... Это обратно несовместимое изменение для целых чисел без кавычек, передаваемых в столбцыDateTime64; строк в кавычках и собственного JSON-вывода ClickHouse (где значения всегда в кавычках) оно не касается. #108091 (alexey-milovidov). - Экспериментальный кодек
ALPтеперь выполняет арифметику масштабированияFloat32вFloat64, что устраняет исключения на десятичных данных и значительно повышает коэффициент сжатия. #111627 (rienath). - Значения настроек временных интервалов (в миллисекундах/секундах), вызывающие переполнение Int64 при пересчёте в микросекунды, теперь отклоняются #112757 (azat).
- Асинхронные метрики теперь могут иметь тип данных
Map, а метрики для отдельных ядер CPU и устройств объединены в единые метрики типа «ключ-значение»: вместоOSUserTimeCPU0,OSUserTimeCPU1, … теперь используется одна метрикаOSUserTimeCPUс отображением номера ядра CPU в значение (аналогично для других метрик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"}), аMetricsTransmitterдля Graphite отправляет их в виде<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]теперь интерпретируются как номера дней (даты с2300-01-01по9999-12-31), а не как Unix-временные метки начала 1970 года. Это соответствует правилу, согласно которому число, попадающее в диапазон номеров дней, считается номером дня. Числа меньше номера дня0000-01-01и временные метки после9999-12-31приводятся к новым границам. #111534 (alexey-milovidov).
Прочие обратно несовместимые изменения
arrayIntersectиarraySymmetricDifferenceбольше не считают значение, повторяющееся внутри одного аргумента, так, будто оно встречается в нескольких аргументах. Запросы, рассчитанные на прежнее поведение, теперь могут возвращать другие результаты:arrayIntersect([1], [2], [1, 1])возвращает[]вместо[1],arrayIntersect([1, 2], [2], [1, 1, 2])возвращает[2]вместо[1, 2], аarraySymmetricDifference([1], [2], [1, 1])возвращает[2, 1]вместо[2]. ДляarraySymmetricDifferenceдостаточно и двух аргументов:arraySymmetricDifference([1], [2, 2])возвращает[2, 1]вместо[1]. Теперь значение засчитывается для аргумента только в том случае, если оно присутствовало во всех предшествующих аргументах, поэтому результат содержит ровно те значения, которые есть во всех аргументах. В рамках того же измененияarrayIntersectстроит хеш-таблицу по наименьшему аргументу, а не по всем сразу, благодаря чему работает до 1,85 раза быстрее и потребляет на треть меньше памяти, если аргументы сильно различаются по размеру. Изменение не затрагиваетarrayUnion. #113021 (alexey-milovidov).- Тип статистики столбцов
minmaxобъявлен устаревшим. #108680 (hanfei1991). - Исправлена проверка прав доступа для
SYSTEM PREWARM PRIMARY INDEX CACHE ... ON CLUSTER, которая ошибочно требовала привилегиюSYSTEM PREWARM MARK CACHEвместоSYSTEM PREWARM PRIMARY INDEX CACHE. #109198 (Algunenano). - Исправлена ошибка, из-за которой
SYSTEM STOP/START CLEANUPиSYSTEM STOP/START VIRTUAL PARTS UPDATE ON CLUSTERтребовали привилегиюSYSTEM PULLING REPLICATION LOGвместоSYSTEM CLEANUP/SYSTEM VIRTUAL PARTS UPDATE. #110289 (groeneai). - Глоб-шаблон
/(любое количество каталогов) теперь соответствует и самому текущему каталогу. Ранее/в глоб-шаблонах не обрабатывался как особый случай, поэтомуdata/**/file.txtне соответствовалdata/file.txt(нулевой уровень вложенности каталогов). #97676 (alexey-milovidov).
Новые возможности
Функции и типы данных
- Добавлены функции
parseQueryToJSONиformatQueryFromJSONдля сериализации и десериализации AST в формате JSON, а также экспериментальный диалектclickhouse_json, включаемый настройкойenable_json_ast_dialect. #100412 (alexey-milovidov). #113480 (fm4v). - Добавлена системная таблица
system.stemmers, в которой перечислены все языки стеммеров, доступные для функцииstem. #100611 (Ergus). - Добавлена поддержка постфиксных операторов стандартного SQL
AT TIME ZONEиAT LOCALв качестве синтаксического сахара дляtoTimeZone. Выражение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применяется до выбора бэкенда по схеме. Перенаправляются только схемы S3, которые разрешаются стандартнымиurl_scheme_mappers; схемы других S3-совместимых поставщиков (cos,obs, …) не перенаправляются — для них нужно напрямую использовать движок или функциюs3. #106093 (alexey-milovidov). - Добавлена функция
dotProductTransposed(псевдонимscalarProductTransposed), которая вычисляет приближённое скалярное произведение столбцаQBitи опорного вектора и дополняет уже существующие функцииL2DistanceTransposedиcosineDistanceTransposed. #108100 (alexey-milovidov). - В тип данных
QBitдобавлен необязательный параметр stride (QBit(T, dimension, stride)), который позволяет хранить группы измерений в отдельных потоках, чтобы векторный поиск мог эффективно читать только первые измерения (например, для эмбеддингов Matryoshka). Транспонированные функции расстояния принимают необязательный четвёртый аргументused_dims, позволяющий читать меньшее число измерений. #108103 (alexey-milovidov). - Добавлена поддержка типа элементов
Int8в типе данныхQBit: теперь можно хранить квантованные 8-битные целочисленные векторы и выполнять по ним векторный поиск с помощью транспонированных функций расстояния (L2DistanceTransposed,cosineDistanceTransposed). #108105 (alexey-milovidov). - Новая функция
randomHadamardTransform(vector[, seed[, output_dims]]): детерминированное рандомизированное преобразование Адамара для вектора чисел с плавающей точкой — ортогональный поворот с сохранением нормы, полезный для предварительной обработки эмбеддингов перед квантованием, а также (при усечении) в качестве случайной проекции Джонсона–Линденштраусса / подвыборочного рандомизированного преобразования Адамара. #108227 (alexey-milovidov). - Реализована агрегатная функция
mergedJSONPatchдля агрегации JSON-значений по принципу merge-patch в стиле RFC 7396, с поддержкой слияния состояний и использования в AggregatingMergeTree. Чтобы получить последнее состояние, можно агрегировать JSON-столбец, используя в качестве ключа сортировки метку времени или другой столбец, задающий порядок. #108349 (larryluogit). - Добавлена функция
xxHash64Spark, которая вычисляет совместимые со Spark значенияxxHash64для входных значений типаStringиNULLс seed42и возвращаетInt64. #108436 (lalitium). - Добавлена функция
digits(n, offset[, length]), которая возвращает число изn, начинающееся с позицииoffset(1-indexed)и содержащееlengthцифр. Еслиlengthне указан, функция возвращает число от позиции offset до конца. #109012 (1000ms). - Добавлена арифметическая функция
sqrдля вычисления квадрата числа. #109061 (lalitium). - Добавлены квантованные транспонированные функции расстояния
cosineDistanceTransposedQuantized,L2DistanceTransposedQuantizedиdotProductTransposedQuantized, которые работают сQBit(Int8), содержащим коды Lloyd-Max, полученные с помощьюquantizeBFloat16ToInt8, и деквантуют сохранённые коды на лету. Опорный вектор с плавающей запятой рассматривается как запрос полной точности и сравнивается с точностьюFloat32(запрос типаFloat64приводится к меньшей точности); опорный векторArray(Int8)также деквантуется, что даёт симметричное расстояние между квантованными векторами. #109405 (alexey-milovidov). - Добавлена новая функция
dictGetRoot, которая возвращает самого верхнего предка (корень) ключа в иерархическом словаре. Это удобная альтернатива выражениюdictGetHierarchy(dict_name, key)[-1]. #109459 (alexey-milovidov). - Добавлена табличная функция
mergeTreeCodecBlockCounts(database, table), которая для каждой комбинации (часть, столбец, подпоток) таблицыMergeTreeпоказывает, сколько сжатых блоков использует каждый кодек. #109623 (rienath). - Добавлена функция
notHas— отрицаниеhasдля массивов, map и JSON. Если haystack — константный массив, настройкаoptimize_rewrite_has_to_in(включена по умолчанию) переписываетnotHas(constant_array, x)вx NOT IN constant_array, поэтому функция выполняется через поиск по множеству и, как иNOT IN, может отсекать данные по индексу первичного ключа. #109926 (nihalzp). - Добавлен геопространственный тип данных
MultiPoint, который хранится какArray(Point)и входит в типGeometry. #109951 (davidmenggx). - Функции
arrayElement(операторvec[n]) иarraySliceтеперь поддерживают тип данныхQBit:qbit[n]возвращает n-й элемент вектора с полной точностью, аarraySlice(qbit, offset, length)возвращает проекцию на подмножество измерений. Обе функции читают только битовые плоскости нужных групп stride, а срезы, выровненные по границам групп stride, переиспользуют сохранённые потоки без копирования. #109953 (Utkal059). - Добавлен токенизатор
splitByRegexpдля текстовых индексов и функцииtokens. Он разбивает входные данные на токены, используя регулярное выражение в качестве разделителя, напримерtokenizer = splitByRegexp('[^\p{L}\p{N}#+]+'). Это позволяет сохранять токены со специальными символами, напримерC++илиC#, которые другие токенизаторы разбили бы на части. #110002 (Ergus). - Добавлены функции
geometryIntersectCartesianиgeometryIntersectSpherical, которые определяют, пересекаются ли две геометрии. В отличие отpolygonsIntersectCartesian/polygonsIntersectSpherical, они принимают любой геометрический тип данных (Point,LineString,MultiLineString,Ring,Polygon,MultiPolygon), включая общий типGeometry, причём аргументы могут быть разных типов. #110062 (alexey-milovidov). - Нативный модуль чтения ORC теперь поддерживает тип ORC
uniontype, сопоставляя его с типом ClickHouseVariant(ранее такие столбцы отклонялись с ошибкойUnsupported ORC type). #110078 (alexey-milovidov). - Нативный выходной формат ORC теперь умеет записывать тип ClickHouse
Variant, сопоставляя его с ORCuniontype(ранее запись завершалась ошибкойILLEGAL_COLUMN). #110085 (alexey-milovidov). - Добавлены форматы фрейминга, которые выбираются новой настройкой
framing_output_format: они мультиплексируют различные части ответа на запрос в едином потоке HTTP-ответа — блоки данных, итоги и экстремумы, пакеты прогресса, события профилирования, журналы сервера и исключения. Реализованы следующие форматы фрейминга:None(по умолчанию, всё работает как прежде),EventStream(события, отправляемые сервером по HTTP),JSONEachPacketBase64иJSONEachPacketString(по одному JSON-объекту на пакет с данными в кодировке base64 или в виде строки). #110127 (alexey-milovidov). - Добавлены табличная функция
bigqueryи движок таблицыBigQueryдля чтения из таблиц Google BigQuery и записи в них, включая общедоступные наборы данных. Структура таблицы определяется по схеме таблицы BigQuery. Для аутентификации поддерживаются токен доступа OAuth, ключ сервисного аккаунта в формате JSON и клиент OAuth с токеном обновления. #110166 (alexey-milovidov). - Новая функция
aiRedactобнаруживает и маскирует персональные данные (PII) в тексте с помощью LLM-провайдера. Укажите категории для маскирования (например,['email', 'name']) или передайте пустой массив, чтобы использовать набор категорий PII по умолчанию. Найденные значения заменяются маркером (по умолчанию[REDACTED]). #110464 (davidmenggx). - Добавлена функция
aiFilter, которая с помощью LLM проверяет, выполняется ли для текста условие, сформулированное на естественном языке, и возвращаетUInt8для использования вWHERE,PREWHEREиJOIN ... ON. #110594 (ylw510). - Добавлена поддержка TLS/SSL-подключений к PostgreSQL для движка таблицы
PostgreSQL, табличной функцииpostgresql, движков баз данныхPostgreSQLиMaterializedPostgreSQL, а также словарейPostgreSQL: поддерживаютсяsslmode, сертификаты и ключ, которые задаются либо непосредственно содержимым (sslrootcert_pem,sslcert_pem,sslkey_pem; маскируются как пароли), либо путями (sslrootcert,sslcert,sslkey; принимаются только из именованной коллекции, определённой в конфигурационном файле сервера). #110615 (alexey-milovidov). - Табличную функцию
postgresqlи движок таблицыPostgreSQLтеперь можно использовать для подключения к другому серверу ClickHouse по протоколу PostgreSQL (при указании имени таблицы; вариантquery(...)пока не поддерживается). Добавлены функции совместимости с PostgreSQLformat_typeиcurrent_setting. #110760 (alexey-milovidov). - Новая функция
aiSimilarity, которая вычисляет семантическое сходство двух текстов с помощью модели эмбеддингов. ВозвращаетNullable(Float32)в диапазоне[-1, 1], где1означает, что тексты идентичны, илиNULL, если один из операндов равенNULLили пуст либо для него не удалось вычислить эмбеддинг. #110777 (davidmenggx). - Добавлены движки баз данных
RemoteиRemoteSecure, которые обеспечивают доступ в реальном времени к таблицам базы данных на удалённом сервере ClickHouse и перенаправляют на него запросыSELECTиINSERT. Это аналоги движков баз данныхMySQLиPostgreSQLдля связи ClickHouse с ClickHouse. #110975 (alexey-milovidov). - Поддержка пайп-операторов в SQL-запросах:
FROM t |> WHERE x > 1 |> AGGREGATE count() AS c GROUP BY y |> ORDER BY c DESC |> LIMIT 10— по аналогии с пайп-синтаксисом GoogleSQL. За любым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, в котором фиксируется время завершения мутации. Для незавершённых мутаций и мутаций с неизвестным временем завершения выводится ноль. #113474 (nikitamikhaylov). - Добавлен новый тип схемы
bucketedдляsystem.metric_log, при котором все метрики хранятся в одном столбцеMap(Enum16(...), Int64)с бакетной сериализациейMapна 128 бакетов, а для совместимости для каждой метрики создаётся столбецALIAS. В результате таблица состоит из нескольких столбцов вместо тысяч, нулевые значения не хранятся, а при чтении одной метрики читается только один из 128 бакетов. Кроме того, кMapс ключами типаEnumтеперь можно обращаться по строковому имени значения перечисления, напримерmap['name']. #115380 (alexey-milovidov). - Добавлен токенизатор
chineseдля функцииtokensи текстовых индексовMergeTree. Он разбивает китайский текст на слова с помощью словаря и скрытой марковской модели (алгоритм заимствован из jieba) и поддерживает уровни детализацииcoarse_grained(по умолчанию) иfine_grained. #89945 (amosbird). - Добавлена агрегатная функция
groupFormat, которая форматирует строки каждой группы в заданном формате вывода и возвращает результат в виде строки. #93201 (wandersofb). - Добавлен комбинатор агрегатных функций
-Tuple, который независимо применяет базовую агрегатную функцию к каждому элементу столбца типаTupleи возвращаетTupleс результатами, сохраняя имена элементов:sumTuple(t)дляt = (a, b)возвращает(sum(a), sum(b)). Агрегатные функции с несколькими аргументами принимают по одномуTupleна каждый аргумент, сопоставляя их по позиции:corrTuple((a1, a2), (b1, b2))возвращает(corr(a1, b1), corr(a2, b2)). В отличие от-ForEachдля массивов, элементы могут иметь разные типы, при этом типы результатов и имена каждого элемента сохраняются. #98190 (RinChanNOWWW).
Возможности SQL и запросов
- Добавлена поддержка предложений WHERE в определениях проекций. Проекции с WHERE материализуют только строки, удовлетворяющие предикату, и оптимизатор может использовать их (на основе оценки стоимости), если из условия WHERE запроса следует условие WHERE проекции. #102347 (SBALAVIGNESH123).
- Добавлена возможность обращаться к таблицам и базам данных через пути URL в HTTP-интерфейсе (например, `/database/table.format.gz?filter=a>0`), а также новые настройки (`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`), которые можно комбинировать друг с другом и с уже существующим параметром URL `query`. #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и refreshable materialized view. Для refreshable materialized view они служат псевдонимами существующих командSYSTEM ... VIEW. В рамках поддержки этих команд для NATS таблицы JetStream теперь подтверждают сообщения только после успешной вставки (семантика «как минимум один раз»; ранее сообщения подтверждались автоматически при доставке и могли теряться, если вставка завершалась ошибкой). Новая настройкаnats_wait_for_flush_interval(по умолчаниюfalse, что сохраняет прежнее поведение с низкой задержкой) позволяет держать цикл потребления открытым в течение всего интервала сброса, а не сбрасывать данные на диск сразу после опустошения очереди. Новая настройкаnats_commit_on_selectпозволяет прямому запросуSELECTк таблице JetStream потреблять (подтверждать) прочитанные им сообщения. #107476 (NIKTONIKTO717). - Табличные функции и движки таблиц
mysql,postgresqlиsqliteтеперь могут принимать пользовательский запрос (вместо имени таблицы) и передавать его во внешнюю СУБД как есть; запрос записывается либо как подзапрос(SELECT ...), либо какquery('SELECT ...'). Структура результирующей таблицы определяется по результату запроса, а сама таблица доступна только для чтения. #107740 (alexey-milovidov). - Добавлен табличный движок
QueryRunner. Записи, вставляемые в таблицуQueryRunner, представляют собой запросы, которые выполняет движок. Движок можно использовать для асинхронного выполнения запросов, пакетного выполнения сгенерированных запросов, направления запросов на удалённые кластеры, бенчмарков, фаззинга и тестирования с теневым трафиком. #107888 (mstetsyuk). - Добавлена поддержка режима рамки окна
GROUPSдля оконных функций (SQL:2011), напримерany(price) OVER (PARTITION BY symbol ORDER BY ts GROUPS BETWEEN CURRENT ROW AND 1 FOLLOWING). В рамкеGROUPSграницы отсчитываются целыми группами равных строк — наборами строк с одинаковым значением ключаORDER BY, — поэтомуN PRECEDING/N FOLLOWINGозначаютNгрупп равных строк до или после группы текущей строки, а не физические строки (ROWS) и не расстояние по значениюORDER BY(RANGE). #108653 (nihalzp). - Обычный
CREATE MATERIALIZED VIEW ... POPULATEтеперь выполняется локально атомарно: подписка представления на новые вставки в исходную таблицу и снимок существующих данных выполняются вместе под кратковременной эксклюзивной блокировкой источника, поэтому строки, вставленные через тот же сервер параллельно с заполнением, больше не теряются и не дублируются (новая настройкаmaterialized_views_populate_atomically, включена по умолчанию). Гарантия распространяется только на локальный путь вставки (вставки, поступающие на другую реплику или через распределённый путь записи, ею не охватываются) и требует источника, способного предоставить зафиксированный снимок (семействоMergeTreeиMemory); для других источников, а также дляCREATE OR REPLACE/REPLACEи представлений, создаваемых в базах данныхReplicated, сохраняется прежнее неатомарное заполнение. Кроме того,POPULATEтеперь можно использовать вместе сTOдля заполнения целевой таблицы уже имеющимися данными. #108715 (alexey-milovidov). ALTER USER,ALTER ROLEиALTER SETTINGS PROFILEтеперь принимаютSET name = valueкак псевдоним дляMODIFY SETTING name = value. Эта форма изменяет отдельные настройки, сохраняя остальные, — в отличие от предложенияSETTINGSбез модификаторов, которое заменяет весь список настроек. Это снижает риск случайно стереть другие настройки пользователя. #108722 (groeneai).- Добавлена поддержка
ALTER TABLE ... MODIFY CONSTRAINT [IF EXISTS] name CHECK exprдля изменения выражения существующего ограничения без его пересоздания. #108768 (alexey-milovidov). - Добавлен алгоритм IEJoin на основе сортировки для JOIN, у которых секция
ONсодержит два сравнения-неравенства (<,<=,>,>=) между соединяемыми таблицами; он включается добавлениемie_joinв настройкуjoin_algorithm. Поддерживаются виды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. Сервер принимает запрос, сразу возвращает пустой результат и выполняет запрос до конца независимо от состояния соединения. Результат отбрасывается. Отслеживать запрос можно по егоquery_idвsystem.processesиsystem.query_log. Настройка предназначена для длительных запросов, таких какINSERT ... SELECT,CREATE TABLE … AS SELECTилиCREATE MATERIALIZED VIEW … POPULATE, которые не должны прерываться при разрыве соединения. #112816 (mstetsyuk). - Добавлена поддержка ALTER TABLE … MODIFY PROJECTION для изменения настроек уровня проекции (например, index_granularity) у существующей проекции без её перестроения. Новые настройки применяются отложенно, в ходе слияний. #113343 (diegomestre2).
- Каталог движка таблиц S3 для озер данных теперь поддерживает не только запросы к существующим таблицам, но и
INSERT. #113505 (scanhex12). - Каталог
Icebergтеперь поддерживает каталог Snowflake Horizon с параметромcatalog_type = 'horizon', что позволяет читать и записывать данные в таблицыIceberg, управляемые Snowflake. #114547 (melvynator). - Добавлена настройка
skip_unavailable_shards_mode(также доступна как настройка движкаDistributed), которая определяет, какие исключения от удалённого сегмента молча игнорируются при включённой настройкеskip_unavailable_shards. Это позволяет точнее управлять поведением запросов в распределённых средах. #79091 (byte-sourcerer).
Хранилище, озёра данных и объектное хранилище
- Добавлена поддержка формата файлов Puffin (https://iceberg.apache.org/puffin-spec/). Теперь этот формат можно использовать в табличных функциях
file,url,s3и других. #103936 (scanhex12). - Для таблиц
MergeTreeдобавлен формат хранения частей данных «packed», при котором все файлы части хранятся в одном архиве (data.packed), а не в отдельном файле для каждого потока. Он управляется настройкамиmin_bytes_for_full_part_storage,min_rows_for_full_part_storageиmin_level_for_full_part_storageи по умолчанию отключён. Примечание о совместимости: как только таблица начинает записывать части в формате packed, более старые версии сервера уже не смогут их прочитать, поэтому после включения этого формата откатить сервер на предыдущую версию будет невозможно. #108118 (Algunenano). - Для движка таблиц NATS добавлена настройка
nats_credentials, позволяющая задавать учётные данные NATS непосредственно в виде строки (с тем же содержимым, что и в файле.creds). #110733 (addshore).
Форматы данных и ингестия
- Добавлен формат вывода
HiveText, записывающий данные в текстовом представлении Apache HiveLazySimpleSerDe. Поля разделяются символом\x01, строки — разделителем, заданным новой настройкойformat_hive_text_rows_delimiter(по умолчанию\n), а для вложенных значенийArray,MapиTupleиспользуется список разделителей Hive. Вывод рассчитан на стандартныйLazySimpleSerDeв Hive и не симметричен входному форматуHiveTextв ClickHouse в части вложенных значений и пользовательских разделителей строк. #107582 (alexey-milovidov). - Добавлен формат вывода
GeoJSONдля записи документов GeoJSONFeatureCollection, в которых каждой строке соответствует один объект (feature). Новая настройкаformat_geojson_validate_geometry(включена по умолчанию) проверяет корректность геометрий GeoJSON при чтении и записи; входной форматGeoJSONтеперь определяет типidкакNullable(String), что позволяет отличать отсутствующие или равныеnullидентификаторы от пустых строк. #108065 (nihalzp).
Настройки, доступ и обсервабилити
- Добавлена встроенная страница поиска по документации, доступная по пути
/docsHTTP-интерфейса. Она обеспечивает мгновенный поиск по таблицеsystem.documentationи отображает справочную документацию (с подсветкой синтаксиса, математическими формулами и перекрёстными ссылками). #108345 (alexey-milovidov). - Добавлен японский токенизатор для текстовых индексов и функций tokens/hasAnyTokens/hasAllTokens на основе морфологического анализатора MeCab. Словарь загружается во время выполнения из каталога, указанного в конфигурации сервера, и перед использованием проверяется по контрольной сумме SHA-256. #111420 (Ergus).
- Добавлена новая настройка файлового кэша
system_cache_extensions, которая определяет, какие файлы хранятся в системном кэше при включённой настройкеuse_split_cache. #111575 (kirillgarbar). - Добавлена настройка
always_fetch_mutated_part, которая позволяет реплике загружать мутированные части с других реплик, а не выполнять мутации локально. #113020 (rorylshanks).
Другие новые возможности
- Добавлена поддержка
WITH TIESдля отрицательногоLIMIT. #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). - Добавлены функции
geoToUTM,UTMToGeo,geoToMGRSиMGRSToGeoдля преобразования географических координат WGS84 в системы координат UTM и MGRS и обратно. #108939 (alexey-milovidov). - Добавлены команды
SYSTEM UNLOAD DICTIONARYиSYSTEM UNLOAD DICTIONARIES, освобождающие память, занятую словарём, без удаления его определения. При следующем обращении словари будут загружены повторно (отложенно). #109639 (Manerone). - Добавлен новый токенизатор
icuдля текстовых индексов и функцийtokens,hasAnyTokensиhasAllTokens, обеспечивающий сегментацию слов Unicode с учётом локали (в том числе сегментацию на основе словаря для таких языков, как китайский, японский и тайский). #109940 (Ergus). - Добавлен новый кодек
ZXC— асимметричный LZ-кодек с медленным сжатием и очень быстрой декомпрессией; по коэффициенту сжатия он занимает промежуточное положение междуLZ4иZSTD. #110620 (alexey-milovidov). - Добавлена настройка
s3_base, позволяющая разрешать относительные URL в табличных функцияхs3,s3Cluster,gcsиoss, а также в движке таблицыS3относительно базового URL S3. Добавлен движок баз данныхURL, который интерпретирует имена таблиц как URL, разрешая их относительно необязательного базового адреса, и передаёт их соответствующему бэкенду. #111512 (alexey-milovidov). - Для
url()и движкаURLреализовано раскрытие подстановочных шаблонов: ClickHouse читает индексные HTTP-страницы (HTML или текстовые листинги каталогов) и извлекает из них подходящие URL. Шаблоны сопоставляются с компонентом пути URL; при этом действуют ограничения на размер индексной страницы и на количество читаемых каталогов. #95181 (niyue). - Для
kafka_sasl_mechanismдобавлено поддерживаемое значениеAWS_MSK_IAM, позволяющее ClickHouse аутентифицироваться в Amazon MSK с помощью ролей IAM без необходимости управлять учётными данными SASL/SCRAM. #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, поэтому функция не теряется при перезапуске сервера. Экспериментальный драйверc_function_body(proof-of-concept) компилирует и выполняет тела функций на C в изолированных контейнерах Docker в режимеexecutable_pool. #105131 (alexey-milovidov). - Запросы Prometheus Query API к
/api/v1/queryи/api/v1/query_rangeтеперь записываются вsystem.query_logс метрикамиread_rowsиread_bytes. #106611 (JTCunning). - Добавлена поддержка чтения с распределённым планом запроса для
SELECT ... FINALпо таблицам семейства MergeTree при включённой настройкеmake_distributed_plan. #108148 (davenger). - Добавлено экспериментальное выполнение запросов к MergeTree с параллельными репликами на основе плана. #108504 (devcrafter).
- Добавлена экспериментальная табличная функция
eval, которая вычисляет константное выражение в строку запроса и выполняет полученный одиночный SELECT-запрос. По умолчанию функция отключена; включить её можно настройкой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). - Повышена безопасность экспериментальных функций ИИ: по умолчанию запрещены небезопасные (
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): весь JOIN выполняется во фрагменте распределённого плана, при этом одна сторона координируется между репликами, а другая рассылается на все реплики. #112268 (devcrafter). - Теперь вместо простого
QUERY_WAS_CANCELLEDвыводится ошибка, из-за которой был отменён распределённый запрос (make_distributed_plan = 1). Ранее фактическая ошибка сбойной задачи воркера была видна только в логе сервера. #112590 (davenger). - Добавлена поддержка распределённого выполнения планов запросов с
IN (subquery)без переписывания вJOIN. Множество строится один раз на инициаторе, а его значения передаются вместе с задачами воркеров. Принудительное переопределениеrewrite_in_to_joinудалено; переписывание по-прежнему можно включить явной настройкой. #113826 (davenger). - Запрос с распределённым планом (
make_distributed_plan) теперь останавливает вышестоящие стадии, как только условиеLIMITвыполнено, а не вычисляет полный результат, чтобы затем его отбросить. #114806 (davenger). - Исправлена ошибка
Illegal type Decimal(18, 0) of argument of function toIntervalNanosecond, возникавшая, когда в запросе PromQL используетсяoffsetвнутри селектора диапазона, напримерrate(m[2m] offset 5m). #114997 (nikitamikhaylov). - Добавлена поддержка агрегации
GROUPING SETSв распределённых планах, построенных оптимизатором Cascades (make_distributed_plan = 1, enable_cascades_optimizer = 1). #115426 (davenger). - Таблицы
TimeSeriesтеперь могут вести таблицу «recent samples»: если новой настройке движкаrecent_samples_ttl_secondsзадано ненулевое значение, движок создаёт копию таблицы образцов с TTL (с партиционированием поrecent_samples_partition_by, по умолчанию — по дням), которая пополняется при каждой вставке, а запросы PromQL, временной диапазон которых укладывается в окно TTL, автоматически читают данные из неё. Благодаря этому правила оповещений и записи, а также панели мониторинга с коротким диапазоном на больших таблицах работают в несколько раз быстрее. Чтение из этой таблицы в приоритетном порядке можно отключить с помощью новой настройки уровня запросаtime_series_prefer_recent_samples_table. #115441 (nikitamikhaylov). - Распределённые планы запросов (
make_distributed_plan) теперь оперативно останавливают бездействующие вышестоящие стадии после выполнения условияLIMIT: бездействующий приёмник обмена считываетNoMoreDataNeededсразу после его поступления, а бездействующий источник обмена обнаруживает, что его выход закрыт, и передаёт сигнал остановки вверх по цепочке. Ранее такие стадии продолжали читать и вычислять данные, которые никто не использовал. #115690 (davenger). - Механизм автоматических параллельных реплик теперь может собирать статистику во время выполнения и включать параллельные реплики для поддерживаемых запросов, если включена настройка
parallel_replicas_plan_based. #115788 (devcrafter). - Добавлен экспериментальный стоимостной оптимизатор Cascades для распределённых планов запросов, который включается настройкой
enable_cascades_optimizer = 1совместно сmake_distributed_plan = 1. На основе оценочной стоимости он выбирает стратегию соединения (shuffle, broadcast, replicated или local), агрегации (двухфазная, shuffle или локальная), двухстадийный распределённый top-N, а также параллельное или реплицированное чтение, при необходимости добавляя операторы обмена. #86353 (davenger).
Хранилище, озера данных и индексы
- Добавлен SLRU-кэш в памяти для десериализованных файлов метаданных Paimon (списков манифестов и манифестов). Если он включен настройкой
use_paimon_metadata_files_cache, повторные запросы к одной и той же таблице Paimon не загружают и не разбирают метаданные из объектного хранилища заново. #104657 (Binnn-MX). - Экспериментальный
ReaderExecutor(use_reader_executor, по умолчанию выключен) теперь может держать открытым удаленное соединение с источником и повторно использовать его при последовательных чтениях, что сокращает количество запросов к объектному хранилищу при сканировании. #107735 (CheSema). - В путь чтения экспериментального
ReaderExecutor(use_reader_executor, по умолчанию выключен) добавлен файловый кэш со сквозным чтением (read-through). #110029 (CheSema). - Добавлена экспериментальная настройка
MergeTreeallow_experimental_adaptive_codec_selection. Если она включена, при слияниях и мутациях для столбцов с кодеком по умолчанию в каждом блоке выбирается кодек, обеспечивающий наименьший размер данных. #111834 (rienath). - В путь чтения экспериментального
ReaderExecutor(use_reader_executor, по умолчанию выключен) добавлен уровень кэша страниц в пространстве пользователя. При промахе исполнитель теперь заполняет кэш страниц в пространстве пользователя и обслуживает из него последующие чтения без копирования (zero-copy). #114890 (CheSema). - Компакция файлов манифестов
Icebergтеперь доступна черезOPTIMIZE TABLE ... MANIFESTи позволяет сократить количество файлов метаданных. Эта возможность включается настройкойallow_experimental_iceberg_compaction. #98178 (SmitaRKulkarni).
Функции, форматы и ИИ
- Экспериментальная возможность: запрос
SELECT count(*) FROM t WHERE col <op> default(col)выполняется на основе статистики разреженности по каждому столбцу изserialization.jsonвообще без сканирования данных, если предикат точно разделяет столбец на значения по умолчанию и прочие значения. #105890 (Algunenano). - Добавлено экспериментальное семейство векторных кодеков
Quantize(...)и включаемое по желанию двухэтапное переписывание запросов приблизительного векторного поиска с использованием сопутствующих квантованных потоков. #108565 (shankar-iyer). - Возвращён экспериментальный кодек сжатия с потерями и ограниченной погрешностью
SZ3для столбцовFloat32/Float64(и массивов из них). Для него требуется настройкаallow_experimental_codecs. #108788 (alexey-milovidov). - Исправлено чтение данных, сжатых экспериментальным кодеком
SZ3('ALGO_LORENZO_REG', ...), которое ранее завершалось ошибкойCORRUPTED_DATA, а также устранено неопределённое поведение при сжатии экспериментальным кодекомSZ3неконечных значений с плавающей запятой (NaNи бесконечностей). #110762 (alexey-milovidov). - PromQL: функции даты и времени (
hour(),minute(),month(),year(),day_of_week(),day_of_month(),day_of_year(),days_in_month()) теперь можно вызывать без аргументов — по умолчанию используетсяvector(time()), как в Prometheus. #111869 (valerypetrov). - PromQL: исправлены операции над мгновенными векторами без тегов, например
vector(1) + vector(2),topk(1, vector(1)),label_replace(vector(1), ...)и бинарные операторы сon(), которые завершались ошибкой типа. #111872 (valerypetrov). - PromQL: реализована функция
deriv; исправлена ошибка, из-за которой лежащая в её основе агрегатная функция при временных метках с миллисекундным разрешением возвращала значения в 1000 раз меньше корректных. #112360 (valerypetrov). - Оптимизация чтения в порядке сортировки теперь применяется к запросам с
ORDER BYпри включённой настройкеparallel_replicas_plan_based: сортировка передаётся на реплики, а результаты объединяются на initiator, поэтому каждая реплика читает данные в порядке ключа сортировки. Также исправлена ошибкаUnknown function __topKFilterдляORDER BYпо столбцу, не входящему в первичный ключ, при включённой настройке. #114315 (devcrafter). - Исправлено чтение при векторном поиске после повторной загрузки части данных (например, после
ATTACHили перезапуска сервера): части больше не теряют подстолбцы кодекаQuantized, поэтому поиск читает квантованные подстолбцы, а не откатывается к столбцу с полной точностью. #114763 (shankar-iyer). - Экспериментальный движок таблицы
TimeSeriesбольше не применяет кодекGorillaк автоматически создаваемым столбцамvalueвнутренней таблицы samples; теперь по умолчанию для них используетсяCODEC(ZSTD(1)). Для явно объявленных столбцов сохраняются кодеки, указанные пользователем. Значение по умолчанию для столбцаtimestampне изменилось (CODEC(DoubleDelta, ZSTD(1))). #112110 (nikitamikhaylov). #114790 (nikitamikhaylov). - Добавлена поддержка
ROLLUP,CUBE,GROUPING SETSи функцииgroupingв запросах, выполняемых сmake_distributed_plan = 1. #114950 (davenger). - В экспериментальный кодек ALP добавлены вариант Real Doubles (RD) и необязательный аргумент
ALP(AUTO|STD|RD). Теперь ALP без аргументов не использует всегда STD, а автоматически выбирает между уже существующей схемой STD и RD. #99654 (nazarii-piontko).
Другие экспериментальные возможности
- Добавлена статическая привязка партиций к сегментам для StorageKafka2 с помощью настроек kafka_partition_shard_num и kafka_shard_count, что позволяет нескольким сегментам ClickHouse детерминированно потреблять непересекающиеся подмножества партиций Kafka. #108886 (JingYanchao).
- Теперь для аутентификации в OneLake можно использовать заранее полученный Bearer-токен, указав его в настройке
onelake_bearer_tokenвместоonelake_client_idиonelake_client_secret. Это избавляет от необходимости передавать долгоживущий секрет клиента. Токен не обновляется, поэтому после истечения срока его действия базу данных необходимо пересоздать. #109104 (asya-ch). - Исправлено значение
data_uncompressed_bytesдля индексов пропуска, упакованных вskp_idx.packed(черезpacked_skip_index_max_bytes): вместо несжатого размера сообщался сжатый, что к тому же могло препятствовать активацииdistributed_index_analysis. #109272 (Algunenano). - В экспериментальный HTTP-обработчик Prometheus remote-write v1 добавлена поддержка сжатия Zstandard. #110907 (JTCunning).
- PromQL: реализованы функции
clamp,clamp_min,clamp_maxиround. #111870 (valerypetrov). - PromQL:
quantileс уровнем квантиля вне диапазона [0, 1] теперь, как и Prometheus, возвращает -Inf/+Inf/NaN вместо ошибки, аhistogram_quantileпо примеру Prometheus игнорирует входные серии, у которых меткаleотсутствует или не поддаётся разбору. #111871 (valerypetrov). - PromQL: реализованы функции
changes()иresets(). #112352 (valerypetrov). - Исправлен сбор статистики вставок и запросов, поступающих через конечную точку Prometheus remote-write. #112825 (JTCunning).
- PromQL: при взятии остатка от деления на бесконечный делитель конечные значения теперь сохраняются. #113746 (fallintoplace).
- Литеральные символы перевода строки в обычных строках PromQL в кавычках теперь отклоняются. #114381 (fallintoplace).
- Очень большое значение
distributed_plan_workers_numбольше не приводит к аварийному завершению сервера сstd::length_errorпри включённых экспериментальных настройкахmake_distributed_planиenable_cascades_optimizer. Теперь такое количество узлов отклоняется с ошибкойINVALID_SETTING_VALUE. #115398 (groeneai). - Для таблиц
TimeSeriesреализована конечная точка/api/v1/seriesPrometheus HTTP API: поддерживаются селекторы серийmatch[](повторяющиеся значения объединяются), необязательный временной диапазонstart/endи необязательный параметрlimit. #115676 (nikitamikhaylov).
Повышение производительности
Производительность JOIN и агрегации
- Кэш условий запроса теперь используется и для запросов, проходящих через динамическую фильтрацию TopK (
ORDER BY ... LIMIT n). Запись QCC партиционируется по параметрам плана TopK, поэтому один и тот же запрос повторно использует закэшированные результаты фильтра WHERE, а другое значениеLIMIT, другой столбец или направление сортировки приводят к созданию новой записи. #104478 (alexey-milovidov). - LIMIT теперь проталкивается в агрегацию по порядку, что позволяет досрочно завершать выполнение, когда ключ GROUP BY совпадает с ключом ORDER BY и ключом сортировки таблицы. Это значительно сокращает количество прочитанных строк. #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. Правая сторона хеш-JOIN теперь использует компактную 8-байтовую ссылку на строку на основе индекса, поэтому записи хеш-таблицы дляALLJOIN при любом типе ключа стали такими же компактными, как и дляANYJOIN. По результатам тестов на крупных запросах сparallel_hashJOIN —INNERиANYJOIN таблиц размером 100–300 миллионов строк по ключамUInt64иString, как с уникальными, так и с повторяющимися ключами — медианный запрос ускорился примерно на 12 % и потреблял примерно на 15 % меньше пиковой памяти, причём ни один запрос не замедлился. Наибольший выигрыш получилиINNERJOIN по ключамUInt64(медианное ускорение около 21 % при снижении потребления памяти на 38 %). #107189 (harikrishnan94). - Добавлен алгоритм перебора порядка JOIN dpsub, который строит оптимальные планы JOIN с меньшими накладными расходами на оптимизацию, чем dpsize, и поддерживает не только внутренние JOIN. #107351 (fkastrati).
- Одноуровневые агрегации с небольшим использованием памяти больше не преобразуются в двухуровневые: для состояния агрегации подключается отдельный трекер памяти вместо учёта памяти всего запроса. #107490 (m-selmi).
- При анализе агрегирующих запросов больше не строится полное AST запроса: ключ кэша статистики размеров хеш-таблицы агрегации теперь вычисляется по плану запроса, а не по AST. #107643 (novikd).
- Добавлена возможность переключаться с
hashJOIN, использованного при первом выполнении запроса, наparallel_hashпри последующих выполнениях на основе статистики, собранной во время первого выполнения. #108125 (m-selmi). - Размер хеш-таблицы из статистики JOIN, собранной во время выполнения, теперь используется для оптимизации размера runtime-фильтров JOIN при последующих выполнениях запроса. Поведение управляется новой настройкой
join_runtime_filter_size_from_hash_table_stats. #108313 (m-selmi). - Ускорено выполнение и снижено использование памяти для запросов
DISTINCTк партиционированным таблицамMergeTree: теперь строки каждой партиции обрабатываются в пределах одного потока, поэтому предварительныйDISTINCTкаждого потока работает с непересекающимся набором ключей, а один и тот же набор ключей больше не встречается в нескольких предварительных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содержит также предикаты неравенства. Благодаря этому в смешанных соединениях по равенству и неравенству в hash join поступает меньше строк. НаLEFT ANTI JOINэто изменение не влияет. #108579 (29antonioac). - Порог программной предвыборки (prefetch) для хеш-таблиц агрегации и JOIN снижен с
4 * L2 cache sizeдоL2 cache size, так что предвыборка включается, как только хеш-таблица перестаёт помещаться в L2. Это устраняет регрессию производительностиGROUP BYиJOINна хеш-таблицах среднего размера (~1–8 МиБ) на платформах с большим заявленным объёмом L2 (например, aarch64 с L2 объёмом 2 МиБ). #108655 (groeneai). - Улучшена производительность оконных функций. Оконные запросы к широким таблицам, содержащие
SELECT *, теперь потребляют значительно меньше памяти и выполняются быстрее. Оконные агрегаты, включаяquantile*,uniq*иgroupArray, работают быстрее сOVER ()иOVER (ORDER BY ... RANGE ...). Функцияcume_distтакже стала быстрее, а окна сPARTITION BYилиORDER BYтеперь эффективнее работают со столбцами, содержащими много повторяющихся значений. #108688 (nihalzp). - Запросы агрегации без агрегатных функций теперь используют методы на основе
HashSetвместоHashMap(для поддерживаемых типов ключей). Наблюдалось ускорение до 1,8 раза. #108862 (nickitat). - Снижены накладные расходы, связанные с конкуренцией за блокировки, в алгоритме JOIN
parallel_hash. #108938 (m-selmi). - Добавлено новое значение
join_algorithm—parallel_full_sorting_merge: для хеш-совместимых соединений по равенству оно разбивает полное сортирующее соединение слиянием по хешу ключей соединения на независимые соединения слиянием для каждого сегмента, выполняемые во всех потоках. При этом сохраняется характерное для соединения слиянием низкое потоковое потребление памяти, но обработка распараллеливается (в бенчмарке — примерно в 2,4 раза быстрее и примерно в 3,3 раза меньше памяти, чемparallel_hash). СоединенияASOFоткатываются к одиночномуfull_sorting_merge; для хеш-несовместимых типов ключей (с плавающей точкой,JSON,Object,Dynamic) пропускается только переписывание с хеш-распределением, при этом их по-прежнему можно сегментировать на источнике по диапазонам первичного ключа, если включена настройкаquery_plan_join_shard_by_pk_ranges. Результат не упорядочен. #109005 (alexey-milovidov). - Статистика столбцов теперь по умолчанию материализуется при
INSERT, если текущий активный размер таблицы вместе с размером записываемого блока не превышает значения новой настройкиmaterialize_statistics_on_insert_max_table_size(по умолчанию 25 GiB). Проверка выполняется для каждого записываемого блока, поэтому при первой массовой загрузке в пустую таблицу статистика всё равно может материализоваться для каждого записанного блока. Благодаря этому стоимостный оптимизатор JOIN получает точные оценки для только что загруженных таблиц измерений и не выбирает заведомо неудачный порядок JOIN (например, запросы TPC-H Q5 и Q8 больше не завершаются по тайм-ауту при scale factor 40). Для крупных устоявшихся таблиц фактов статистика, как и прежде, материализуется во время слияний. #109454 (alexey-milovidov). - Оптимизирована агрегатная функция
uniqCombinedдля агрегации без ключа. #109794 (CurtizJ). - Оптимизированы агрегатные функции
uniqHLL12иuniqCombined. #109831 (CurtizJ). - Обработка строк без соответствия в алгоритме JOIN
parallel_hashтеперь распараллеливается ещё в двух случаях: при наличии остаточного фильтра и при малых ключах JOIN (одноуровневая хеш-таблица). #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предложениеWHERE, отбрасывающее NULL и ссылающееся на столбцы обеих сторон внешнего JOIN (например,WHERE l.k = 42 AND r.k = 42), теперь преобразует JOIN вINNER(илиLEFT/RIGHT) и выполняет отсечение по первичному ключу — так же, как приjoin_use_nulls = 0. Ранее в этом случае преобразование не выполнялось, и обе таблицы читались целиком. #110121 (groeneai). - Оптимизированы функции
uniq,uniqExactиuniqHLL12при агрегации без ключа. #110150 (CurtizJ). JOIN, условиеONкоторого всегда ложно (например,ON 1 = 2,ON NULLили условие, сводящееся к false, такое какa.t = 'A' AND a.t = 'B'), больше не читает сторону, не влияющую на результат. Новая оптимизация плана запроса заменяет пустым источником те входные стороны, которые не могут дать ни одной строки. Управляется настройкойquery_plan_short_circuit_constant_false_join(по умолчанию включена). #110234 (groeneai).- Финальное слияние одноуровневых хеш-таблиц агрегации теперь распараллелено: пространство ключей разбивается на непересекающиеся хеш-партиции, которые потоки сливают независимо друг от друга (настройка
enable_parallel_single_level_merge, включена по умолчанию). Это ускоряет запросыGROUP BY, в которых хеш-таблицы отдельных потоков не достигают порога перехода к двухуровневой структуре, но слияние занимает основную часть времени выполнения. #110395 (nihalzp). - Ключи агрегации из одного
Stringтеперь используют более компактное представление хеш-таблицы, что ускоряет нагрузкиGROUP BYс преобладанием строковых данных. Новая настройкаenable_packed_string_keys_in_aggregationвключена по умолчанию; если её отключить или задатьcompatibilityниже26.8, будет использоваться прежний путьStringHashTable, который может работать быстрее для ключей очень низкой мощности длиной более 11 байт. #110573 (harikrishnan94). #112089 (harikrishnan94). - Производительность полного сортирующего соединения слиянием в разреженных сценариях повышена в 1,5–3 раза. #111200 (vdimir).
join_runtime_filter_from_fixed_hash_tableтеперь включается и в случае, когда типы ключей JOIN на стороне проверки и на стороне построения различаются (например, ключ проверки имеет тип Nullable, а ключ построения — нет). #111244 (m-selmi).- Повышена производительность
RIGHTиFULLJOIN с алгоритмомparallel_hashв случаях, когда правая сторона содержит ключи JOIN со значениемNULLили строки, отфильтрованные выражениемON: карты NULL больше не перестраиваются. #111258 (m-selmi). - Новый адаптивный алгоритм для параллельного
GROUP BY(управляется настройкойenable_adaptive_aggregator, включённой по умолчанию): каждый поток агрегирует данные в собственную хеш-таблицу, пока в ней не наберётсяadaptive_aggregator_freeze_thresholdключей, после чего замораживает её. Благодаря этому частые ключи продолжают обновлять небольшие таблицы, помещающиеся в кэш, без какой-либо координации, а редкие ключи по своему хешу направляются в очереди соответствующих бакетов и агрегируются ровно один раз — в ходе параллельного по бакетам слияния. #111459 (nihalzp). - Ускорено построчное хеширование значений столбцов JSON/
Object, хранящихся в общих данных (используется, например, вuniq/uniqExactпо JSON-столбцу и в хешированных ключахGROUP BY/DISTINCT):ColumnDynamicбольше не реконструируется для каждого значения. Хеш-значения не изменились. #111501 (valerypetrov). - Повышена производительность RIGHT и FULL hash JOIN с несколькими дизъюнктами
ORв секции ON, а также RIGHT/FULL JOIN с остаточными условиями (неравенствами). #111590 (m-selmi). - Чтение по порядку через JOIN теперь работает и в случае, когда для hash join настроен автоматический порог сброса данных на диск (по умолчанию начиная с 26.5). Если эта оптимизация применяется, JOIN остаётся в памяти и сохраняет порядок левой стороны; чтобы вернуть прежнее поведение, при котором такие JOIN не используются для чтения по порядку и могут свободно сбрасывать данные на диск, установите
query_plan_read_in_order_through_spilling_join = 0. Кроме того,ORDER BY ... LIMITповерхLEFT JOINс чтением по порядку больше не указывает в качестве планируемого числа читаемых строк размер всей таблицы, поэтому чтение с ранней остановкой больше не приводит к срабатываниюmax_rows_to_readприread_overflow_mode = 'throw'. #111973 (alexey-milovidov). - Снова включена оптимизация последовательных ключей для агрегации
TTL ... GROUP BYво время слияний. Агрегатор создавался со значениемmin_chunk_bytes_for_parallel_parsing(порог в байтах, по умолчанию 10 MiB) на месте параметраmin_hit_rate_to_use_consecutive_keys_optimization(доля попаданий в диапазоне[0, 1], по умолчанию 0.5), из-за чего на этом пути оптимизация всегда оставалась отключённой. На результаты это не влияет. #112314 (groeneai). - Отложенная репликация столбцов для
ARRAY JOINбольше не теряется при сериализации плана запроса. Приserialize_query_plan = 1узел, выполняющий удалённый фрагмент плана, ранее игнорировалenable_lazy_columns_replicationи всегда материализовал каждую реплицированную копию, хотя по умолчанию эта настройка включена. #112330 (groeneai). - Условие равенства из предложения
WHEREтеперь объединяется с условиемJOIN, если его операнды имеют разные типы, но общий супертип, напримерInt32иNullable(Int32). Это позволяет преобразовать CROSS JOIN в INNER JOIN. #112630 (m-selmi). - Исправлено квадратичное перераспределение памяти при репликации
Array, элементы которого содержат значенияJSONв общих данных, — например, константного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). - Устранена кубическая сложность планирования запроса для JOIN с таблицей
Mergeповерх множества таблиц с разной структурой. Ранее планирование таких запросов могло занимать минуты, при этом они не реагировали наmax_execution_timeилиKILL QUERY. #113140 (alexey-milovidov). - Исправлена регрессия производительности: агрегация без ключей
GROUP BYпри каждом выполнении сериализовала всё поддерево входного плана, включая полное содержимое свёрнутых константных литералов, ради вычисления ключа кэша размера хеш-таблицы, который она всё равно не может использовать. Запрос видаSELECT quantileMerge(arrayJoin(arrayMap(x -> state, range(5000000))))тратил на оптимизацию плана запроса около 63 мс при каждом выполнении, а теперь — 0,15 мс. #113333 (groeneai). - Операторы агрегации PromQL
topk,bottomkиlimitkтеперь вычисляются с помощью потокового плана, состояние выборки которого занимаетO(time_steps * k), вместо сбора всех серий в одну строку с промежуточным расходом памятиO(time_steps * series^2). Запросы по метрикам с высокой мощностью, которые раньше завершались ошибкойMEMORY_LIMIT_EXCEEDED, теперь выполняются в ограниченном объёме памяти, а вычисление распараллелено, а не выполняется в одном потоке. #113656 (nikitamikhaylov). - Хеш-таблица для каждого бакета в агрегатных функциях
timeSeries*ToGridзаменена плоским отсортированным массивом образцов: для упорядоченных входных данных (а это подавляющее большинство случаев) приём образца сводится к добавлению за O(1), а копирование и сортировка каждого бакета при финализации больше не требуются. #113681 (nikitamikhaylov). - Подвыражения PromQL, общие для нескольких шагов плана (операнд
topk/bottomk/limitk, левая частьor), теперь вычисляются один раз, а не дважды: SQL, генерируемый из PromQL, материализует общие подзапросы. Это избавляет от повторного сканирования таблицы образцов:topkповерхrateпри холодном запуске работает примерно в 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–3 раза коротких запросов с
GROUP BYи тяжелыми состояниями агрегатных функций (например,COUNT(DISTINCT ...), ClickBench Q10/Q11) на машинах с очень большим числом ядер. Регрессия появилась в сборках разработки 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). JOIN, секцияONкоторого содержит несколько равенств, объединенных черезOR, больше не материализует столбцы ключей правой стороны, не выбираемые запросом. #115465 (nickitat).- Ускорено построение хеш-таблицы для
ANY,SEMIиANTIJOIN, когда в правой части одни и те же ключи соединения повторяются многократно: JOIN больше не перечитывает настройкуjoin_any_take_last_rowиз памяти для каждой строки правой части. #115820 (nickitat). - Ускорен
GROUP BYбез агрегатных функций по ключамString,FixedStringиLowCardinality: запрос больше не перезаписывает неиспользуемое значение-заполнитель в хеш-таблицу для каждой строки — только для строк, добавляющих новый ключ. #115834 (nickitat). - Снижено использование памяти и сокращено время оптимизации плана запроса для агрегаций по ключам над большими литералами, полученными в результате свёртки констант. Ключ кэша статистики хеш-таблиц агрегации теперь хешируется непосредственно в процессе сериализации, а не накапливается предварительно в памяти, поэтому план, содержащий большой литерал, больше не хранит его копию во время оптимизации. Для литерала размером 80 МБ пиковое потребление памяти снижается примерно на 250 МБ, а время оптимизации сокращается примерно в 2,5 раза. Вычисляемый ключ при этом не меняется. #115847 (groeneai).
- Оптимизированы запросы
GROUP BY ... ORDER BY ... LIMITиGROUP BY ... LIMIT: во время агрегации поддерживается куча ограниченного размера, что позволяет отсекать группы, которые заведомо не попадут в результат. Это значительно снижает использование памяти и время выполнения при группировке по столбцам с высокой мощностью. Управляется настройкойenable_group_by_top_k_optimization. Основано на первоначальной реализации Dmitriy Terenichev #96630 (thevar1able).
Оптимизация и выполнение запросов
- Чтение в порядке сортировки с параллельными репликами теперь использует ту же логику разбиения таблицы на
max_threadsчастей, что и локальное чтение, что улучшает распараллеливание. #101434 (nickitat). - В модуль чтения Parquet добавлено пространственное отсечение GeoParquet на уровне групп строк и страниц. Отсечение на уровне групп строк пропускает целые группы строк, ограничивающий прямоугольник которых не пересекается с геометрией запроса. Отсечение на уровне страниц использует индекс столбца
covering.bbox, чтобы пропускать нерелевантные страницы внутри групп строк. Кроме того, проталкивание пространственных предикатов обобщено черезIFunctionBase::isSpatialPredicate(), а также добавленGeoFilter, который вычисляет пространственные предикаты во время чтения строк Parquet. #104435 (bacek). - Добавлена настройка
use_constant_folding_in_index_analysis(по умолчанию отключена). Если она включена, анализ первичного ключаMergeTree,MinMaxи индексов пропуска подставляет константы уровня партиции в предикат фильтра отдельно для каждой части, что улучшает отсечение для фильтров, ветви которых зависят от значений партиции, например(a = 1 AND b >= 1) OR (a = 2 AND b > 10)приPARTITION BY a. #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). - Счётчики селективности
system.predicate_statistics_logбольше не обновляются на пути чтения MergeTree, когда эта функциональность отключена (predicate_statistics_sample_rate = 0, значение по умолчанию). Это убирает из каждого чтения атомарное обновление для каждой гранулы и подсчёт битов фильтра со сложностьюO(rows), устраняя регрессию производительности, наиболее заметную на aarch64. #108190 (groeneai). - Добавлена настройка
merge_use_batch_sorting_queueMergeTree, позволяющая использовать очередь пакетной сортировки для обычных слиянийMergeTree. Это сокращает затраты CPU и общее время выполнения для нагрузок, где сортирующее слияние составляет значительную часть затрат. #108468 (rorylshanks). - Ускорено планирование запросов в анализаторе для выражений, которые многократно ссылаются на один и тот же псевдоним
WITHили повторяют одно и то же подвыражение (например, глубоко вложенные цепочкиif/multiIf): общие подвыражения больше не перестраиваются при построении DAG действий. #108523 (novikd). - Ускорен анализ запросов, содержащих много
AND-цепочек сравнений или очень длинные такие цепочки: работа оптимизацииoptimize_and_compare_chainтеперь ограничена бюджетом (новая настройкаoptimize_and_compare_chain_max_hash_work), и она больше не хеширует значительную часть дерева запроса, а при разрешении лямбда-выражений хеши тела лямбды больше не пересчитываются для защиты от рекурсии. #108757 (alexey-milovidov). - Постпроцессоры, выполняющие только фильтрацию (
if(..., '', token)), теперь строят гранулу из исходных токенов и отбрасывают пустые значения на этапе построения. Это позволяет избежать материализации для каждого вхождения и выполненияActionsDAG, характерных для общего пути. #109049 (ahmadov). - Устранено однопоточное узкое место в
ShuffleSendStepраспределённого плана запроса: каждый входящий поток теперь независимо распределяет свои строки по корзинам пункта назначения, а не пропускает весь фрагмент через одинScatterByPartitionTransform. #109206 (davenger). - Снижены накладные расходы CPU на вычисление выражений в запросах с большим количеством столбцов (например, при векторном поиске по столбцу
QBitс малым шагом, когда каждый вектор разворачивается в сотни подстолбцов битовых плоскостей, которые передаются в один вызов*DistanceTransposed). #109380 (alexey-milovidov). - Фильтр теперь проталкивается ниже
LIMIT BY, если предикат ссылается только на столбцы ключаLIMIT BY, а секция сохраняет хотя бы одну строку для каждой непустой группы (LIMIT n BYсn >= 1иOFFSET 0). Благодаря этому такие предикаты (записанные как внешнее предложениеWHEREвокруг подзапроса сLIMIT BY) доходят до хранилища и используются для отсечения по первичному ключу, индексов пропуска данных и проекций — вместо чтения всей таблицы и предварительного вычисления top-N для каждой группы. Семантика исключений дляOFFSET,LIMIT 0 BYи отрицательных формLIMIT BYпри этом не меняется. #110116 (groeneai). - Устранено выделение памяти в куче при каждой проверке гиперпрямоугольника в ходе анализа индекса первичного ключа, что ускоряет фильтрацию засечек на 5–26% в зависимости от вида запроса. #110153 (raimannma).
- Проталкивание фильтров в Parquet (отсечение групп строк и индексы столбцов) теперь поддерживает преобразования между вариантами
DateTime64, вариантамиDecimal, а также междуFloat32иFloat64. #110457 (al13n321). - Оптимизировано построение текстовых индексов пропуска данных и индексов на основе bloom-фильтра с токенизатором sparseGrams #110541 (UnamedRus).
- При упорядочивании условий PREWHERE стоимость операций ввода-вывода теперь учитывается вместе с селективностью. Это устраняет регрессию производительности выполнения PREWHERE, возникавшую в некоторых случаях после https://github.com/ClickHouse/ClickHouse/pull/101275. Часть https://github.com/ClickHouse/ClickHouse/issues/110462 #110695 (Avogar).
- Сокращено хеширование токенов, заданных в фильтре
IN/NOT INпостпроцессора. #111690 (ahmadov). - Функции mapContainsKeyLike, mapContainsValueLike, mapExtractKeyLike и mapExtractValueLike с неконстантным шаблоном регулярного выражения потребляют меньше памяти и работают быстрее при включённой настройке enable_lazy_columns_replication. Шаблон больше не копируется заранее для каждой записи map в момент захвата: копирование откладывается до выполнения внутреннего лямбда-выражения, а память освобождается раньше, поэтому в пике в памяти находится на одну развёрнутую копию шаблона меньше. #111749 (diegomestre2).
- По умолчанию включены (и переведены в статус бета) две функции, связанные с хранением данных на диске: 1)
packed_skip_index_max_bytes = '1M': подпотоки индексов пропуска размером до 1 МиБ теперь записываются в единый архив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>без сканирования данных, если предикат разделяет строки на значения по умолчанию и прочие. Совместимость: флагexact_num_defaultsвserialization.jsonигнорируется более старыми версиями, поэтому части остаются полностью читаемыми после понижения версии; переписывание count применяется только к частям с точными счётчиками, поэтому результаты остаются корректными и для таблиц со смешанными частями. #111816 (Algunenano). - Оптимизация транзитивных условий теперь использует свой дополнительный фильтр только для анализа индексов, если не может применить фильтр целиком. См. настройку
optimize_and_compare_chain. #112076 (yariks5s). - API запросов Prometheus (
/api/v1/query,/api/v1/query_range) экспериментального движка TimeSeries теперь выполняет запросы параллельно, а не в одном потоке. #112108 (nikitamikhaylov). randomHadamardTransformот константного вектора теперь вычисляется один раз, а не для каждой строки. Это ускоряет запросы векторного поиска, которые поворачивают вектор запроса с помощьюrandomHadamardTransformперед сравнением со столбцомQBit. #112921 (alexey-milovidov).- Восстановлено совместное использование множеств задачами частей одной мутации, фильтрующей по
IN (subquery)по столбцу первичного ключа. Настройкаenable_sharing_sets_for_mutationsвключена по умолчанию, однако множество, построенное для анализа первичного ключа, перестало участвовать в общем кэше, из-за чего в таблице с N частями одно и то же множество материализовалось N раз. #112941 (groeneai). - В распределённых планах запросов (
make_distributed_plan)ORDER BY ... LIMIT kтеперь использует отложенную материализацию на каждой реплике: широкие столбцы читаются только для локальных top-k строк этой реплики, а не для всех строк-кандидатов. #113111 (shankar-iyer). - Ускорено планирование запросов при использовании статистики столбцов
uniq_v2. Оценка количества уникальных значений теперь кэшируется, а не пересчитывается при каждом обращении — а при планировании одного запроса таких обращений происходит множество. #113357 (groeneai). - Проталкивание фильтров теперь работает для подстолбцов
Tupleв файлах Parquet и ORC. Предикат видаWHERE tup.1 = 555555дляfile(),s3()илиurl()теперь отсекает группы строк и шаги индекса строк по статистике самого элемента кортежа, а не читает файл целиком. #113383 (groeneai). - Повышена производительность запросов PromQL к движку TimeSeries: внутренний SQL селекторов теперь читает столбцы первичного ключа таблицы сэмплов напрямую (без холостых приведений типов) и проверяет диапазон временных меток до множества идентификаторов серий, благодаря чему «холодные» запросы с большим количеством селекторов выполняются на 30–44% быстрее. #113768 (nikitamikhaylov).
- Селекторы PromQL, которые соответствуют всем сериям одной метрики, теперь при анализе индекса фильтруют таблицу сэмплов таблицы
TimeSeriesпо непрерывному диапазону первичного ключа поid, а не по большому условиюid IN <set>, если структура id представляет собой кортеж из двух компонентов с каноническим генератором id. Это устраняет основные затраты на однопоточный анализ индекса в PromQL-запросах с большим количеством селекторов: задержка при холодном запуске снижается до 45% для запросов дашбордов и правил, а среднее геометрическое холодной задержки на полном наборе тестов для таблицы с 62 миллиардами сэмплов — на 11%. #114131 (nikitamikhaylov). - Эндпоинты Prometheus HTTP API
/api/v1/queryи/api/v1/query_rangeтеперь вычисляют подзапрос PromQL, общий для нескольких шагов плана, только один раз — так же, как это уже делали табличные функцииprometheusQueryиprometheusQueryRange. Ранее запрос, выполненный сenable_analyzer = 0или пользователем, в профиле которого задана эта настройка, повторно сканировал общий подзапрос для каждого ссылающегося на него шага. #114261 (groeneai). - Исправлена регрессия в 26.7: для таблицы
MergeTree, упорядоченной поtoUnixTimestamp(или другому целочисленному преобразованию) столбцаDateTime64, простой фильтр по диапазону этого столбца перестал использовать первичный ключ и читал все гранулы подходящих частей. Кроме того, фильтр видаtoInt64(ts) >= cпо таблице, упорядоченной по исходному столбцуDateTime64, теперь использует первичный ключ. #114413 (alexey-milovidov). - Ускорено выполнение
INдля кластеризованных столбцов (например, отсортированных по первичному ключу): для одинаковых идущих подряд строк повторно используется результат предыдущей строки. #114853 (nikitamikhaylov). - Устранена квадратичная сложность функций
h3kRing,h3ToChildren,h3PolygonToCellsиh3PolygonToCellsWithContainmentпри построении результата для большого числа строк. Во время стресс-теста в CI запрос по 196 000 строкам тратил 838 секунд на копирование памяти; теперь он выполняется примерно за 5 секунд. #115773 (groeneai). - Оптимизирован обратный поиск по словарю. Предикат равенства с константой, например
WHERE dictGet(dict, attr, key_expr) = value, теперь при свёртке констант сразу преобразуется в фильтр по ключу (key_expr = const,key_expr IN [...]илиWHERE 0), а не переписывается в подзапросIN (SELECT ... FROM dictionary(...)); кроме того, веткаdictGetKeysдля константных аргументов теперь выполняется параллельно. #91164 (nihalzp). - Добавлена новая настройка
merge_tree_generic_exclusion_search_max_steps, ограничивающая число шагов, которые универсальный алгоритм поиска с исключением тратит на анализ индекса первичного ключа каждой части данных. Бюджет расходуется в первую очередь на самые большие из оставшихся диапазонов ключей, поэтому даже небольшой бюджет позволяет отсечь основной объём данных; не до конца проанализированные диапазоны читаются целиком, так что результаты запроса остаются корректными, но читаться может больше гранул. Ограничение нестрогое: оно может быть превышено не более чем наmerge_tree_coarse_index_granularityшагов плюс по одному шагу на каждый диапазон, на которые часть уже разделена (например, кэшем условий запроса). Значение по умолчанию 0 означает отсутствие ограничения. #92779 (EmeraldShift). - Запросы с
ORDER BYиLIMITкVIEWповерх распределённых таблиц теперь используют оптимизацию слияния отсортированных потоков. ВнешниеORDER BY/LIMITпроталкиваются во внутренний запрос простого представления, поэтому каждый шард сортирует свои данные локально, а координатор лишь сливает заранее отсортированные потоки, не выполняя полную сортировку у себя. #94102 (matanper).
Производительность хранилища, ввода-вывода и озер данных
- Границы minmax-индекса партиций теперь используются для отсечения большего числа гранул при анализе первичного ключа в таблицах
MergeTree, если столбец первичного ключа также входит в выражение ключа партиционирования. Например, в таблицеMergeTreeсORDER BY (id, event_time)иPARTITION BY toYYYYMM(event_time)ClickHouse будет использовать minmax-индекс партиций поevent_timeпри анализе индекса первичного ключа, чтобы точнее определять, какие гранулы можно отсечь. Управляется новой настройкойuse_partition_minmax_for_primary_key_pruning(включена по умолчанию). #103480 (UnamedRus). - Ускорены операторы, которые сканируют отсортированный поток в поисках последовательностей одинаковых значений ключа:
DISTINCTв порядке сортировки,LIMIT BYв порядке сортировки, отрицательныйLIMIT BYв порядке сортировки, а также соединенияfull_sorting_mergeиpartial_merge. #106502 (nihalzp). - Ридер Parquet v3 теперь может пропускать целые группы строк по странице словаря (в дополнение к статистике min/max и bloom-фильтрам) для условий равенства и
IN, если фрагмент столбца полностью закодирован словарём. Управляется новой настройкойinput_format_parquet_dictionary_filter_push_down. #106952 (alexey-milovidov). - Для сжатия и декомпрессии gzip/zlib/deflate теперь используется libdeflate, что ускоряет работу (сжатие — примерно в 1,15 раза при лучшем коэффициенте, декомпрессия — примерно в 1,4–1,5 раза) для данных
.gz/HTTP/url/s3и кодека Parquet GZIP. #108074 (alexey-milovidov). - Ускорены функции
trimLeft/trimRight/trimBothс пробельными символами по умолчанию (и их псевдонимыltrim/rtrim/trim): идущие подряд строки, не требующие обрезки, копируются одним пакетом, а построчный поиск пробелов выполняется только для строк, в которых действительно есть начальный или конечный пробел. #108177 (groeneai). - Ускорено чтение таблиц Iceberg за счёт предварительной загрузки следующего файла манифеста во время разбора текущего, что позволяет совмещать операции ввода-вывода с вычислениями на CPU. #108543 (asya-ch).
- Запросы векторного поиска с пересчётом оценок теперь вычисляют точные расстояния только для строк-кандидатов, найденных векторным индексом, а не перебирают все соседние строки из той же гранулы
MergeTree. #108846 (skuznetsov). - Добавлена настройка
merge_tree_min_bytes_per_read_stream, позволяющая сократить избыточное число потоков чтения и накладные расходы конвейера при обычном локальном неупорядоченном сканировании узких столбцовMergeTreeна серверах с большим числом ядер. #109035 (jiebinn). - Ускорены сериализация и слияния столбцов
JSON, общие данные которых содержат множество разреженных путей. При развёртывании общих данных в отдельные столбцы для каждого путиflattenAndBucketSharedDataPathsбольше не сканирует все накопленные столбцы путей для каждой строки и не вставляет значения по умолчанию по одной ячейке: построчное сканирование всех путей удалено, а пропуски заполняются массово. #109341 (groeneai). - Нативный протокол теперь передаёт столбцы
Stringв виде отдельного потока накопленных байтовых смещений (та же структура, которуюArrayиспользует для своих смещений), за которым следуют конкатенированные данные, а не с префиксом длины varint для отдельных значений, — при условии, что обе стороны используют ревизию протокола 54489 или новее. Благодаря этому клиент может читать столбцыStringс точным предварительным выделением буфера и одним массовым копированием — примерно в 4 раза быстрее, чем при структуре для отдельных значений. Старых клиентов и серверов это не затрагивает: структура согласовывается через ревизию протокола. Та же структура доступна в форматахNativeиBuffersчерез новые настройкиoutput_format_native_write_string_with_size_stream/input_format_native_read_string_with_size_stream(по умолчанию отключены, чтобы форматы оставались переносимыми). #110320 (vahid-sohrabloo). - Запросы с
FINAL, читающие данные в порядке первичного ключа (ORDER BYпо префиксу ключа сортировки) с небольшимLIMIT, больше не используютsplit_intersecting_parts_ranges_into_layers_final. #110431 (KochetovNicolai). - Отложенная (поздняя) материализация при чтении файлов Parquet из объектного хранилища, включая таблицы Iceberg: в запросах
ORDER BY ... LIMIT nстолбцы, не нужные для сортировки и фильтрации, читаются только дляnстрок, оставшихся послеLIMIT. Для файла Parquet размером 200 МБ в S3 запросSELECT k, s ... ORDER BY k DESC LIMIT 10читает 3,3 МБ вместо 171 МБ (в 51 раз меньше IO, в 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 в Parquet как DECIMAL, что позволяет отсекать группы строк и страницы. #113347 (bobrik).
- Исправлено многократное дублирование запросов на чтение с удалённых дисков в случаях, когда один из шагов цепочки читателей читает фрагментированные диапазоны засечек, например диапазоны, отфильтрованные первичным индексом или индексами пропуска. #113584 (CurtizJ).
- При записи кусков
MergeTree, все ключи сортировки которых константны, больше не выполняется избыточная проверка отсортированности. #113899 (perfloop-agent). - Отложенная материализация для запросов
ORDER BY ... LIMIT nтеперь применяется и к локальным файлам Parquet, читаемым табличной функциейfileи движком таблицFile: столбцы, не нужные для сортировки и фильтрации, читаются только дляnстрок, оставшихся послеLIMIT. Если файл был изменён между двумя проходами, повторное чтение безопасно завершается с новой ошибкойFILE_CHANGED_DURING_READ. Управляется новой настройкойquery_plan_optimize_lazy_materialization_for_file(включена по умолчанию). Также исправлена ошибкаNot found column or subcolumn ... in blockпри отложенной материализации для объектного хранилища, возникавшая, когда чтение запрошенного подстолбца (например, столбцаJSON) откладывалось. #114262 (alexey-milovidov). - Ускорено построение множества для
IN (subquery)на партиционированных таблицахMergeTree: строки каждой партиции теперь обрабатываются в рамках одного потока, а дедупликация выполняется в каждом потоке независимо, поэтому единственное преобразование заполнения множества, которое ранее последовательно хешировало каждую строку, получает только уникальные строки. Это работает, когда выражение партиционирования является детерминированной функцией от выходных столбцов подзапроса. Оптимизация не применяется, если в самой крупной партиции более чем вдвое больше строк, чем в средней; новая настройкаforce_creating_set_partitions_independently(по умолчанию отключена) позволяет обойти эту проверку. Управляется новой настройкойallow_creating_set_partitions_independently(по умолчанию включена). #114645 (nihalzp). - Ротированные нереплицируемые системные таблицы логов
MergeTreeбез TTL теперь помечаются какtable_readonly, чтобы избежать лишних фоновых операций. Настройкаtable_readonlyMergeTreeтеперь также отключает всю фоновую работу для обычной таблицыMergeTree— обычные слияния, слияния по TTL (DELETE/MOVE/повторное сжатие) и слияния с повторным сжатием, фоновые мутации и фоновые перемещения частей — и отклоняет изменяющие команды для партиций (ATTACH/MOVE/DROP/DROP DETACHED/FETCH/REPLACE PARTITIONиMOVE PARTITION ... TO TABLEв эту таблицу) — в дополнение к вставкам, мутациям иOPTIMIZE, которые отклонялись и ранее. Поэтому таблицаtable_readonlyс TTL, пока настройка включена, больше не удаляет данные с истёкшим сроком хранения и не освобождает занимаемое ими место. #95079 (matt-metivier).
Эффективность использования памяти и ресурсов
- Снижено использование памяти командой
UNLOCK SNAPSHOT: метаданные отдельных частей данных, которые не нужны при снятии блокировки, больше не загружаются. Это предотвращает нехватку памяти при работе со снимками, содержащими очень большое количество частей. #111849 (jkartseva). - Сокращено число операций выделения памяти при чтении метаданных резервной копии: каждая запись о файле теперь не копируется, а перемещается в хранящиеся в памяти отображения (map). #111718 (jkartseva).
Производительность функций, типов данных и форматов
- Форматирование значений
Decimalв текст стало значительно быстрее — до 190 раз дляDecimal256с большим масштабом и примерно в 1,6 раза дляDecimal64. На процессорах с поддержкой AVX-512 IFMA преобразование 64-битных целых чисел в текст ускорено примерно в 1,4 раза. Также исправлено округление вtoDecimalString, при котором терялся перенос из дробной части:toDecimalString(toDecimal64('9.995', 3), 2)возвращала9.00, а теперь возвращает10.00. #112457 (thevar1able). - Повышена производительность алгоритма JOIN
partial_mergeдля ключей типаFixedString: теперь последовательности значений сравниваются за один раз, а не отдельным вызовом сравнения для каждого значения. #105737 (4ertus2). - В
HashJoinтеперь нативно поддерживаются ключи из одного не-Nullable строкового столбца типа LowCardinality. #107264 (nickitat). - Повышена производительность
replaceAllиreplaceRegexpAll, когда шаблон и замена состоят из одного символа (например,replaceRegexpAll(s, ' ', '_')). Такие замены больше не меняют байтовую структуру строк, поэтому столбец теперь копируется один раз, а совпадающие байты перезаписываются на месте — без цикла поиска для каждого совпадения. #108178 (groeneai). - Ускорен разбор канонического представления даты и времени
YYYY-MM-DD hh:mm:ssв режиме best-effort (date_time_input_format = 'best_effort',cast_string_to_date_time_mode = 'best_effort'), который используется по умолчанию. Это устраняет регрессию производительности разбора, возникшую после смены значений по умолчанию сbasicнаbest_effort. #108187 (groeneai). - Разбор глубоко вложенных литералов массивов и кортежей теперь выполняется за линейное, а не за квадратичное время. #108892 (alexey-milovidov).
- Функция
toStartOfInterval(псевдонимыtime_bucket,date_bin) ускорена до 5 раз для интерваловSECOND,MINUTEиHOUR. #109729 (raimannma). - Функции
arraySortиarrayReverseSortпри вызове без лямбда-выражения работают в несколько раз быстрее с числовыми массивами (включаяDecimalиDateTime64). #109832 (raimannma). - Ускорены
addDays,addWeeks,subtractDaysиsubtractWeeksдля значенийDateTimeиDateTime64в часовых поясах с фиксированным смещением (например, UTC) за счёт быстрого арифметического пути. #109836 (raimannma). - Декомпрессия кодека
Deltaвекторизована. Декодирование теперь выполняется в 1,5–5 раз быстрее для 8/16/32-битных типов данных, а сканирование столбцов, сжатых с помощьюDelta, — до 20% быстрее. #110189 (raimannma). - Ускорены функции поиска в строках (
like,position,match,countSubstrings,hasTokenи др.) по столбцамEnumс константной искомой строкой: теперь поиск выполняется не по каждой строке, а только по уникальным именам значений enum, после чего результаты сопоставляются с каждой строкой. #110325 (alexey-milovidov). - Производительность функций поиска подстрок (
position,countSubstrings,multiSearch*,replaceAll/replaceOne, а также их регистронезависимых вариантов и вариантов для UTF-8) с непостоянным аргументом needle выросла до 1,5 раза: теперь при построчной обработке вместо наивного резервного варианта используются алгоритмы поиска строк на основе SIMD. #110580 (Algunenano). - Улучшена производительность объединения блоков (squashing) и слияния столбцов
DynamicиObjectс большим количеством динамических вариантов или JSON-путей. #110583 (cv4g). - Ускорена работа
estimateCompressionRatioс кодекомNONE#111107 (rienath). - Ускорены сортировка и другие операции на основе сравнения для JSON-столбцов, пути которых хранятся в общих данных. Ранее при каждом сравнении значений создавался временный столбец
Dynamicи выполнялась полная двоичная десериализация обоих операндов, из-за чегоORDER BYпо таким столбцам работал крайне медленно. #111894 (groeneai). - При делении 256-битных целых чисел (
Int256,UInt256иDecimal256) частное теперь вычисляется не побитово, делением столбиком методом сдвига и вычитания, а по одному 64-битному разряду (limb) за шаг: с помощью цикла делений 128 / 64, если делитель помещается в 64 бита, и с помощью алгоритма D Кнута в остальных случаях. Это затрагиваетintDiv,modulo, арифметикуDecimal256и преобразование этих типов в текст. #112477 (thevar1able). - При чтении столбца
Nestedиз типа в двоичной кодировке (Native,RowBinaryсinput_format_binary_decode_types_in_binary_format) тип больше не преобразуется обратно в имя типа с последующим повторным разбором. Кроме того, для некорректного имени вложенного типаTupleтеперь сразу выдаётся синтаксическая ошибка — вместо разбора, время которого росло экспоненциально с глубиной вложенности и завершалось ошибкойTOO_SLOW_PARSING. #112560 (alexey-milovidov). - Ускорены запросы PromQL к таблицам TimeSeries: если у последовательных строк совпадает id серии,
timeSeriesIdToGroupтеперь повторно использует группу предыдущей строки, не выполняя построчную сериализацию id и поиск в хеш-таблице. #113580 (nikitamikhaylov).
Другие улучшения производительности
- Реализованы нативные средства чтения и записи для форматов
ArrowиArrowStream, не использующие библиотеку Apache Arrow, что позволяет избежать лишних копирований и преобразований данных. Теперь они используются по умолчанию (настройкиinput_format_arrow_use_native_readerиoutput_format_arrow_use_native_writer) и работают быстрее как при чтении, так и при записи. #106522 (alexey-milovidov). - Оптимизированы предикаты вида
nullIf(key, sentinel) = const: теперь для них строятся диапазоны ключей, что позволяет выполнять отсечение по первичному ключу, партициям и индексам пропуска данных. #107308 (adityaksolves). - Производительность `INTERSECT ALL` и `EXCEPT ALL` (режим по умолчанию для `INTERSECT` и `EXCEPT`) выросла в несколько раз: ключом мультимножества теперь служит само значение строки, а не хеш SipHash каждой строки. #107649 (Algunenano).
- Ускорены функции
match,extract,extractAll,replaceRegexpOneиreplaceRegexpAllдля простых регулярных выражений за счёт их компиляции в нативный код с помощью LLVM. Поведение управляется новой настройкойcompile_regular_expressions(включена по умолчанию); шаблоны, выходящие за рамки поддерживаемого подмножества, незаметно для пользователя обрабатываются движком RE2. #108004 (alexey-milovidov). - Ускорена декомпрессия ZSTD на AArch64 (ARM) для столбцов с малыми смещениями совпадений, например целочисленных столбцов фиксированной ширины, за счёт векторизации перекрывающихся копирований с коротким смещением с помощью NEON. Так, декомпрессия столбца
UInt64на AWS Graviton 4 выполняется до ~2,3 раза быстрее. #108049 (alexey-milovidov). - Повышена скорость декомпрессии LZ4 для столбцов фиксированного размера с низкой мощностью. #108175 (nickitat).
- Повышена производительность
levenshteinDistance(иeditDistance) для строк средней длины на ARM за счёт отказа от выделения памяти в куче для каждой строки в блочной реализации алгоритма Майерса. #108185 (groeneai). - Ускорен разбор чисел с плавающей запятой из текста при
precise_float_parsing = 1: теперь почти на всех входных данных он работает не медленнее парсера по умолчанию. Кроме того, встроенная библиотекаfast_floatобновлена до версии v8.2.10. #108205 (Algunenano). - Функции кодирования и декодирования Base64 теперь используют
simdutf, что повышает их производительность. #108333 (thevar1able). - Оптимизирован
DISTINCTдля ресурсоёмких ключей с высокой мощностью. #108366 (nihalzp). - Повышена производительность математических функций за счёт включения оптимизаций компилятора, не сохраняющих
errno. #108628 (nickitat). - Ускорена функция
estimateCompressionRatioдля столбцов с кодированиемT64: сжатый размер теперь вычисляется аналитически, без фактического сжатия. #109054 (rienath). - JOIN теперь может использовать индекс первичного ключа или индекс пропуска данных левой таблицы для отсечения гранул #109085 (shankar-iyer).
- Повышена производительность геофункций H3 (
h3ToGeoBoundary,h3ToGeo,h3CellAreaM2/h3CellAreaRads2,geoToH3): синус и косинус теперь вычисляются совместно, а избыточные тригонометрические вызовы при преобразовании координат устранены. Результаты не изменились (побитово идентичны). #109399 (alexey-milovidov). - Сравнения (
<,>,<=,>=) широких целочисленных типов (Int128,UInt128,Int256,UInt256и основанных на них типов, напримерDecimal128) ускорены до 7 раз, а преобразование знаковых целых чисел вInt256— до 7 раз на данных со смешанными знаками. Это достигнуто за счёт устранения ветвлений в коде сравнения и знакового расширения. #109474 (raimannma). - Функции с единственным неконстантным аргументом типа
Nullableтеперь используют null map аргумента совместно с результатом, а не выделяют память под новую карту с последующим слиянием. #110151 (raimannma). - Функции
arrayMinиarrayMaxдля числовых массивов ускорены примерно в 1,3–1,5 раза благодаря векторизованной редукции вместо поэлементного цикла сравнения. #110163 (raimannma). - Повышена производительность
DISTINCTв случаях, когда входной поток отсортирован по префиксу столбцов DISTINCT, напримерSELECT DISTINCT a, b FROM table ORDER BY a. Такие запросы выполняются до 2,4 раза быстрее. #110170 (nihalzp). - Добавлена векторизованная пакетная обработка для
groupBitOr/groupBitAnd/groupBitXorи семейства функций дисперсии (varPop,varSamp,stddevPop,stddevSamp,skewPop,skewSamp,kurtPop,kurtSamp,covarPop,covarSamp,corr): ускорение до 4 раз с комбинатором-Ifпри непредсказуемых условиях и до 3 раз для семейства функций дисперсии без него. #110461 (raimannma). - Оптимизирован анализ текстового индекса. #110530 (CurtizJ).
- Ускорен разбор значений
UUIDиз текста (например,JSONExtractвLowCardinality(UUID),toUUID,CAST AS UUID): проверка и преобразование шестнадцатеричных цифр теперь выполняются за один проход вместо двух. #110625 (groeneai). - Ускорена декомпрессия ZSTD на x86_64 для столбцов с небольшими смещениями совпадений (например, целочисленных столбцов фиксированной ширины) за счёт векторизации перекрывающихся копирований с короткими смещениями с помощью SSSE3
pshufb(аналог для x86_64 оптимизации AArch64 NEON из #108049). #110909 (thevar1able). - Функция
groupUniqArrayдля числовых типов ускорена до 3 раз за счёт хеширования CRC32 (как вuniqExact) и встраивания построчной вставки. #110917 (raimannma). - Повышена эффективность minmax и базовой статистики столбцов для столбцов с плавающей запятой. #111221 (cv4g).
- Запросы
COUNT()теперь выполняются напрямую по метаданным мощности текстового индекса. #111494 (ahmadov). - Ускорены функции
minиmaxдля 128- и 256-битных типов (Int128,UInt128,Int256,UInt256,Decimal128,Decimal256): до 1,8 раза быстрее для широких целых чисел и до 3,4 раза быстрее для широких десятичных чисел. #111965 (raimannma). - Исправлено снижение производительности при записи в
system.query_log. Построение столбцов типа MapSettingsиasynchronous_read_countersвыполнялось примерно в 6 раз медленнее, чем раньше, из-за чегоSYSTEM FLUSH LOGS query_logмог превышать тайм-аут в 180 секунд на серверах, которые логируют много запросов с большим количеством изменённых настроек. #112210 (groeneai). - Добавлено необязательное кэширование токенов, отсутствующих в текстовых индексах. #112742 (rorylshanks).
- Асинхронное логирование теперь использует ограниченную очередь без блокировок: потоки, записывающие сообщения лога, никогда не блокируются на мьютексе и не пробуждают потоки логирования. #112803 (alexey-milovidov).
- Индекс первичного ключа теперь используется для
pointInPolygon, если аргумент-точка представляет собой целый столбец ключа типаPoint(или другойTupleиз двух числовых элементов), напримерpointInPolygon(coord, [...])для таблицы, упорядоченной поcoord. Ранее анализировалась только формаpointInPolygon((x, y), [...])с двумя скалярными столбцами ключа. #112956 (alexey-milovidov). - Значение
text_index_posting_list_apply_modeпо умолчанию теперьlazy: запросы к текстовому индексу декодируют списки вхождений по требованию с помощью курсора с гранулярностью упакованных блоков, а не материализуют их заранее в битовые карты для текстовых индексов с заданнымposting_list_codec. #113521 (CurtizJ). - Ускорены векторизованные преобразования тегов TimeSeries: переназначение на основе хеширования заменено прямой индексацией, если ID групп тегов занимают компактный диапазон. #114244 (fallintoplace).
- Повышена производительность слияний текстовых индексов. #114525 (CurtizJ).
- Для операторов над множествами в PromQL теперь используются компактные маски присутствия. #115224 (fallintoplace).
- При подключении системных таблиц метаданные каждой таблицы, включая полное описание столбцов, больше не копируются дважды лишь для того, чтобы задать комментарий к таблице. #115490 (thevar1able).
- Ускорены проверки на дублирование серий для полностью нулевых векторов условий PromQL. #115822 (fallintoplace).
- Ускорены
toUTCTimestamp/to_utc_timestampиfromUTCTimestamp/from_utc_timestampдля аргументовDateTime64: восстановлена пропускная способность, утраченная после прежних исправлений переполнения. Результаты не изменились. #115838 (groeneai). - Снижены фиксированные накладные расходы на подготовку к генерации случайных данных (
rand,rand64,randomString,randomFixedString,generateUUIDv4,generateUUIDv7) на x86-64. Эффект заметен при небольших блоках; генерируемые значения не изменились. #116158 (Algunenano). - Теперь с помощью настройки
enable_function_early_short_circuitможно включить раннее свёртывание встроенных функцийandиorпо принципу сокращённого вычисления на этапе анализа. Это позволяет пропускать выполнение «мёртвых» однострочных скалярных подзапросовcount(), сохраняя при этом обычный вывод типов и семантическую проверку. #83505 (fhw12345). - Для тривиально сериализуемых векторов теперь выполняется один вызов IO для буфера. #89842 (Ergus).
- Настройка
optimize_or_like_chainтеперь включена по умолчанию. #94517 (alexey-milovidov). - Ускорено получение записи отдельного пользователя из system.users, когда на сервере много пользователей. #96699 (alistairjevans).
Улучшения
Улучшения запросов и SQL
- Materialized CTE, на которые ссылаются несколько ветвей запроса
UNION, теперь материализуются один раз и используются всеми ветвями совместно. Ранее каждая ветвь получала собственную копию CTE, которая встраивалась и вычислялась отдельно. #102107 (novikd). - JOIN runtime filter не применяется, если зондирующая (probe) сторона, по оценке, невелика. Порог задаётся новой настройкой
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). - Если
INSERTзавершается ошибкой из-за того, что целевая таблицаTOmaterialized view отклоняет запись на этапе построения конвейера вставки (например, если целевой объект являетсяViewили не поддерживает транзакции), в сообщении об ошибке теперь указываются materialized view и её целевая таблица, а не только исходная ошибка хранилища. #107234 (groeneai). ALTER TABLE ... MODIFY COLUMN <col> Tuple(...)для именованногоTupleтеперь изменяет только метаданные, если добавляются лишь подполя, и выполняется так же быстро, какADD COLUMNверхнего уровня. Включается с помощьюSET allow_metadata_only_named_tuple_alter = 1. #107305 (amosbird).- Для движка баз данных
MaterializedPostgreSQLдобавлена настройкаmaterialized_postgresql_use_extended_date_and_time_types, задаваемая при создании базы данных. По умолчанию (настройка включена) для столбцов PostgreSQLdate/timestampвыводятся типыDate32/DateTime64; если приCREATE DATABASEзадать значение0, будут выводиться более узкие типыDate/DateTime. Настройка неприменима к движку таблицMaterializedPostgreSQL. #107428 (alexey-milovidov). EXPLAIN PLANтеперь помечает оценку числа строк результата JOIN как приблизительную (~~...), если она получена из подсказки или случайного резервного значения, а не из статистики таблицы. Это помогает выявлять планы, для которых нет надёжной статистики для переупорядочивания JOIN. #107666 (vdimir).INSERTв таблицуMergeTreeтеперь учитывает отмену запроса иmax_execution_timeпри записи большого количества кусков и больше не продолжает выполняться долгое время после принудительного завершения. #107929 (al13n321).arrayFoldтеперь учитывает отмену запроса иmax_execution_time. Ранее свёртка очень длинного массива (например,arrayFold(acc, x -> arrayPushFront(acc, x), range(number), emptyArrayUInt64())) целиком выполнялась внутри одного вызова функции и не могла быть прервана, поэтомуKILL QUERYи ограничения по времени игнорировались до завершения свёртки. #108192 (groeneai).- Добавлены
ProfileEventsдля отдельных этапов подготовки запроса к выполнению:QueryParseMicroseconds,QueryAnalysisMicroseconds,QueryPlanBuildMicrosecondsиQueryPipelineBuildMicroseconds. Они показывают, на что уходит время до выполнения запроса (разбор, анализ, построение плана запроса, построение конвейера), и доступны вsystem.query_logиsystem.events. #108282 (jrdi). - Операции
ALTER TABLE, в результате которых метаданные таблицы превысили быmax_query_size, теперь отклоняются заранее. Это не позволяет таблицам оказаться в состоянии, когда их не могут загрузить такие компоненты, как распространение DDL и восстановление реплик. #108283 (lockie). - Добавлен
ConstantJoinдля декартовых JOIN и JOIN с константными предикатами, планируемых анализатором, поэтому такие запросы больше не завершаются ошибкой из-за несовместимого значения настройкиjoin_algorithmпри использовании анализатора. #108289 (antaljanosbenjamin). - В
system.documentationдобавлен столбецsource, содержащий путь к исходному файлу, в котором определена документация каждой сущности. Теперь таблица также документирует кодеки сжатия, события профилирования, текущие метрики, асинхронные метрики и сами системные таблицы (вместе с их столбцами), а в документацию настроек добавлены их тип и значение по умолчанию. #108346 (alexey-milovidov). - Если в предложении WHERE указаны фильтры по
tableиdatabase, тоsystem.iceberg_historyвыведет только соответствующие им базы данных. Это может сэкономить время, если на сервере много посторонних удалённых баз данных. #108492 (Diskein). - Параметры запроса (подстановки
{name:Type}) теперь можно использовать в качестве значений настроек — как в предложенииSETTINGSзапроса (например,SELECTилиINSERT), так и в отдельных запросах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, тогда как при двух и более CTEWITHвыносился на отдельную строку, а каждый CTE выводился с отступом. #109092 (groeneai). - Добавлена поддержка кэша условий запроса для локальных файлов Parquet, читаемых через табличный движок
File(ранее она была доступна только для объектного хранилища и озёр данных). #109247 (alexey-milovidov). - Ключ кэша условий запроса для удалённых файлов Parquet (в объектном хранилище) теперь включает ETag в дополнение к пути, поэтому перезапись объекта на месте больше не приводит к выдаче устаревших результатов из кэша. #109310 (alexey-milovidov).
- Неквалифицированная ссылка на ключ
INNER JOIN, приравниваемый в условииON(например,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). - Добавлена проверка того, что распределённый запрос всегда содержит известную версию клиента: вместо того чтобы молча передавать удалённым шардам нулевую версию, выбрасывается логическая ошибка. Запросы, инициированные сервером (фоновые сбросы на диск, потребители стриминга, перезагрузка словарей, сброс асинхронных вставок), теперь передают в качестве версии инициатора собственную версию сервера. #109408 (alexey-milovidov).
- Исправлено использование квалифицированных имён столбцов в предложении WHERE операции мутации для движков таблиц семейства MergeTree. #109491 (Michicosun).
- Добавлена поддержка оконных функций без партиционирования (
OVER (ORDER BY ...)) в распределённых планах запросов (make_distributed_plan). Ранее любой запрос с оконной функцией завершался ошибкой, посколькуWindowStepневозможно было сериализовать для удалённого выполнения; окна сPARTITION BYпока по-прежнему не поддерживаются. #109802 (VighneshPath). - Теперь некоторые настройки аутентификации каталога one-lake можно изменить с помощью
ALTER DATABASE ... MODIFY SETTING = 'xxx'. #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), а также состояние, специфичное для алгоритма, например объём памяти хеш-таблицы и сброс данных на диск. Чтобы собирать метрики совпадений, требующие дополнительного учёта, используйтеmatches = 1. #110892 (Fgrtue).- Исправлена ошибка heap-use-after-free в исполнителе конвейера, которая могла приводить к аварийному завершению сервера, если запрос удалял процессоры во время выполнения (например,
FINALс ленивым чтением или внешней сортировкой). Ошибка обнаружена AST-фаззером. #111017 (groeneai). - Исправлена ошибка use-after-free (ошибка сегментации), возникавшая, когда запрос с общим снимком хранилища (настройка
enable_shared_storage_snapshot_in_query) удалял части данных из снимка — например, если потоковый подзапрос читал ту же таблицуMergeTree, которую одновременно читала другая часть запроса. #111192 (alexey-milovidov). - Добавлена поддержка распределённых планов запросов (
make_distributed_plan) для запросов, источник которых уже на этапе планирования заведомо не возвращает строк, например при чтении из пустой таблицыMergeTree. Ранее такие запросы завершались ошибкойSUPPORT_IS_DISABLED. #111941 (groeneai). - Исправлена ошибка, из-за которой кэш условий запроса не заполнялся для гранул, отсеянных любым конъюнктом, кроме последнего, в предложении
WHEREс несколькими условиямиAND. #112083 (shankar-iyer). - Снижено пиковое потребление памяти при записи JSON-столбцов с бакетной сериализацией общих данных (map_with_buckets и advanced): теперь при записи общие данные разбиваются на бакеты поочерёдно, а не материализуются все бакеты одновременно. Наибольший выигрыш это даёт для столбцов Array(JSON). Для скалярного JSON общие данные разбиваются по гранулам (с ограничением index_granularity_bytes), поэтому экономия невелика, тогда как одна гранула Array(JSON) может содержать множество вложенных строк и, соответственно, большой объём общих данных — здесь поочерёдное разбиение по бакетам заметно снижает пиковое потребление памяти #112172 (Avogar).
- Планирование резервирования памяти (экспериментальная функция) больше не вытесняет выделение памяти, если ожидаемое освобождение памяти обеспечит место, необходимое для увеличения резервирования сверх лимита: решение о вытеснении теперь принимается только после применения уже выполняющихся уменьшений. Это позволяет избежать лишнего завершения запросов при нехватке памяти. #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для отдельного столбца — также можно указывать в любом порядке. При этомSETTINGSдля отдельного столбца вADD COLUMNи объявленныеSTATISTICSвADD COLUMN/MODIFY COLUMNтеперь применяются, а не отбрасываются без предупреждения, аCOLLATEиPRIMARY KEYв этих командахALTERтеперь приводят к исключению, а не игнорируются молча. #112788 (alexey-milovidov). - Запрос к таблице
Merge(или к табличной функцииmerge), охватывающий множество таблиц, теперь реагирует наKILL QUERYиmax_execution_timeещё во время построения планов запросов для отдельных таблиц, а не только после завершения планирования всех дочерних таблиц. #113415 (alexey-milovidov). SELECTиз таблицыMerge, превысившийmax_execution_timeприtimeout_overflow_mode = 'break', теперь прекращает построение планов запросов для оставшихся подходящих таблиц, а не выполняет перед остановкой полный анализ запроса для каждой из них. Как и предусмотрено документацией этого режима, запрос по-прежнему завершается без ошибки. #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.JOIN, секцияONкоторого содержит только условия неравенства (два сравнения<,<=,>,>=между выражениями соединяемых таблиц), теперь выполняется алгоритмом IEJoin на основе сортировки вместоCROSS JOINс фильтром; также поддерживаются соединенияLEFT/RIGHT/FULL/SEMI/ANTIс такими условиями. Посколькуie_joinстоит в списке последним, он используется только тогда, когда остальные алгоритмы неприменимы. #114327 (vdimir).- Контекст трассировки OpenTelemetry теперь передаётся в файберы, используемые для асинхронного установления соединений и удалённого выполнения запросов (hedged requests,
async_socket_for_remote,async_query_sending_for_remote). Спаны удалённых запросов в распределённом запросе теперь корректно становятся дочерними по отношению к спануConnection::sendQueryинициатора, а не привязываются напрямую к контексту трассировки, переданному клиентом. Кроме того, каждое выполнение асинхронной задачи порождает собственный спан. #114813 (diegomestre2). DROP DATABASEтеперь удаляет таблицы в обратном топологическом порядке с учётом как зависимостей загрузки, так и ссылочных зависимостей (ранее учитывались только зависимости загрузки), поэтому сбой посреди выполненияDROP DATABASEуже не может оставить таблицу, зависимости которой уже удалены. #114952 (alexey-milovidov).- Добавлена поддержка операторов сопоставления с регулярным выражением в стиле PostgreSQL:
~(псевдоним функцииmatch),~*(регистронезависимое сопоставление),!~и!~*(отрицания). Команды\d,\dt,\dvутилитыpsqlтеперь работают при подключении к ClickHouse по протоколу совместимости с PostgreSQL, а неудачный запрос больше не разрывает соединение. #115066 (alexey-milovidov). EXPLAIN WHATIFтеперь сообщает, почему эмпирическая оценка была пропущена: причина выводится в новой строкеempirical_reason, еслиempirical_statusимеет значениеunsupported. #115140 (yariks5s).- Если ни один из алгоритмов JOIN, включённых настройкой
join_algorithm, не может выполнитьJOIN, сообщение об ошибке теперь перечисляет опробованные алгоритмы, а также строгость и тип JOIN, который не удалось выполнить, а не просто сообщает, что ни один из алгоритмов не сработал. #115226 (elkinal). - Запросы векторного поиска теперь могут использовать индекс векторного сходства, если опорный вектор задан литералом целочисленного массива, например
ORDER BY L2Distance(vec, [1, 2]). Ранее такие запросы без предупреждения переходили к полному перебору. #115255 (rschu1ze). BACKUPбольше не оставляет файл блокировки в пункте назначения, если создавшая его попытка завершается неудачей до записи каких-либо данных — будь то при захвате пункта назначения или при открытии архива. Такую блокировку не могла подхватить ни одна последующая резервная копия, поэтому все повторные попытки в тот же пункт назначения завершались ошибкой, пока файл не удаляли вручную. Кроме того, при резервном копировании в пункты назначенияS3иAzureблокировка теперь создаётся эксклюзивно, а если блокировка принадлежит другой резервной копии, об этом сообщается как о параллельном резервном копировании, а не как о произвольной ошибке, возвращённой хранилищем. #115387 (jkartseva).- Трассировка, запущенная в результате сэмплирования (
opentelemetry_start_trace_probability), теперь записывается обратно в клиентскую информацию запроса, поэтому удалённые и распределённые вторичные запросы, а также записи DDL присоединяются к той же трассировке, а не создают отдельные. #115619 (diegomestre2). - Исправлена работа
CREATE TABLEдля таблиц Iceberg на базе Amazon S3 Tables, где расположением таблиц управляет сам сервис. #115652 (scanhex12). - Адаптивная агрегация
GROUP BY(enable_adaptive_aggregator) теперь оценивает, окупается ли откладывание редких ключей, и возвращается к обычному алгоритму, если ключи или аргументы агрегатных функций слишком широки, чтобы их копирование было выгодным. Благодаря этому агрегации по тяжёлым строковым столбцам (например,min(URL)для каждого пользователя) выполняются со скоростью и потреблением памяти обычного алгоритма. Добавлена настройкаadaptive_aggregator_freeze_threshold_bytes, ограничивающая размер замороженной таблицы каждого потока в байтах (таблица замораживается при достижении любого из двух порогов — этого или порога по количеству ключей, — в зависимости от того, какой будет достигнут первым). #115755 (nihalzp). - Добавлена настройка
query_plan_aggregation_bucket_top_k(включена по умолчанию), которая включает и отключает оптимизацию плана, материализующую толькоnлучших групп каждого двухуровневого бакета, когда результаты финальной агрегации передаются вORDER BYпо её выходным столбцам сLIMIT n. Эта оптимизация теперь также отображается в выводеEXPLAIN. #116124 (nihalzp). - Улучшена поддержка запроса
DESCRIBEдля параметризованных представлений. В новом анализаторе добавлена поддержка параметризованных представлений в скалярных выражениях. #68978 (novikd). - Запросы вида
SELECT * FROM t WHERE idтеперь используют индекс пропуска данных для столбцаid. #89603 (adityachopra29). - Добавлена настройка
query_plan_merge_expression_into_join, которая позволяет объединять шаги Expression с шагами JOIN при оптимизации переупорядочивания JOIN. Благодаря этому переупорядочивание JOIN становится возможным и для подзапросов, внутри которых находятся соединения (например, когда JOIN расположен в подзапросе с вычисляемыми столбцами), что улучшает оптимизацию сложных деревьев соединений. #98533 (vdimir). - В таблицу
system.grantsдобавлен столбецis_wildcard, который показывает, использует ли привилегия сопоставление по префиксу с подстановочным шаблоном (например,GRANT SELECT ON db*.*). Ранее вsystem.grantsнельзя было отличить привилегии с подстановочным шаблоном от точных привилегий с тем же именем. #98577 (il9ue).
Функции и типы данных
- Добавлена новая настройка
allow_lossy_numeric_supertype(по умолчанию отключена). Если она включена,if,multiIf,coalesce,ifNull,arrayиmapнад числовыми аргументами, у которых нет общего типа без потери точности (например,DecimalиFloat64илиInt64иFloat64), приводятся к числовому супертипуFloat64, а не кVariant, поэтому результат можно использовать с агрегатными функциями, такими как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). - Добавлена настройка
input_format_json_max_object_sizeдля ограничения размера объекта JSON при разборе. #107669 (Avogar). - Исправлена утечка памяти, возникавшая при неудачной попытке открыть базу данных SQLite (например, когда табличной функции
sqliteили движку баз данныхSQLiteпередаётся путь, который невозможно открыть). #107807 (alexey-milovidov). - Добавлена поддержка функции
lengthдля типа данныхQBit. Она возвращает размерность вектора в виде константы. #108071 (alexey-milovidov). - Добавлена поддержка
CASTизQBitвArrayс восстановлением исходного вектора. Это преобразование, обратное уже существующему преобразованиюArrayвQBit. #108072 (alexey-milovidov). - Движок баз данных, движок таблицы и табличная функция
MySQLтеперь сопоставляют пространственные типы столбцов MySQL (LINESTRING,POLYGON,MULTILINESTRING,MULTIPOLYGONи обобщённыйGEOMETRY) с соответствующими геометрическими типами ClickHouse вместоString. Это поведение управляется новым флагомgeometryнастройкиmysql_datatypes_support_level, который включён по умолчанию.POINTпо-прежнему всегда преобразуется вPoint. Обобщённый столбецGEOMETRYсопоставляется с объединяющим типомGeometry; при чтении значения, подтип которого не имеет аналога в ClickHouse (MULTIPOINT,GEOMETRYCOLLECTION), генерируется исключение. #108944 (alexey-milovidov). - Теперь по умолчанию используется точный алгоритм разбора чисел с плавающей точкой (с выбором ближайшего представимого значения), а настройка
precise_float_parsingприменяется к входным форматам (CSV, TSV, JSON, VALUES, …) и числовым литералам, а не только кtoFloat*/CAST. Чтобы вернуть прежнее поведение — в некоторых случаях более быстрое, но менее точное, — установитеprecise_float_parsing = 0. #109086 (Algunenano). - Добавлена поддержка
reinterpretмассиваArrayиз элементов фиксированного размера какString— операции, обратной уже существующемуreinterpretзначенияString/FixedStringкакArray. #109383 (alexey-milovidov). - Разрешено выполнять
CASTмежду типамиQBit, которые различаются типом элементов и/или параметром stride, при условии что размерность остаётся прежней (например,CAST(x AS QBit(Float64, N))изQBit(Float32, N)). Изменение только stride происходит без потерь; при изменении типа элементов действует та же семантика, что и при соответствующем преобразованииArray(например, при преобразованииFloat32вBFloat16возможна потеря точности, аaccurateCast/accurateCastOrNullотклоняют строки, которые невозможно представить точно). #109387 (alexey-milovidov). - Функции
quantizeBFloat16ToInt8иdequantizeInt8ToBFloat16теперь, помимо существующих скалярных перегрузок, принимают аргументы типовArrayиQBit, применяя кодек Ллойда — Макса ко всему вектору (и возвращаяArray/QBitс соответствующим типом элементов). #109398 (alexey-milovidov). - Спецификатор формата
%fв стиле MySQL вparseDateTime/parseDateTime64(и их вариантахOrZero/OrNull) теперь принимает от 1 до 6 цифр дробной части вместо ровно 6; они интерпретируются как микросекунды с выравниванием по левому краю, как вSTR_TO_DATEв MySQL. Также исправлено смещение таблицPrettyCompactв примерах встроенной документации функций. #109421 (alexey-milovidov). - Подстатистика
NullCountстатистикиbasicпереименована вDefaultCount: вместо подсчёта строк со значениемNULLв столбце типаNullableфункцияbuildтеперь подсчитывает строки, равные собственному значению по умолчанию для типа столбца, с помощьюIColumn::getNumberOfDefaultRows. #109977 (hanfei1991). - Размер исполняемого файла уменьшен примерно на 10,5 МБ: операции сравнения и арифметические операции над редко используемыми парами смешанных типов (
Decimalи целое число другой разрядности, а также пары с участиемInt128/UInt128/Int256/UInt256) теперь выполняются через преобразование к общему типу, а не с помощью отдельного скомпилированного ядра для каждой комбинации типов. Пары одинаковых типов, часто используемые пары, а также ограниченные пропускной способностью памятиplus/minus/multiplyсохраняют свои отдельные ядра; результаты, типы результатов и обработка исключительных случаев не изменились. #110131 (alexey-milovidov). - Чтение из движка таблицы
SQLiteили табличной функцииsqliteбольше не загружает ядро CPU на 100 % активным ожиданием, когда база данных SQLite заблокирована другим соединением. Теперь во время ожидания блокировки чтение простаивает, и его по-прежнему можно отменить. #110248 (groeneai). - Значения затраченного времени, скорости и доли в журналах и сообщениях об исключениях теперь округляются до трёх цифр, поэтому числа вроде
1.345844286 sec.больше не выводятся с полной точностью. #110277 (alexey-milovidov). - Исправлено чтение в
MergeTreeстолбцов типаStringс отдельным потоком размеров после пропуска начальных строк: оно могло возвращать неверные данные или выходить за границы кеша подпотоков. Также исправлена возможная выдача неверных данных при параллельном или повторном чтении вложенного объектаJSON, хранящегося с сериализацией shared-data в виде map. #110471 (alexey-milovidov). - Добавлена поддержка предложения
SETTINGSдля движка таблицыPostgreSQLи табличной функцииpostgresql(например,SETTINGS postgresql_connection_pool_size = 50) — теперь их возможности соответствуют движкуMySQL. #110614 (alexey-milovidov). - Функции
bitmaskToArrayиbitmaskToListтеперь поддерживают аргументы(U)Int128и(U)Int256. Для аргументов с большими целыми числами функцияbitPositionsToArrayтеперь выполняется за время, пропорциональное количеству установленных битов, а не позиции старшего установленного бита. #110743 (raimannma). - Исправлена обработка кодеком GCD знаковых значений фиксированной ширины, содержащих отрицательные числа. Ранее делитель вычислялся непосредственно по знаковым значениям, из-за чего общий делитель мог не обнаруживаться, а эффективность сжатия для столбцов знаковых целочисленных и десятичных типов значительно снижалась. Теперь для знаковых типов делитель вычисляется по модулям значений, а поведение для беззнаковых типов и декомпрессии не изменилось. #113798 (kshcherbatov).
- Оконная функция с
PARTITION BYтеперь работает при включённомmake_distributed_plan. Если структура плана позволяет, окно вычисляется параллельно по бакетам, каждый из которых получает партиции целиком. #114111 (VighneshPath). - Для внешних методов агрегации по Nullable-ключам фиксированной ширины теперь используется 64-битная хеш-функция (это предотвращает лавину коллизий при агрегации с очень высокой мощностью). #114210 (nickitat).
x IN (subquery)для столбцаLowCardinalityтеперь возвращаетLowCardinality(UInt8)— тот же тип, что иx IN (literal list). Ранее эти две формы возвращали разные типы, и для распределённых планов с такимINпри проверке типов плана требовалась отдельная обработка. #114229 (davenger).- Добавлена поддержка разбора целых чисел, выходящих за пределы 64-битного диапазона, в типе данных
JSON, а также вJSONExtractиisValidJSON. Такие значения считываются в широкие целочисленные типы, напримерInt128/UInt256, и больше не приводят к отклонению всего документа. #114379 (Avogar). - Добавлен псевдоним
keywordдля токенизатора текстового индексаarray— для лучшей совместимости с OpenSearch, Elasticsearch, SolR и Lucene. #115507 (rschu1ze). - Функции
toDateOrNull,toDateTimeOrNullиtoDateTime64OrNullтеперь принимают аргументы всех встроенных целочисленных типов (они интерпретируются так же, как вtoDate,toDateTimeиtoDateTime64, с необязательным аргументом часового пояса) и возвращаютNULLдля значений, выходящих за пределы диапазона результирующего типа. Например,toDateTimeOrNull(1583851242, 'Asia/Shanghai')возвращает2020-03-10 22:40:42, аtoDateTimeOrNull(4294967296)—NULL. #79791 (jitendra1411).
Хранилище, озера данных и объектное хранилище
- Добавлены опциональные метрики 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). - Движок
Aliasтеперь поддерживает чтение с параллельных реплик, если целевая таблица использует движок семействаMergeTree. #107830 (nauu). - Количество одновременно подготавливаемых частей при копировании в Azure Blob Storage по схеме «чтение, затем запись» (применяется при резервном копировании, когда нативное копирование недоступно) теперь ограничено значением max_inflight_parts_for_one_file. Это предотвращает чрезмерное использование памяти при параллельном копировании множества больших файлов. #108232 (SmitaRKulkarni).
- Добавлена поддержка виртуального столбца
_etagдля хранилища HDFS #108255 (zhangyifan27). - В
system.backupsиsystem.backup_logдобавлены столбцыsettingsиengine_settings.settingsсодержит запрошенные для операции настройки резервного копирования и восстановления (например,allow_s3_native_copy,deduplicate_files,structure_only), аengine_settings— настройки, фактически используемые модулями чтения и записи движка резервного копирования (например, настройки запросов S3, такие какallow_native_copy, которые после слияния с конфигурацией конечной точки могут отличаться от запрошенных). Так можно узнать, с какими настройками на самом деле выполнялась операцияBACKUP/RESTORE. #108334 (jkartseva). - Добавлены
system.s3_queue_metadataиsystem.azure_queue_metadataдля просмотра состояния зарегистрированных таблицS3QueueиAzureQueueв Keeper, включая количество обработанных, обрабатываемых и завершившихся ошибкой файлов. #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). - Исправлены ложные переподключения keep-alive HTTP-соединений из пула поверх TLS (HTTPS, S3). Проверка устаревших соединений использовала
pollна сокете, из-за чего живое защищённое соединение с непрочитанной TLS-записью, полученной после рукопожатия (тикет сессии илиKeyUpdate), ошибочно считалось закрытым. Теперь для обычных сокетов используется неблокирующийMSG_PEEK, а для TLS-сокетов —SSL_peek/SSL_has_pending, что также позволяет корректно обнаруживать штатное завершение TLS-сессии и TLS-запись, пришедшую лишь частично. #110402 (alexey-milovidov). - Каталоги OneLake теперь могут использовать токены обновления OAuth для продления токенов доступа. #110413 (alesapin).
- Добавлено событие ProfileEvent
DuplicationDataHashComputations, которое подсчитывает поколоночные вычисления хешей данных, выполняемые при дедупликации вставляемых блоков в таблицы*MergeTree. #111173 (valerypetrov). - SST индекса UNIQUE KEY теперь записывается непосредственно в часть через абстракцию хранилища, без промежуточного сохранения в локальный временный файл. #111189 (JingYanchao).
- Добавлена поддержка конкурентной записи в таблицы Iceberg на локальном диске:
LocalObjectStorageтеперь реализует условную запись, поэтому операция compare-and-swap, публикующая новый снимок черезversion-hint.text, работает и здесь, а конкурентные писатели больше не могут потерять обновления друг друга. #112556 (alexey-milovidov). - Кеш регионов бакетов клиента
S3теперь работает и для каталогов озёр данных; ранее при каждом запросе к ним регион определялся заново. #113330 (scanhex12). - Сетевые сбои на стороне клиента Azure (сброс соединения или отказ в соединении, ошибки DNS и TLS) теперь обрабатываются как транспортные ошибки с повторными попытками, а не возвращаются в виде искусственной ошибки
500, — так же, как в клиенте S3. #115269 (arsenmuk).
Форматы и ингестия
- Добавлена поддержка сжатия snappy в HTTP-интерфейсе (
Accept-Encoding: snappy), а также настройкаsnappy_mode, позволяющая выбрать блочный формат Hadoop snappy или формат фрейминга snappy для операций ввода-вывода snappy в универсальных функцияхfile/url. #100752 (alexey-milovidov). - Добавлена настройка
input_format_csv_missing_nullable_as_empty_string(по умолчанию отключена). Если она включена, отсутствующее значение типаNullable(String)во входных данных CSV считывается как пустая строкаString, а не какNULL, независимо от значенияinput_format_csv_empty_as_default. #107577 (alexey-milovidov). - При обработке сообщений protobuf с настройкой
input_format_protobuf_oneof_presenceточное совпадение тегов больше не требуется, что позволяет изменять схему. #109174 (ilejn). - Удалён устаревший считыватель ORC на основе Apache Arrow. Входной формат ORC теперь всегда использует нативный декодер ClickHouse (ранее он применялся по умолчанию). Настройка
input_format_orc_use_fast_decoderустарела (она по-прежнему принимается, но ни на что не влияет). #110074 (alexey-milovidov). - Движок Hive теперь считывает метаданные ORC-файлов (индексы min/max, количество строк) с помощью нативного считывателя ORC в ClickHouse вместо адаптера Apache Arrow ORC. #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). - Документация настройки в
system.documentation, которая выводится встроенной страницей/docsи командойhelp, теперь включает историю изменений её значения по умолчанию: версию, в которой настройка появилась, и все последующие изменения значения по умолчанию с указанием предыдущего и нового значений, а также причины изменения. #112177 (alexey-milovidov). - Документацию по всем SQL-командам (имя, синтаксис, описание, примеры и т. д.) теперь можно получить из системной таблицы
system.statements. #115341 (rschu1ze).
Настройки и конфигурация
- Добавлена новая настройка сервера
memory_worker_rss_speculative_reserve_ratio(по умолчанию1.0, или0в сборках с санитайзерами), при которой глобальный трекер памяти на каждом тактеMemoryWorkerспекулятивно резервируетratio * min(resident - previous_resident, resident - tracked)сверх наблюдаемого RSS. Это смещает показания трекера вверх, когда рост RSS между замерами опережает учёт трекера, поэтому выделения памяти раньше получаютMEMORY_LIMIT_EXCEEDED, а вероятность того, что OOM-killer ядра сработает первым, снижается. Чтобы отключить спекулятивное резервирование, установите долю в0. В сборках с санитайзерами значение по умолчанию —0, поскольку разрывresident - trackedтам в основном обусловлен теневой памятью санитайзера. #104976 (alexey-milovidov). - Режим отложенного применения списков вхождений (posting lists) текстового индекса больше не является экспериментальным: его можно выбрать с помощью
text_index_posting_list_apply_mode = 'lazy'безallow_experimental_text_index_lazy_apply. Настройка порога плотности переименована из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
RESET,UNLISTENиDISCARDтеперь принимаются в PostgreSQL wire protocol как пустые операции, а не завершаются синтаксической ошибкой. Это улучшает совместимость с драйверами вроде Skunk, которые отправляютRESET ALLиUNLISTEN *при установке и закрытии соединения. #110780 (alexey-milovidov). - Текстовые AI-функции (
aiGenerate,aiClassify,aiExtract,aiTranslate) теперь отклоняют усечённые или иным образом неполные ответы провайдера (например, когда модель достигает лимитаmax_tokens), вместо того чтобы молча возвращать частичный результат. Поведение определяется настройкойai_function_throw_on_error. #111830 (george-larionov). - Улучшены функции пониженной точности
L2DistanceTransposedQuantized,cosineDistanceTransposedQuantizedиdotProductTransposedQuantizedза счёт восстановления кодовp < 8QBit(Int8)с помощью префиксных центроидов на основе гауссова условного среднего. При полной точности (p = 8) результаты остаются побитово идентичными; приближённые расстояния при пониженной точности могут измениться, а выигрыш в полноте и задержке зависит от нагрузки. #111867 (skuznetsov). - Настройка
write_snapshot_versionтеперь поддерживает горячую перезагрузку. #112150 (alesapin). - Добавлены средства обсервабилити стеков файберов, используемых для асинхронного взаимодействия с удалёнными репликами: события профилирования
FiberStackAllocs,FiberStackAllocBytes,FiberStackAllocNanoseconds,FiberStackFreeNanosecondsи метрикиFiberStacks,FiberStackBytes. #114541 (alexey-milovidov). - Протокол Prometheus remote-write теперь поддерживает асинхронные вставки: данные из нескольких одновременных запросов remote-write объединяются в пакеты перед формированием частей в соответствии с настройкой
async_insert(включена по умолчанию; чтобы сохранить синхронное поведение, добавьтеasync_insert=0в URL обработчика). Запрос подтверждается только после сброса данных во все внутренние таблицы целевой таблицыTimeSeries. #115688 (nikitamikhaylov).
Другие улучшения
- Добавлены две настройки,
shrink_over_allocated_columns_min_waste_ratioиshrink_over_allocated_columns_min_waste_bytes, при включении которых INSERT перед материализацией и записью частей ужимает до фактического размера столбцы с избыточно выделенной памятью (когда зарезервированная память превышает используемую из-за роста столбцов переменной длины по степеням двойки), что снижает пиковое потребление памяти. По умолчанию отключены. #112161 (Avogar). - Для слияний
TTLDropэтап чтения данных теперь полностью пропускается, чтобы избежать чрезмерного использования памяти, особенно на выделение буферов чтения/предварительной выборки. #105859 (Avogar). - Добавлена поддержка
BFloat16вdotProduct; кроме того, скалярное произведение стало вычисляться быстрее благодаря пакетной обработке в 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). - Запись в таблицы
DeltaLake, управляемая настройкойallow_experimental_delta_lake_writes, переведена в статус Beta. #107034 (kssenii). - Добавлен тип статистики столбцов
uniq_v2— легковесная альтернативаuniqна основе скетчаuniqCombined64. #107863 (hanfei1991). - Добавлены ProfileEvents
DistributedPlanRemoteTasks,DistributedPlanLocalExecutionиDistributedPlanHostsUsedдля отслеживания выполнения make_distributed_plan. #107985 (shankar-iyer). - Запросы к REST-каталогам озёр данных, например OneLake, теперь содержат заголовок
User-Agentс идентификатором ClickHouse. #108117 (scanhex12). MVTEncodeGeomтеперь привязывает геометрию к целочисленной пиксельной сетке перед отсечением и отсекает полигоны с помощьюwagyu, поэтому результат отсечения корректен (самопересекающиеся кольца исправляются) и выровнен по границам — так же, как в PostGISST_AsMVTGeom. #108248 (saarthak2002).- Все три кэша текстового индекса теперь включены глобально — ранее они включались только в рамках запросов. Кроме того, размер кэша списков вхождений теперь равен нулю (что фактически снова его отключает), поскольку списки вхождений велики и их кэширование обходится слишком дорого. #108274 (rschu1ze).
- Конечная точка Prometheus (для конфигураций, предназначенных только для метрик) и асинхронный сбор метрик теперь запускаются до загрузки таблиц, чтобы метрики были доступны во время потенциально длительной загрузки метаданных. #108402 (cwurm).
- Добавлена поддержка BFloat16 в бинарных математических функциях #108442 (zhangyifan27).
- Транспонированные функции векторного расстояния
L2DistanceTransposed,cosineDistanceTransposedиdotProductTransposedтеперь применяют оптимизацию частичного чтения битовых плоскостей к столбцамNullable(QBit), считывая только запрошенные битовые плоскости, а не весь столбец. #109358 (alexey-milovidov). - Добавлена поддержка
arraySum,arrayAvgиarrayProductдля массивов типаBFloat16. #109420 (alexey-milovidov). - Функции
L1Normalize,L2Normalize,LinfNormalizeиLpNormalize(а также их псевдонимы) теперь работают не только с кортежами, но и с массивами — аналогичноL2Normи функциям расстояния. #110052 (alexey-milovidov). - Соединения из пула больше не проверяются с помощью ping перед каждым использованием. Это устраняет дополнительный обмен
Ping-Pongпри каждом повторном использовании соединения и снижает задержку распределённых запросов иclickhouse-benchmark. Устаревшее соединение из пула обнаруживается с помощью poll с нулевым тайм-аутом (неблокирующая проверка, не требующая обмена с сервером) и восстанавливается путём повторного подключения. #110068 (alexey-milovidov). - Большие списки кусков для распределённого анализа индексов теперь передаются как скаляры (это предотвращает возможные сбои из-за max_ast_elements/max_query_size и устраняет накладные расходы на разбор AST) #110419 (azat).
- Нажатие на логотип облака в Песочнице ClickHouse теперь открывает сайт 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. Полное преобразование для длины, которую невозможно представить точно, теперь вызывает исключение вместо неявного дополнения нулями до более длинного вектора; чтобы вычислить усечённую проекцию произвольной длины, передайтеoutput_dims. #111006 (alexey-milovidov).- Для исключений
ACCESS_DENIEDв HTTP-интерфейсе теперь возвращается HTTP-код403 Forbidden(вместо500 Internal Server Error). #111043 (Schum-io). UTMToGeoтеперь принимает в качестве четвёртого аргумента букву широтной зоны MGRS, возвращаемуюgeoToUTM(помимо целочисленного флага полушария), поэтому результатgeoToUTMможно напрямую передать вUTMToGeoбез потерь. #111521 (alexey-milovidov).MaterializedPostgreSQLтеперь сохраняет неизменённые значения PostgreSQLTOASTпри обновлениях, а не заменяет их значениями по умолчанию. #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). - ANSI-последовательности экранирования больше не записываются в файл, указанный в предложении INTO OUTFILE, если stdout является tty #113252 (azat).
- Настройка
allow_experimental_delta_kernel_rsпереименована вallow_delta_kernel_rs. Старое имя сохранено как псевдоним. #113476 (kssenii). - Добавлены настройки
enable_alp_codec,enable_sz3_codec,enable_zxc_codecиenable_quantized_codec, позволяющие включать каждый экспериментальный кодек сжатия по отдельности. #113824 (rienath). - Теперь при переполнении стека выводится сообщение об ошибке, а не происходит молчаливое аварийное завершение: обработчики фатальных сигналов выполняются на альтернативном стеке сигналов, поэтому при
SIGSEGV,SIGABRT,SIGILL,SIGBUS,SIGSYS,SIGFPEиSIGTRAPвыводится трассировка стека, даже если сбойный поток исчерпал свой стек. #113927 (groeneai). - Добавлена поддержка параметра lookback_delta из Prometheus HTTP API для мгновенных запросов и запросов по диапазону. #113971 (fallintoplace).
- Таблицы QueryRunner теперь запускают рабочие потоки по мере необходимости и освобождают их при простое, а не занимают потоки на протяжении всего времени существования таблицы. #114522 (mstetsyuk).
- Теперь при использовании индексов WHATIF базовый вариант, обслуживаемый проекцией, возвращает
not_applicableдля каждого кандидата, а не завершает выполнение оператора с ошибкой. #114846 (yariks5s). - Оптимизированы цепочки AND с несколькими условиями сравнения для одного и того же выражения: обнаруживаются противоречия (например,
a < 3 AND a > 5→false) и отбрасываются избыточные условия (например,a = 3 AND a < 5→a = 3). #99736 (wudidapaopao).
Исправления ошибок
Исправления в MergeTree, репликации и хранилище
- Исправлено состояние гонки между
ALTER TABLE ... RENAME COLUMNи параллельнымOPTIMIZE TABLE ... FINAL(или любым фоновым слиянием) вMergeTree, из-за которого данные переименованного столбца могли незаметно заменяться значениями по умолчанию. Окно гонки между публикацией новых метаданных в памяти и регистрацией мутации переименования вcurrent_mutations_by_versionтеперь закрыто:currently_processing_in_background_mutexудерживается на протяжении обеих операций. #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). - Теперь генерируется исключение
BAD_ARGUMENTSвместоLOGICAL_ERROR, когдаALTER TABLE ... MOVE/REPLACE/ATTACH PARTITIONвыполняется между двумя таблицамиMergeTreeс несовместимыми настройками гранулярности (одна адаптивная, другая неадаптивная). #103881 (groeneai). - Исправлена ошибка
LOGICAL_ERROR«Expected one block from input stream», возникавшая вKILL QUERY/KILL MUTATION/KILL PART_MOVE_TO_SHARD/KILL TRANSACTION, если их предложениеWHEREсодержит построчный подзапрос или если значениеmax_block_sizeнастолько мало, что внутреннийSELECTпо соответствующей таблицеsystem.*возвращает более одного блока. #104927 (groeneai). - Исправлена утечка в Refreshable Materialized Views (
MATERIALIZED VIEW ... REFRESH ...): временную внутреннюю таблицу, которую задача обновления выводит из ротации черезEXCHANGE TABLES, не удавалось удалить, если её размер превышал заданный на сервереmax_table_size_to_drop. Каждое последующее обновление создавало ещё одну временную внутреннюю таблицу, так и не удаляя предыдущие, и каталог данных представления разрастался, пока на диске не заканчивалось место. Внутреннее удаление в задаче обновления теперь игнорируетmax_table_size_to_dropиmax_partition_size_to_drop; эти защитные ограничения по-прежнему действуют, когда пользователь сам выполняетDROP TABLEдля представления. #105106 (groeneai). - Исправлена неожиданная ошибка
DATA_TYPE_CANNOT_BE_USED_IN_KEYв запросахALTER, которые не могут изменить ключ сортировки (настройки, комментарии, кодеки, добавление неключевого столбца и т. д.), для таблицMergeTree, у которых в ключе сортировки естьSimpleAggregateFunction(или другой тип, допустимый только приallow_suspicious_primary_key = 1). #105111 (groeneai). OPTIMIZE ... DRY RUN, прерванный по тайм-ауту запроса (max_execution_timeсtimeout_overflow_mode = 'break'), теперь возвращаетTIMEOUT_EXCEEDEDвместо логической ошибки, связанной сrows_sources(в отладочных сборках и сборках с санитайзерами она приводила к аварийному завершению сервера). #107114 (groeneai).- Исправлена ошибка
NOT_FOUND_COLUMN_IN_BLOCKпри чтении файлов с hive-партиционированием приuse_hive_partitioning=1и предложенииWHERE/PREWHERE, фильтрующем реальный (не виртуальный) столбец, если одновременно выбирается и столбец hive-партиции. #107505 (groeneai). - Исправлены неверные результаты запросов, вызванные некорректным отсечением по первичному ключу и партициям, когда
toStartOfDay,toStartOfISOYear,toDaysSinceYearZero,toRelativeSecondNum,toRelativeMinuteNum,toRelativeHourNum,toRelativeWeekNum,toRelativeDayNum,toMonthNumSinceEpochилиtoYearNumSinceEpochприменяется к ключевому столбцу типаDate32, содержащему даты вне диапазона, представимого функцией (в частности, даты до1970-01-01). Эти функции сообщают первичному индексу, что они монотонны, однако ранее для таких аргументов их значения переполнялись и «заворачивались», из-за чего индекс мог отсекать гранулы, на самом деле содержавшие подходящие строки. Теперь значения ограничиваются границами типа результата (насыщение), функции остаются монотонными на всём диапазонеDate32, и отсечение работает корректно. #108018 (nihalzp). - Исправлена ошибка, из-за которой
CREATE TABLE dst AS src SETTINGS ...(и аналогичные варианты сORDER BY/PARTITION BY, но без явногоENGINE) молча отбрасывали движок исходной таблицы, секции хранения (например,TTLтаблицы и ключи) и настройки. Теперь движок и непереопределённые секции хранения наследуются от исходной таблицы, а указанные настройки применяются поверх настроек исходной таблицы. #108085 (alexey-milovidov). - Исправлен сбой
INSERTв таблицыMergeTreeс ошибкойfilesystem error: in rename: Permission deniedна файловых системах на базе Windows (WSL, CIFS/SMB, bind mounts в Docker Desktop): модуль записи частей оставлял файловые дескрипторы открытыми во время переименования каталога части. #108089 (alexey-milovidov). - Исправлено зависание таблицы MergeTree, подключённой с устаревшим пропускающим индексом
hypothesis(удалённый тип индекса, сохранённый только для совместимости сATTACH). Ранее облегчённыйDELETE,OPTIMIZE, обычныйINSERTилиSELECTс фильтром для такой таблицы завершались ошибкойILLEGAL_INDEX(“Index of type ‘hypothesis’ is no longer supported”), а мутацияDELETEповторялась бесконечно. Теперь неработающий индекс считается инертным: при слиянии и мутации он переносится без изменений, игнорируется при вставке и планировании запроса и по-прежнему может быть удалён с помощьюALTER TABLE ... DROP INDEX. #108217 (groeneai). - Исправлена ошибка
NOT_FOUND_COLUMN_IN_BLOCK(например,Column _part not found) при выборке виртуальных столбцов из таблицыMergeTreeс параллельными репликами, в том числе черезSELECT *приasterisk_include_virtual_columns = 1. #108451 (groeneai). - Исправлена ошибка, из-за которой
ATTACH PARTITION ... FROMотклонял таблицы с эквивалентными, но по-разному объявленными первичными ключами (в одной — явныйPRIMARY KEY, в другой — неявный изORDER BY). #108590 (jordiori). - Настройка
join_any_take_last_rowтеперь учитывается во всех поддерживаемых вариантах хеш-JOIN, включая JOIN с автоматическим сбросом данных на диск. #108936 (antaljanosbenjamin). - Исправлена ошибка
NOT_FOUND_COLUMN_IN_BLOCK, возникавшая при включённой настройкеquery_plan_optimize_lazy_finalв сочетании с фильтромWHERE, частично перенесённым вPREWHERE(черезoptimize_move_to_prewhere_if_final). Отложенная оптимизация FINAL больше не запрашивает из хранилища столбцы предикатов, вычисляемые в prewhere. #109073 (groeneai). - Исправлена ошибка, из-за которой
ALTER TABLE ... ADD PROJECTIONнад столбцомALIASуровня таблицы делал таблицу непригодной для использования (последующийINSERTзавершался ошибкойUNKNOWN_IDENTIFIER, “Missing columns”), если в сессии был заданoptimize_respect_aliases = 0. #109091 (groeneai). - Исправлено срабатывание проверки на нулевой указатель (
px != 0вTreeRewriter::analyzeSelect, приводившее к аварийному завершению сервера в отладочных сборках и сборках с санитайзерами) при выполненииORDER BY ALL(илиGROUP BY ALL) над таблицей на движкеMerge, соединённой с другой таблицей, при использовании старого анализатора (allow_experimental_analyzer = 0). #109139 (groeneai). - Исправлен неверный результат коррелированных подзапросов
EXISTSи скалярных подзапросов в случае, когда корреляция присутствует только в проекции подзапроса, а предложениеWHEREнекоррелированное (подзапрос мог возвращать false /NULLдля каждой строки). Исправляет https://github.com/ClickHouse/ClickHouse/issues/105760. #109186 (novikd). - Исправлена ошибка, из-за которой слияние таблицы
MergeTreeс проекциями при включённой настройкеenable_block_number_columnилиenable_block_offset_columnсоздавало части проекций с лишним столбцом_block_number/_block_offset. В результате слитая часть проекции переставала соответствовать определению проекции и частям проекций, созданным при вставке, поэтомуCHECK TABLEиOPTIMIZE ... DRY RUNсообщали о её повреждении (CORRUPTED_DATA). #109284 (groeneai). - Исправлена ошибка
UNKNOWN_IDENTIFIERпри выполненииALTER TABLE ... RENAME/ADD/MODIFY COLUMNдля таблицы MergeTree с неявным min-max индексом по постоянным виртуальным столбцам_block_numberили_block_offset(включается настройкамиadd_minmax_index_for_block_number_column/add_minmax_index_for_block_offset_column). #109428 (groeneai). - Исправлена ошибка, из-за которой индексы пропуска удалялись из части данных (или
CHECK TABLEзавершался ошибкойUNEXPECTED_FILE_IN_DATA_PART) после мутации с полной перезаписью части форматаWide, напримерALTER TABLE ... DROP COLUMNдля столбцаMATERIALIZED. #109616 (groeneai). - Исправлена ошибка, из-за которой индексы пропуска (
text,bloom_filterи др.) и проекции устаревали после материализации облегчённых обновлений с помощьюALTER TABLE ... APPLY PATCHES. Ранее файлы индексов и проекций, зависящие от столбца, обновлённого патчем, оставались без изменений, поэтому использующие их запросы могли возвращать неверные результаты (например,hasTokenпропускал обновлённую строку, а проекция возвращала устаревшие агрегаты после удаления отработанной части патча). #109709 (groeneai). - Исправлена ошибка, из-за которой мутация, ссылающаяся на виртуальный столбец
_sample_factor, завершалась сбоем посреди выполнения с сообщениемUnexpected const virtual column: _sample_factorи зависала. Теперь мутация считывает его как1— то же значение, что возвращает запрос безSAMPLE. #109813 (groeneai). - Исправлены две ошибки, возникавшие при выполнении запроса с
GROUP BY GROUPING SETS(или содержащего такой запрос скалярного подзапроса либо подзапроса мутации) сforce_aggregation_in_order = 1:Trying to get name of not a column: ExpressionListпри старом анализаторе (enable_analyzer = 0) иMemory bound merging of aggregated results is not supported for grouping sets.для распределённого запроса сenable_memory_bound_merging_of_aggregation_results = 1при новом анализаторе. #109862 (groeneai). - Исправлены три проблемы с
use_constant_folding_in_index_analysis: логическая ошибкаInvalid partition key size, которая могла прерыватьSELECTс обычной проекцией, если в таблице заданоpart_minmax_index_columns = 'with_block_number_offset'; неверные результаты (строки молча отбрасывались) при фильтрации по ключу партиционирования с делением по модулю, напримерPARTITION BY id % 200; а также сбой (гонка данных) при запросе к индексуtextс токенизаторомsparseGramsс предикатомLIKEпо множеству партиций приmax_threads > 1. #109896 (groeneai). - Исправлены неверные результаты при использовании индекса пропуска
minmax, построенного по столбцуLowCardinality(Nullable(...)): предикатыWHERE/PREWHERE/HAVING ... IS NULL, передаваемые в хранилище, ранее отсекали все гранулы, и запрос возвращал 0 строк, хотя столбец содержал значения NULL. #110061 (groeneai). - Исправлено медленное выполнение запросов
ORDER BY ... LIMITк таблицамDistributed, когдаprefer_localhost_replicaвыбирает локальную реплику. #110136 (EmeraldShift). - Исправлено исключение (
UNION mode UNION_DEFAULT must be normalized), возникавшее, когда мутацияDELETEилиALTER UPDATEиспользовала операцию над множествами (UNION/UNION ALL/UNION DISTINCT/EXCEPT/INTERSECT) внутри подзапроса в условииWHEREили в присваиванииUPDATE. #110196 (alexey-milovidov). - Исправлены медленное завершение работы сервера и отсутствие реакции на
KILL MUTATION, когда мутация сx IN (subquery)строила множество для подзапроса во время анализа первичного ключа; теперь построение множества отменяется незамедлительно. #110198 (alexey-milovidov). - Исправлена гонка между
KILL TRANSACTIONиALTER TABLE ... UPDATE/DELETE, выполняемым внутри транзакции: если откат происходил между регистрацией мутации в транзакции и её регистрацией в таблице, оставалась «осиротевшая» запись о мутации. Это вызывало логическую ошибку (Cannot find transaction ... that has started mutation ...) в фоновых задачах и блокировало все последующие мутации затронутых частей до перезапуска сервера. #110226 (tiandiwonder). - Исправлена ошибка
system.tablesдля базы данныхDataLakeCatalog(Iceberg/Glue): если метаданные одной таблицы не удавалось получить, весь запрос прерывался или таблицы молча пропадали из результата. Теперь такая таблица по-прежнему отображается в списке по имени, а столбцы, для которых требуется открытый объект хранилища (engine,total_rowsи т. д.), содержат значения по умолчанию или NULL — независимо отdatabase_datalake_require_metadata_access. При прямом обращении к повреждённой таблице ошибка по-прежнему выводится. #110242 (groeneai). - Оценка мощности при выборе порядка JOIN теперь строится на статистике столбцов только по тем частям, которые остались после отсечения по партициям/первичному ключу, а не по всем активным частям. Ранее запрос, затрагивающий лишь небольшую партицию, планировался по статистике всей таблицы (наблюдалась переоценка числа строк в 2500 раз, из-за которой менялась сторона построения hash join), и отключение статистики парадоксальным образом давало более удачный план. Также исправлено: ленивый FINAL молча отключался для отношений MergeTree под JOIN, поскольку мемоизированный результат анализа индексов в оптимизаторе порядка JOIN ошибочно принимался за применённую проекцию. #110283 (skuznetsov-clickhouse).
ALTER TABLE ... MOVE/REPLACE PARTITIONмежду двумя таблицами MergeTree с несовместимой гранулярностью (одна адаптивная, другая нет) теперь выбрасываетBAD_ARGUMENTSвместоLOGICAL_ERROR. Пользователь вполне может столкнуться с такой ситуацией, поэтому она не должна приводить к внутренней ошибке (которая в отладочных сборках и сборках с санитайзерами аварийно завершает сервер). #110535 (groeneai).- Исправлена ошибка, из-за которой
TTL ... DELETE WHERE <cond>никогда не удалял строки, начавшие удовлетворять<cond>после выполненияALTER TABLE ... UPDATEнад столбцом, используемым вWHERE. Теперь мутация пересчитывает TTL строк, поэтому истёкшие строки, ставшие удовлетворять условию, удаляются, а не продолжают незаметно храниться. #110648 (groeneai). - Исправлена ошибка
LOGICAL_ERROR“Invalid partition key size: 0”, которая могла прерыватьINSERTв партиционированную таблицуMergeTreeс включённымnon_replicated_deduplication_window, если пакет асинхронной вставки дедуплицировался лишь частично (часть значенийinsert_deduplication_tokenбыли дубликатами, а часть — новыми). #110651 (groeneai). - Исправлена ошибка, из-за которой свёртка констант в новом анализаторе незаметно меняла тип константного значения
Geometry.Geometry— это именованныйVariant, альтернативы которого могут иметь одинаковое представление в хранилище (LineString/Ring,MultiLineString/Polygonи пустые значения), поэтому две свёрнутые константы, различающиеся только альтернативой, схлопывались в одну: например, константаMULTIPOLYGON EMPTYпревращалась вLINESTRING(). #110709 (groeneai). - Исправлен неверный результат (неправильный порядок слияния) для запросов с чтением в порядке сортировки, когда
distinct-in-orderилиaggregation-in-orderрасширяет чтение до более длинного префикса ключа сортировки, чем тот, для которогоORDER BYподготовил виртуальную строку. Дополнительные столбцы сортировки виртуальной строки заполнялись значениями по умолчанию, что могло нарушать порядок вMergingSortedTransform(и приводить к аварийному завершению сLOGICAL_ERRORв отладочных сборках и сборках с санитайзерами). #110725 (groeneai). - Активные роли запроса (SET ROLE / role=) теперь передаются на удалённые узлы при чтении с параллельных реплик и из Distributed-таблиц в кластере с interserver-секретом; ранее вместо них использовались роли пользователя по умолчанию, из-за чего политики строк вычислялись не так, как на узле-initiator. #110867 (evillique).
- Исправлено редкое состояние гонки, при котором
ALTERтаблицыReplicatedMergeTree, изменяющий только комментарий или настройки, мог незаметно отбросить столбец, добавленный параллельнымALTER ... ADD COLUMN, и реплика оставалась с устаревшей структурой таблицы. #111029 (tiandiwonder). - Исправлена ошибка
NUMBER_OF_COLUMNS_DOESNT_MATCHдляGROUP BYс агрегатной функцией над таблицейMerge, оборачивающей таблицуDistributed, когда ключ группировки является функцией от столбца, а агрегатная функция читает тот же столбец (например,SELECT toString(g), min(g) FROM merge_over_distributed GROUP BY toString(g)). #111334 (groeneai). - Исправлен неверный результат
FULL JOINс таблицей на движкеJoin(StorageJoin) иUSING, когда левый ключ имеет типNullable, а ключ хранилища — нет: для левой строки без соответствия с ключомNULLвозвращался0вместоNULL. #111371 (groeneai). ALTER TABLE ... DETACH PARTITION/PARTтеперь выполняет fsync для копии, создаваемой вdetached/(поддерева части, а также цепочки каталогов вплоть до корня диска), если для таблицы включена настройкаfsync_part_directory; это касается как формата хранения частей Full (каталог), так и Packed. Ранее fsync для копии никогда не выполнялся, хотя для пустой покрывающей части, удаляющей строки из активного набора, он выполнялся. Поэтому отключение питания сразу после подтверждения могло уничтожить отсоединённые данные на btrfs: несинхронизированные записи каталога копии откатывались,detached/оставался пустым, и дляATTACHничего не оставалось. Новое поведение управляется существующей настройкойfsync_part_directory; поведение по умолчанию не изменилось. #111426 (groeneai).- Столбец типа
Nullable(Nothing)(или любого другого типа, недопустимого в таблицах) теперь отклоняется на этапеCREATE TABLE, если схема выводится из хранилища (например, для таблицыremote()/Remote/Distributedбез столбцов поверх представления, выполняющегоSELECT NULL). Ранее сохранялись метаданные, которые не удавалось загрузить при следующем перезапуске сервера, из-за чего блокировалась загрузка никак не связанных с ними таблиц. #111487 (groeneai). - Исправлена ошибка
LOGICAL_ERROR(Got read request from replica N for unknown stream ...), которая могла приводить к аварийному завершению сервера при чтении с параллельными репликами, если запрос полностью обрабатывался на инициаторе за счёт оптимизации с использованием проекций (точный подсчёт, minmax-подсчёт или сохранённая агрегирующая/обычная проекция, не выбирающая ни одного диапазона). #111689 (groeneai). - Исправлен партиционированный
INSERTв DeltaLake (allow_experimental_delta_lake_writes=1), который искажал значения партиций, содержащие символы пути, и отклонялNULL. Значение видаa/bбез предупреждения записывалось какa,%приводил к созданию файла данных, который затем не удавалось прочитать, а значение партицииNULLвызывало ошибкуNOT_IMPLEMENTED. Теперь значения партиций кодируются в один сегмент пути с помощью percent-encoding, исходное значение сохраняется вpartitionValues, а не извлекается обратно из пути, а значение партицииNULL(или пустая строка) записывается как__HIVE_DEFAULT_PARTITION__с записью null вpartitionValues. #111793 (groeneai). - Исправлены логические ошибки
Expected UInt64 column for __grouping_set, got BLOBиColumnBLOB should be converted to a regular column before usageпри выполнении распределённого запроса на шарде сenable_parallel_blocks_marshalling(включено по умолчанию), например приGROUP BY GROUPING SETSна кластере с локальной репликой или при чтении таблицыMerge, охватывающей локальную и distributed таблицу.BlocksMarshallingStepбольше не добавляется в планы, блоки которых потребляются в том же процессе. #111997 (groeneai). - Исправлена ошибка
LOGICAL_ERROR(Type mismatch when building statistics for column) при мутацииMergeTreeв таблице, где тип столбца со статистикой был изменён с помощьюALTER MODIFY COLUMN, затрагивающего только метаданные (например,Enum8наInt8илиDateTimeнаUInt32). Теперь мутация пересчитывает статистику только для фактически перезаписываемых столбцов, а остальную переносит без изменений. Для столбца, перезаписанного с помощьюMATERIALIZE COLUMN,UPDATEстолбца, от которого зависит столбецMATERIALIZED, илиCLEAR COLUMN, статистика теперь пересчитывается, а не остаётся устаревшей. #112009 (groeneai). - Исправлена проблема, из-за которой строки незаметно пропадали из результата, если запрос фильтрует по
intDiv(constant, key)илиdivide(constant, key). Анализ первичного ключа и партиций определял неверное направление монотонности для константы, делённой на столбец ключа, поэтому подходящие гранулы отсекались и запрос без какой-либо ошибки возвращал меньше строк. Также исправлена работаintDivс беззнаковой константой-делимым, у которой установлен старший бит; монотонность больше не заявляется, если из-за операнда типаDecimalделение вычисляется в собственной разрядности decimal; кроме того, анализ ключа больше не выдаёт ошибкуCannot compare DB::IPv4 with longдля корректного запроса, в котором константаIPv4/IPv6делится на столбец ключа. #112156 (groeneai). - Исправлена ошибка, из-за которой параметризованное представление, в теле
SELECTкоторого используетсяINTERSECT/EXCEPTили цепочкаUNION, сочетающаяUNION DISTINCTсUNION ALL, классифицировалось как обычное представление. Такое представление успешно создавалось, но его метаданные затем не удавалось прочитать: при загрузке возникала ошибкаInvalid storage definition in metadata file, из-за чего представление навсегда становилось незагружаемым, а сервер в отладочной сборке или сборке с санитайзером аварийно завершался при запуске. Кроме того,system.tables.parameterized_view_parametersне показывал для таких представлений никаких параметров. #112211 (groeneai). - Исправлена ошибка, из-за которой
max_execution_timeиKILL QUERYигнорировались, пока запрос вычислял функциюgeohashesInBox. Такой запрос разворачивал все строки блока, прежде чем его можно было прервать, поэтому отмена срабатывала лишь через несколько минут; теперь функция проверяет ограничение времени запроса по мере обхода строк. Вычисления внутри сохраняемого табличного выражения, например ключа сортировки, skip-индекса илиPARTITION BY, этим исправлением не охвачены и отслеживаются отдельно. #112273 (groeneai). - Исправлена логическая ошибка при использовании PREWHERE для Merge-таблицы поверх другой Merge-таблицы или materialized view с отличающимся типом столбца. Также исправлена ситуация, когда политика строк незаметно игнорировалась для таблиц, читающих данные с удалённых серверов (Distributed-таблица или таблица-обёртка над ней), из-за чего могли раскрываться строки, которые политика должна была скрывать; теперь такие запросы отклоняются с ошибкой ILLEGAL_PREWHERE. Вместо этого задавайте такие политики для базовых локальных таблиц на каждом удалённом сервере; обратите внимание, что такая политика по-прежнему не применяется к чтению, передаваемому с
serialize_query_plan = 1, — это отдельная, уже существовавшая ранее ошибка. #112326 (PedroTadim). - Исправлено чтение устаревшего вторичного (skip) индекса после изменения типа через
ALTER TABLE ... MODIFY COLUMN, если соответствующая мутация так и не была выполнена — например, потому что её удалили с помощьюKILL MUTATION: гранулы на диске были записаны со старым типом, но декодировались с новым, что приводило кLOGICAL_ERROR, попыткам выделить память объёмом в несколько эксабайт или незаметному возврату неверного результата. Также исправлен неверный результат индекса над выражением, смысл которого меняется, хотя все хранимые байты остаются прежними, поэтому мутация вообще не создаётся: например, приMODIFY COLUMN, изменяющем только часовой поясDateTimeили только пользовательское имя типа, напримерUInt8наBool. Теперь такой индекс для затронутой части пропускается. #112484 (groeneai). - Исправлена ошибка
LOGICAL_ERROR(Cannot add transform Resize to Pipes because it has no outputs), возникавшая при выполнении запроса с агрегацией по кластеру сserialize_query_plan = 1и параллельными репликами на основе плана: шаг слияния изменял размер конвейера до нуля потоков. #112506 (groeneai). - Исправлена ошибка
LOGICAL_ERROR(“Part … contains column … that is absent in table …”), возникавшая, когда репликаReplicatedMergeTreeвыполняла мутацию части, полученной с другой реплики, до применения собственного отложенногоALTER ... ADD COLUMN. Теперь такая мутация откладывается до применения изменения метаданных. #112510 (groeneai). - Исправлено завышение счётчиков чтения (
read_rows,read_bytes,ProfileEvents['SelectedRows'],ProfileEvents['SelectedBytes']) и избыточное списание квотREAD_ROWSиREAD_BYTESдля запросов, у которыхORDER BYсбрасывает данные на диск. Строки, повторно считанные из временных файлов внешней сортировки, ещё раз учитывались как чтения из источника, поэтому запрос со сбросом данных на диск завышал объём прочитанного и мог быть отклонён с ошибкойQUOTA_EXCEEDED, хотя и не выходил за пределы своей квоты. #112645 (groeneai). - Исправлено занижение размера результата
JOINсо сбросом данных на диск вProfileEvents['JoinResultRowCount']. Строки, выдаваемые из отложенных бакетов, учитывались только вJoinDelayedJoinedTransformRowCountи не попадали в общий итог. Результаты запросов при этом всегда были корректными — неверным было лишь значение события профилирования. #112673 (groeneai). - Исправлена проблема, из-за которой
max_execution_timeиKILL QUERYнезаметно переставали действовать на распределённый запрос, устанавливающий соединения с репликами. Теперь такой запрос останавливается при следующей попытке соединения, а не перебирает все оставшиеся реплики и повторные попытки. #112689 (groeneai). - Исправлено применение
ALTERк таблицамMergeTreeв то время, когда ещё выполняется незавершённая мутацияRENAME COLUMN. Это могло несовместимым образом изменить метаданные хранилища и полностью заблокировать последующие мутации. #112783 (Michicosun). - Исправлены неверные результаты
ORDER BYпри чтении из таблицыMergeповерх таблицDistributed: строки могли возвращаться в неправильном порядке, а при использованииLIMITчасть строк, которые должны были попасть в результат, могла отсутствовать. #112931 (alexey-milovidov). - Исправлены неверные результаты при включённой предварительной выборке (prefetch) при чтении из файловой системы, когда столбец
Nestedчитается вместе с подстолбцом, который был удалён и добавлен заново, в таблицах с включённой настройкойshare_nested_offsets(по умолчанию). Такой запрос мог возвращать значения по умолчанию для физически присутствующего столбца, который операцииALTERвообще не затрагивали. В объектном хранилище проблема проявляется без каких-либо нестандартных настроек, посколькуremote_filesystem_read_prefetchпо умолчанию равно1; на локальных дисках для этого требуетсяlocal_filesystem_read_prefetch = 1. Отдельный дефект, не связанный с предварительной выборкой, по-прежнему портит такие чтения, когда диапазон охватывает несколько блоков; данное исправление его не затрагивает. #112997 (groeneai). - Исправлена логическая ошибка
Pipeline stuckв запросах, распределяющих данные по партициям, например в оконной функции сPARTITION BYили в JOIN сjoin_algorithm = 'parallel_full_sorting_merge', когда последующая обработка одного шарда завершалась, пока блок был распределён лишь частично. #113190 (groeneai). - Исправлено зависание операторов
ALTER,OPTIMIZE,TRUNCATEи операций над партициями сalter_sync = 2вReplicatedMergeTree, когда таблица начинает завершать работу, пока оператор ожидает другую реплику, например из-за параллельно выполняемогоDROP DATABASE ... SYNC. Теперь такой оператор завершается с ошибкойUNFINISHED, а также учитываетmax_execution_timeиKILL QUERY. #113228 (groeneai). - Исправлена ошибка
Cannot insert element into Set(NOT_IMPLEMENTED), возникавшая при включённой настройкеread_in_order_use_virtual_row, когда запрос кMergeTreeс чтением в порядке сортировки сочетаетWITH FILL ... INTERPOLATEс фильтромINилиhas. #113264 (groeneai). - Исправлена логическая ошибка (исключение)
Chunk info was not set for chunk in MergingAggregatedTransform, возникавшая при включённой настройкеinject_random_order_for_select_without_order_by, когда агрегирующий запрос читает из таблицыMerge, содержащей дочернюю таблицуDistributed: обёртка со случайной сортировкойORDER BY rand()больше не добавляется в запросы, план которых строится только до промежуточной стадии. #113266 (alexey-milovidov). - Исправлена ситуация, при которой строки никогда не удалялись, если у таблицы
MergeTreeесть два или более правилаTTL ... DELETE WHEREс одинаковым временным выражением, различающиеся только условиемWHERE. После слияния с удалением по TTL значениеrows_where_ttl_infoдля части сбрасывалось в ноль, поэтому новые TTL-слияния для неё больше не планировались, а истёкшие строки хранились бессрочно — без какой-либо ошибки или сообщения в логе. #113384 (groeneai). - Исправлена ошибка, из-за которой
max_execution_timeиKILL QUERYигнорировались, пока запрос вычислял функцииgeohashesInBox,arrayFold,sleep,base58Decode,h3PolygonToCellsилиh3PolygonToCellsWithContainmentвнутри выражения, хранящегося в метаданных таблицы, например в ключе сортировки, индексе пропуска данных или ключеPARTITION BY. #113456 (groeneai). - Исправлена ошибка
LOGICAL_ERROR(Reading from materialized CTE '...' before its materialization completed - DelayedPortsProcessor gate is missing in the query plan), возникавшая, когда таблицаMergeс несколькими дочерними таблицами читает материализованное CTE, на которое ссылается внешний запрос. #113558 (alexey-milovidov). - Исправлена ошибка
Logical error: 'Required output position N is out of range for pass-through inputs'вEXPLAIN ANALYZEдля таблицыMergeс несколькими дочерними таблицами,PREWHEREпо одиночному столбцу и отдельнымWHERE. #113725 (groeneai). - Исправлена логическая ошибка (
Unexpected return type), возникавшая при проталкивании в хранилище фильтра по представлению, тип столбца которого отличается от типа в нижележащем хранилище (например,information_schema.tables, гдеengineимеет типNullable(String), поверхsystem.tables, где он имеет типString). #113984 (alexey-milovidov). - Исправлена ошибка
Not-ready Set is passed as the second argument for function 'in', возникавшая при отмене мутации, предикат которой содержитIN (subquery)(например, с помощьюKILL MUTATIONилиDETACH DATABASE), пока множество для подзапроса ещё строится. #114463 (groeneai). ALTER TABLE ... DROP COLUMNдля столбца, используемого в ключе сортировки, первичном ключе или ключе партиционирования, теперь завершается ошибкойALTER_OF_COLUMN_IS_FORBIDDENс пояснением — так же, какALTER TABLE ... CLEAR COLUMN. Ранее возникала малопонятная ошибкаUNKNOWN_IDENTIFIER: Missing columns, вызванная пересчётом ключевых выражений. То же относится к удалению или очистке целой группыNestedпо её общему префиксу, если какой-либо столбец группы используется в ключе; ранее это могло незаметно уничтожить данные группы или оставить мутацию, которая никогда не завершится. При удалении столбца, используемого только в выраженииTTL, теперь также сообщается, какое TTL-выражение будет нарушено #114468 (m7kss1).- Исправлена ситуация, при которой столбец, переименованный, удалённый и снова добавленный в одном
ALTER, до завершения мутации возвращал значения удалённого столбца вместо собственного значения по умолчанию. #114601 (tiandiwonder). - Исправлено чтение подстолбца (
.size0,.null, элемента кортежа,String.size) через таблицуMerge, когда в базовой таблице родительский столбец объявлен какALIAS. Такое чтение возвращало значение типа по умолчанию, а если родительский столбец выбирался в том же запросе, могло вернуть значение постороннего столбца. #114673 (groeneai). - Исправлено отсутствие строк в результате
SELECTс фильтромpointInPolygonпо первичному ключу MergeTree, когда аргумент-полигон является некорректным константным литералом, аvalidate_polygons = 0. Анализ первичного ключа отсекал гранулы на основе полигона, который так и не был проверен, и отбрасывал гранулы с подходящими строками. #114710 (groeneai). - Исправлено форматирование
ALTER TABLE ... MATERIALIZE INDEX,MATERIALIZE STATISTICSиMATERIALIZE PROJECTION, при котором терялась секцияIF EXISTS, из-за чего отформатированный запрос не совпадал с разобранным. Кроме того, теперь отклоняются четыре JSON-представления AST дляALTER ... STATISTICS, которые SQL-парсер не может сгенерировать и которые при форматировании превращались в другую команду. #115099 (groeneai). - Исправлено чтение за границами кэшированных хешей словаря при агрегации или соединении по ключу
LowCardinality(String), словарь которого растёт во время агрегации (проявлялось, в частности, черезTTL ... GROUP BY). Это могло приводить к неверному хешу, а в сборках с санитайзерами — к ошибке heap-buffer-overflow. #115604 (groeneai). CREATE TABLEиALTER TABLEтеперь запрещают использовать кодеки с потерями, напримерSZ3, для столбцов, входящих в ключ партиционирования. #115626 (groeneai).- Чтение через таблицу
Merge, которой соответствует таблицаAlias, ссылающаяся на параметризованное представление, больше не вызывает ошибку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). - Исправлена ошибка
Invalid number of columns in chunk pushed to OutputPort(LOGICAL_ERROR), возникавшая, когда запросSELECT ... FROM t STREAM ... ORDER BY ... LIMIT nчитал таблицу сPROJECTION. Ленивая материализация больше не применяется при чтенииSTREAM. #116187 (groeneai). ALTER TABLE ATTACH PARTITION FROMбольше не реплицируется в реплицируемых базах данных. #94835 (MikhailBurdukov).- Исправлено аварийное завершение сервера (в сборках с санитайзерами) и скрытая потеря данных при запуске таблицы, когда откаченная транзакционная часть MergeTree пересекается с закоммиченной частью. Теперь
PartLoadingTree::addправильно определяет, какая из двух пересекающихся частей была откачена, исключает её и в правильном порядке переносит её осиротевшие дочерние части под закоммиченную часть. #100992 (tuanpach). - Исправлена ошибка, из-за которой
indexOfAssumeSortedвозвращала неверные результаты для столбцовArray(LowCardinality(String))в таблицах семейства MergeTree. #101771 (Onyx2406). - Исправлены исключения
LOGICAL_ERRORпри чтении таблиц озёр данныхIcebergилиDeltaLakeпо путям, на которых конвейер чтения может запускаться без закреплённогоdatalake_table_state, например при параллельных обновлениях метаданныхIcebergили чтении черезmergeиз таблицDeltaLake. #102033 (groeneai). - Исправлена ошибка
Logical error: Parsed partition value: ... doesn't match partition value for an existing part with the same partition ID: ..., возникавшая при выполненииOPTIMIZE TABLE ... PARTITION ...(и других запросов, определяющих значение партиции черезconvertFieldToTypeImpl) для таблиц с ключом партиционирования типаTime. #106202 (groeneai). - Исправлена ошибка, из-за которой часть данных ошибочно помечалась как имеющая повреждённую проекцию, если после легковесного удаления не оставалось части проекции — либо когда проекция перестраивалась и не содержала ни одной строки, либо когда она удалялась (
lightweight_mutation_projection_mode = 'rebuild'/'drop'). Ранее из-за такого состояния для запросов к этой части отключалась оптимизация с помощью проекций. #106273 (tiandiwonder). - Исправлено отставание предупреждений о перегрузке по памяти/CPU/мутациям в
system.warningsна один цикл асинхронных метрик (и их отсутствие в первом цикле). #108035 (alexey-milovidov). - Исправлено исключение
LOGICAL_ERROR(ScatterExchangeStep should have one source shard, got 8) и дублирование строк при запросе к таблицеMergeповерх таблицDistributedили представлений с экспериментальной настройкойmake_distributed_plan = 1. #108401 (groeneai). - Исправлено аварийное завершение сервера (
Sort order of blocks violated) во время слияния, а также некорректное чтение, когда не допускающий NULL элементLowCardinalityстолбцаNullable(Tuple(...))используется как подстолбец (например, в качестве ключа сортировки). #108679 (groeneai). - Исправлен сбой в функции
Base64Decodeвстроенной копии Azure SDK, который мог возникать при вызовеazureBlobStorage()(и связанных табличных функций/хранилищ Azure), если ключ учётной записи не является корректной строкой Base64. Байт>= 0x80приводил к чтению за пределами таблицы декодирования, а любой недопустимый байт вызывал неопределённое поведение при сдвиге влево отрицательного значения (аварийное завершение в сборках с санитайзерами). Теперь недопустимые ключи корректно отклоняются. #108716 (groeneai). - Исправлена ошибка
LOGICAL_ERROR(“New empty part is about to materialize but the directory already exist”), которая могла приводить к аварийному завершению сервера в отладочных сборках и сборках с санитайзерами, когдаDROP/DETACH/MOVE/REPLACE PARTITIONдля таблицы семейства MergeTree выполнялась после того, как предыдущая такая операция была прервана (например, из-за отката транзакции или сбоя) и оставила после себя устаревший каталогtmp_empty_<part>. Теперь такой каталог используется повторно, а не приводит к ошибке. #108879 (groeneai). - Исправлена ошибка, из-за которой проекция возвращала значение по умолчанию для типа столбца (например,
0) вместо значенияDEFAULTиз DDL (например,-1) после истеченияTTLстолбца в широкой части. #109013 (tiandiwonder). - Исправлены сбои запросов
ALTERдля таблицMergeTree, созданных с пользовательской настройкойdisk(SETTINGS disk = disk(...)). #109199 (Michicosun). - Исправлено появление устаревших и удалённых строк при чтении таблиц базы данных
MaterializedPostgreSQLчерез таблицуMerge. #109339 (vdimir). - Исправлено чтение таблиц Paimon, партиционированных по столбцу
BIGINT, значение которого не помещается вInt32. Такие значения партиций усекались (например,9223372036854775807превращалось в-1), из-за чего формировался неверный путь партиции и возникала ошибка файловой системы. #109510 (groeneai). - Исправлена логическая ошибка («Cannot determine row level filter; 0 columns deleted, 0 columns added») при чтении из таблицы
Merge, у дочерней таблицы которой есть политика строк, где фильтром служит просто существующий столбец (например,CREATE ROW POLICY ... USING flag). #109843 (groeneai). - Исправлено: IcebergLocal указывал Azure в качестве типа хранилища. #109872 (PedroTadim).
CHECK TABLEтеперь сообщает о фактическом повреждении части проекции, метаданные которой не удалось загрузить, вместо вводящей в заблуждение ошибкиColumns doesn't match ... Expected: 0 columns. #110262 (Algunenano).- Исправлен сбой запуска сервера для таблиц
MergeTreeна дисках объектного хранилища, возникавший, если у оставшегося файлаtxn_version.txt.tmpповреждены метаданные на уровне диска. #110519 (alexey-milovidov). - Исправлена ситуация, при которой таблицу семейства MergeTree с проекцией
_part_offsetили проекцией порядка коммитов становилось навсегда невозможно подключить, если после отключенияallow_part_offset_column_in_projectionsилиallow_commit_order_projectionтаблицу отсоединяли или перезапускали сервер. Эти две настройки проверяются только при CREATE, поэтому при ATTACH они больше повторно не проверяются. #110570 (groeneai). - Исправлена редкая ошибка
LOGICAL_ERROR(«Unexpected number of parts to remove from parts_queue»), которая могла привести к аварийному завершению сервера сReplicatedMergeTree, когда две операции с партициями (например, два запросаMOVE PARTITION/REPLACE PARTITIONили один такой запрос в гонке с фоновой операциейDROP_RANGE) одновременно отменяли фоновую проверку частей в пересекающихся диапазонах. #110738 (groeneai). - Исправлена логическая ошибка
Hash is not set for serialization, которая могла возникать, если столбец с кодекомQuantized(...)был вложен в сериализацию, использующую пул, — например, в таблицеMergeповерх источников, в которых одноимённый столбец имеет разные типы (объединяемые вVariant). #110776 (groeneai). - Исправлена ошибка
std::length_error(LOGICAL_ERROR) при чтении таблицы семейства MergeTree с аномально большим значениемmax_streams_for_merge_tree_reading(близким к максимумуUInt64) в сочетании сallow_asynchronous_read_from_io_pool_for_merge_tree = 1. Теперь значение этой настройки ограничивается тем же пределом, что иmax_threads. #110936 (groeneai). - Исправлена логическая ошибка
Cannot calculate columns sizes when columns or checksums are not initialized, возникавшая при слиянииMergeTree-таблицы с единственным столбцом, для которого задан полностью истекающийTTLстолбца (приmin_bytes_for_wide_part = 1). #111169 (groeneai). - Теперь, если заданы
min_rows_to_fsync_after_merge/min_compressed_bytes_to_fsync_after_merge/fsync_part_directory, для файлов текстового индекса слитой или материализованной части выполняется fsync. Ранее только эти файлы части оставались несинхронизированными, поэтому при отключении питания сразу после слияния могла остаться закоммиченная, но повреждённая часть, что приводило к потере данных. #111335 (groeneai). - Исправлена работа
OPTIMIZE TABLE ... MANIFESTдля таблицIcebergв случае, когда кортежи партиций в манифесте не соответствуют их спецификации партиционирования #111368 (SmitaRKulkarni). - Исправлены чтение за пределами границ (в релизных сборках) / логическая ошибка (в отладочных сборках) в оптимизации ленивой материализации, а также логическая ошибка в
Pipe::unitePipesдля таблицMerge, возникавшие, когда оптимизация прямого чтения из текстового индекса оставляла неиспользуемый виртуальный столбец индекса в заголовке чтенияMergeTree-таблицы с несколькими индексамиtext. #111467 (groeneai). - Исправлена ошибка
LOGICAL_ERROR(“Part level Min-Max index was constructed from unexpected columns set”), которая могла прерывать фоновое слияние в отладочных сборках и сборках с санитайзерами после понижения значенияpart_minmax_index_columns(например, сwith_block_number_offsetобратно доpartition_key_only). #111511 (groeneai). - Исправлен сбой при чтении
STREAM(enable_streaming_queries = 1) из таблицы, содержащей более одной партиции и имеющей политику строк. В отладочных сборках и сборках с санитайзерами возникала логическая ошибкаFilter column ... not found in DAG outputs, а в релизных сборках мог происходить segfault. #111572 (groeneai). - Исправлена ошибка
LOGICAL_ERROR(Cannot create part with type Compact and storage type Full because table does not support polymorphic parts), возникавшая, когдаMergeTree-таблица загружала ранее созданную частьCompact, хотя её текущие настройки отключают полиморфные части (неадаптивная гранулярность). Это могло происходить, например, когда таблица только для чтения использует общий путь на диске с другой таблицей и перезагружает свои части черезSYSTEM RESTART DISKили при запуске сервера. В отладочных сборках и сборках с санитайзерами это исключение приводит к аварийному завершению сервера. #111626 (groeneai). - При
fsync_part_directory = 1переименование каталога части из временного имени в окончательное теперь также фиксируется надёжно за счёт fsync родительского каталога (а при перемещении между разными родительскими каталогами — и исходного родительского каталога). Ранее fsync выполнялся только для перемещённого каталога, поэтому при отключении питания сразу после коммита части она могла отсутствовать на диске, хотя её файлы уже были записаны, и строки терялись, несмотря на включённую настройку. #111861 (groeneai). - Исправлены неверные результаты и ошибка
LOGICAL_ERRORпри выборке изMergeTree-таблицы столбцаNullable(Tuple(...))вместе с одним из его подстолбцов-элементов, способных содержать NULL (Variant,DynamicилиLowCardinality). При чтении подстолбца строки, равныеNULLв родительском кортеже, помечались какNULLв столбце, который уже стал общим через кэш подпотоков, из-за чего при чтении всего столбца значения оказывались смещёнными. #111949 (groeneai). - Исправлена ошибка, из-за которой hash join терял оптимизации, применяемые после этапа построения (преобразование в хеш-таблицу фиксированного размера, общий runtime-фильтр, переупорядочивание диапазонов правой таблицы), если был настроен порог автоматического сброса на диск, а это поведение по умолчанию начиная с версии 26.5. #111972 (alexey-milovidov).
- Исправлены неверные результаты (строки незаметно пропадали) для
hasAllTokensи других поисков поtext-индексу с несколькими токенами в сборках безsimdcomp(на всех целевых платформах, кроме x86_64 Linux, например aarch64) приtext_index_posting_list_apply_mode = 'lazy'. Переносимый декодер битовой упаковки не записывал декодированные нули для блока с нулевой разрядностью, поэтому элемент списка вхождений, находившийся в сегменте с единственным элементом, отбрасывался. Формат хранения на диске не изменился, и после исправления существующие данные читаются корректно. #112178 (groeneai). - Теперь при загрузке повреждённой статистики MergeTree операции завершаются с ошибкой, а не игнорируют её. #112201 (skuznetsov-clickhouse).
- Исправлена незаметная потеря подтверждённых записей Iceberg в HDFS: коммит Iceberg публикует каждый новый файл метаданных с помощью условной записи, но
HDFSObjectStorageотбрасывал условие и выполнял обычную перезапись, поэтому все конкурентные пишущие стороны получали подтверждение, а снимок одной из них становился недостижимым. Теперь HDFS отклоняет условную запись, поэтому управляемые хранилищем записи Iceberg в HDFS, включаяCREATE TABLE ... ENGINE = IcebergHDFS(...)с явно заданным списком столбцов, завершаются с ошибкой. Чтение это не затрагивает. #112437 (groeneai). - Исправлена ошибка, из-за которой
DELETEв таблицахKeeperMapудалял только первыеmax_block_sizeподходящих строк, но при этом сообщал об успешном завершении мутации. Также исправлена неатомарностьDELETEприkeeper_map_strict_mode = 1: он мог переключаться на удаление без учёта версий и удалять строки, параллельно обновлявшиеся другими операциями, а кроме того, применял подходящие строки поблочно, из-за чего при конфликте удаление могло выполниться лишь частично. #112777 (alexey-milovidov). - Исправлена ошибка, из-за которой временный сбой Azure Blob Storage при чтении или слиянии —
403 Forbiddenиз-за задержки распространения разрешений RBAC, сбой аутентификации по учётным данным или тайм-аут подключения, возвращаемый как408, — ошибочно считался неповторяемым и выдавался какPOTENTIALLY_BROKEN_DATA_PART(Code 740), вызывая ложное критическое оповещение для исправной части. Теперь такие временные сбои считаются допускающими повторную попытку, а действительно постоянный сбой выводится как обычная ошибка Azure, а не как несуществующая повреждённая часть данных. #112871 (arsenmuk). - Исправлена ошибка, из-за которой
listObjectsна диске Azure Blob Storage с конечной точкой, содержащей префикс, возвращал неверные имена blob-объектов на всех страницах, кроме первой, поскольку постраничная выборка обходила клиентскую обёртку, удаляющую префикс конечной точки. Теперь постраничная выборка снова проходит через обёртку с использованием токена продолжения, и имена blob-объектов корректны на каждой странице. #112872 (arsenmuk). - Исправлена потеря minmax-индекса уровня части по
_block_numberи_block_offsetпосле перезагрузки таблицы, если часть была создана мутацией, которая не перезаписывает её целиком. #112878 (alexey-milovidov). - Исправлено исключение (в релизных сборках — ошибка, препятствующая запуску сервера), возникавшее, когда предикат мутации использует табличную функцию
mergeбез явного указания имени базы данных. Теперь используется база данных изменяемой таблицы — так же, как это делается для имён таблиц. #113185 (alexey-milovidov). - Исправлены неверные результаты и ошибка
LOGICAL_ERRORпри чтении подстолбца удалённого и повторно добавленного членаNestedвместе с существующим членом той же группы в таблицеMergeTreeсshare_nested_offsets = 1. Если чтение охватывало более одного блока, существующие члены возвращали значения из последующего блока. #113225 (groeneai). - Исправлено арифметическое исключение в отладочных сборках и сборках с санитайзерами при чтении из таблицы
Mergeс очень большим значениемmax_streams_to_max_threads_ratio: количество потоков усекалось до 32 бит, поэтому значения, кратные2^32, обращались в ноль. Кроме того, если произведение количества потоков для таблицыMergeпревышаетsize_t, теперь выбрасываетсяPARAMETER_OUT_OF_BOUNDвместо неопределённого поведения; устранено переполнение при ограничении количества потоковMergeTreeобъёмом данных; чтение из таблицыMergeотклоняется, если суммарное количество источников превысило бы 65536. #113382 (alexey-milovidov). - Исправлена запись на диск
hdfs: она завершалась ошибкойParent directory doesn't exist, поскольку сгенерированные ключи объектов содержат префикс вложенного каталога, а в HDFS, в отличие от объектных хранилищ, есть настоящие каталоги, и при создании файла отсутствующий родительский каталог не создаётся. #113396 (alexey-milovidov). - Исправлено сообщение об ошибке, выдаваемое, когда табличным функциям
remote/remoteSecureили движкам таблицRemote/RemoteSecureпередаётся несуществующая именованная коллекция вместе с переопределениемkey = value. Такой вызов незаметно повторно разбирался как позиционный, поэтому переопределение анализировалось как выражение данных, а в сообщении об ошибке упоминалось нечто постороннее (например, Function with namemergedoes not exist дляremote(collection, database = merge(...))). Теперь сообщается именно об отсутствующей именованной коллекции. #113510 (groeneai). - Исправлен бесконечный цикл в фоновых слияниях и
OPTIMIZE, когда значениеmerge_max_block_size_bytesбыло меньшеbyteSize()пустого столбца. Пустой столбецLowCardinalityвсё равно содержит словарь, поэтому лимит по байтам мог быть достигнут до слияния хотя бы одной строки; в результате слияние бесконечно порождало пустые блоки, загружая ядро CPU на 100% и так и не освобождая свой слот в фоновом пуле. #113585 (groeneai). - Исправлена ситуация, когда мутация части формата Compact давала разный результат в зависимости от того, находилась ли информация о сериализации части ещё в памяти или была повторно загружена из
serialization.json(если таблица используетserialization_info_version = 'basic'). ВReplicatedMergeTreeиз-за этого две реплики с побайтово идентичной исходной частью записывали разные мутированные части, и мутация завершалась ошибкойCHECKSUM_DOESNT_MATCH. #113588 (groeneai). - Если целевое хранилище не может прочитать файл .lock, при резервном копировании теперь сообщается исходная ошибка доступа к файлу блокировки, а не ошибочно — о параллельном резервном копировании. #113637 (kirillshokhin).
- Исправлена гонка данных между фоновыми задачами таблицы
MergeTree(обновление статистики, обновление частей, загрузка устаревших/неожиданных частей) и уничтожением таблицы. #113722 (alexey-milovidov). - Исправлено чтение не тех таблиц операциями
UPDATEи легковесногоDELETE, когда база данных обновляемой таблицы отличается от базы данных сеанса. Выражение мутации теперь канонизируется относительно базы данных обновляемой таблицы — как для табличной функцииmerge, неявно использующей текущую базу данных, так и для неквалифицированных идентификаторов таблиц. Ранее такие имена разрешались относительно базы данных сеанса, поэтому запрос незаметно обновлял или удалял строки, выбранные из другой таблицы. #113748 (groeneai). - Исправлено исключение при чтении таблицы
MergeTreeпо слоям диапазонов первичного ключа, когда слой порождает пустой конвейер. #114177 (alexey-milovidov). BACKUP,RESTOREиENGINE = Backupтеперь проверяют доступ к расположению резервной копии по привилегиямSOURCESпользователя — так же, как это делаютs3(),file()иazureBlobStorage(). Ранее пользователь с привилегиейBACKUP, но безSOURCESмог записать резервную копию в любое расположение, доступное серверу, и прочитать её оттуда. Теперь для записи резервной копии требуется правоWRITEна источник пункта назначения (WRITE ON S3,WRITE ON AZURE,WRITE ON FILE), а для чтения —READ; пункты назначенияDisk(...)по-прежнему ограничиваются только настройкойbackups.allowed_disk. #114405 (groeneai).- Исправлено чтение таблицы во время выполнения мутации: столбец
MATERIALIZEDмог возвращать устаревшее значение, а его выборка вместе с обновлённым столбцом могла завершаться ошибкой. #114561 (tiandiwonder). - Исправлена логическая ошибка (
Block structure mismatch) при чтении таблицыMergeс включённымmake_distributed_plan, если дочерние таблицы содержат внутренние операции над множествами. #114753 (alexey-milovidov). OPTIMIZE TABLEдля таблицы в объектном хранилище, движок которой не реализует компакцию, сообщал об успешном выполнении, фактически ничего не делая. Теперь возвращается ошибка, как и для любого другого движка, не поддерживающего эту команду. Изменение затрагиваетDeltaLake,Paimon,Hudiи обычные движки объектного хранилища (S3,GCS,COSN,OSS,AzureBlobStorage,HDFSиURLна базе объектного хранилища); поведениеIceberg, который поддерживает компакцию, не изменилось. #114805 (groeneai).- Исправлена ошибка
BAD_DATA_PART_NAME(«Trying to get part name in new format for old format version») для таблицыReplicatedMergeTree, созданной с устаревшим позиционным синтаксисом при включённомallow_deprecated_syntax_for_merge_tree. Мутация могла отображаться как завершённая на реплике, которая её не применила, а таблица после перезапуска могла оставаться в режиме только для чтения. #114980 (groeneai). - Исправлена ошибка
Found patch part ... that intersects mutation with version ...(LOGICAL_ERROR) в таблицах с легковесными обновлениями. Слияние патч-частей могло создать патч, диапазон версий данных которого охватывает версию данных существующей части; такой патч нельзя ни применить, ни пропустить, поэтому все последующие операции над партицией завершались ошибкой, а очередь репликации останавливалась. Такие слияния больше не назначаются. #115064 (alexey-milovidov). - Исправлена проблема, из-за которой сервер не запускался, если движок баз данных
Backupссылался на ставшую недоступной резервную копию (например, если её файлы были удалены или нижележащее хранилище недоступно). Теперь база данных загружается без таблиц и не препятствует запуску всего сервера. #83188 (orloffv). - Исправлено восстановление логирования после ошибки переполнения диска. Ранее при заполнении диска с логами ClickHouse переходил в состояние сбоя и непрерывно засыпал syslog сообщениями об ошибках (иногда записывая более 100 ГБ в час), не восстанавливаясь даже после освобождения места на диске. Теперь система логирования автоматически восстанавливается, как только на диске появляется свободное место, без перезапуска сервера. #93127 (jaehanbyun).
- Исправлено аварийное завершение в обходчике схемы в хранилище DeltaLake. #97112 (kssenii).
Исправления для озёр данных и внешних хранилищ
- Исправлен временный сбой
Code: 499 ... InvalidPart(S3_ERROR) при multipart-загрузках в S3 (например,INSERT INTO ... hits_s3). При вызовеCompleteMultipartUploadMinIO может на короткое время сообщать об отсутствии только что загруженной части; теперь при этой ошибке выполняются повторные попытки, как и при уже обрабатываемой ошибкеNoSuchKey, а их число ограничено параметромs3_max_unexpected_write_error_retries. #109364 (groeneai). - Запросы
ALTER TABLE ... DELETEиALTER TABLE ... UPDATEк таблицам Iceberg, формат файлов данных которых отличается отParquet, теперь отклоняются с понятной ошибкойNOT_IMPLEMENTED, а не приводят к аварийному завершению сервера или незаметному повреждению таблицы. #105893 (groeneai). - Исправлена ошибка
Cannot add column ...: column with this name already existsприINSERT SELECTиз табличной функции, напримерfile,s3илиinput, если один и тот же исходный столбец выбирается несколько раз. #105982 (crakjie). - Конфиденциальные значения, передаваемые в параметрах строки HTTP-запроса (например, при привязке параметров запроса
param_*, таких какparam_secret_key/param_aws_secret_access_key, в параметреpasswordили в параметрахsignatureв стиле S3), больше не записываются как есть вsystem.text_logи в спаны OpenTelemetry. В строке журналаRequest URIзначения параметров с потенциально конфиденциальными именами теперь заменяются на[HIDDEN]. #108475 (groeneai). - Исправлен виртуальный столбец
_etagдля движков таблицS3QueueиAzureQueue: он был объявлен, но не заполнялся, поэтомуSELECT _etagвсегда возвращал пустую строку. Теперь он возвращает ETag объекта, как и движокS3и табличная функцияs3(). #108625 (groeneai). - Запрос на чтение из S3 или запись в S3, отменённый (например, с помощью
KILL QUERY) во время выполнения обращения к S3, теперь помечается как отменённый, а не завершается вводящей в заблуждение сетевой ошибкой или ошибкой S3. В частности, для отменённого резервного копирования в S3 или восстановления из S3 вsystem.backupsтеперь отображается статусBACKUP_CANCELLED/RESTORE_CANCELLED. #108673 (jkartseva). - Исправлен виртуальный столбец
_tagsдля движка таблицS3Queue: он был объявлен, но не заполнялся, поэтомуSELECT _tagsвсегда возвращал пустой словарь. Теперь он возвращает теги объекта, как и движокS3и табличная функцияs3(). #108676 (groeneai). - Исправлена ситуация, когда SHOW TABLES и SELECT … FROM system.tables возвращали разные результаты для баз данных каталогов озёр данных: таблицы, которые ClickHouse не может прочитать, теперь скрываются в обоих случаях. #109273 (SmitaRKulkarni).
- Исправлено аварийное завершение сервера (а в релизных сборках — незаметно оставшийся нефинализированным файл данных), возникавшее, если
INSERTв таблицу Delta Lake (DeltaLakeLocal/deltaLake) завершался ошибкой после того, как приёмник уже начал запись, например когда исходный запрос выбрасывал исключение посреди вставки или запрос отменялся. #109328 (groeneai). - Исправлена ошибка
Not found column or subcolumn c.null in block(иBad cast from ColumnConst to ColumnNullableв отладочных сборках и сборках с санитайзерами) при выполненииWHERE col IS NULL/IS NOT NULLдля столбца Iceberg, добавленного в ходе эволюции схемы уже после записи более старых файлов данных, приoptimize_functions_to_subcolumns=1(значение по умолчанию). #109515 (groeneai). - Исправлена ошибка
Host is empty in S3 URI, возникавшая при использовании скалярного подзапроса в качестве аргумента URL табличной функцииs3(или аргумента любой другой табличной функции) в запросахCREATE TABLE ... AS SELECT: теперь скалярные подзапросы в аргументах табличных функций вычисляются на этапе анализа запроса. #110254 (CheSema). - Исправлена логическая ошибка (аварийное завершение сервера в отладочных сборках и сборках с санитайзерами) при выполнении для таблицы Iceberg
ALTERс несколькими командами, напримерUPDATE ..., DELETE .... Теперь такие мутации отклоняются с понятной ошибкойNOT_IMPLEMENTED. #110347 (groeneai). - Исправлено появление дублирующихся ID полей в таблицах Iceberg после
ALTER TABLE ... ADD COLUMN, если исходная схема содержит вложенные поля (Tuple/Array/Map). Теперьlast-column-idхранит максимальный назначенный ID поля с учётом вложенных дочерних полей, поэтому добавленный впоследствии столбец больше не получает повторно ID вложенного поля, а чтение больше не завершается ошибкойICEBERG_SPECIFICATION_VIOLATION(Duplicate field id). #110884 (groeneai). - Исправлена ситуация, когда
DELETE/UPDATEдля таблицы Iceberg молча удаляли не те строки (или выбрасывалиNOT_FOUND_COLUMN_IN_BLOCK), если таблица содержит файлы данных, записанные как до, так и послеALTER TABLE ... ADD COLUMN, и включён параметрoptimize_move_to_prewhere. #111693 (groeneai). - Исправлена ошибка, из-за которой значение
made_current_atвsystem.iceberg_historyстановилось равным1970-01-01для сохранённого снимка после выполненияALTER TABLE ... EXECUTE expire_snapshotsдля таблицы Iceberg. Также исправлена ситуация, когдаsystem.iceberg_historyне возвращала строк для таблицы, в метаданных которой отсутствуетsnapshot-log. #111781 (groeneai). - Исправлено повреждение данных при вставке в таблицу Iceberg через
MATERIALIZED VIEW. Файл данных записывался с типами столбцов целевой таблицы, заданными приCREATE, а не с её актуальной схемой Iceberg, поэтому значениеDateTimeсохранялось как простой Avrointи при чтении интерпретировалось как микросекунды, а приDateTime64(0)илиDateTime64(9)файл и вовсе невозможно было прочитать. Как следствие,INSERT INTO <materialized view>для целевой таблицы, схема Iceberg которой шире объявленных столбцов представления, теперь завершается ошибкойTYPE_MISMATCHвместо записи повреждённой строки. #112359 (groeneai). - Исправлена запись в таблицы Iceberg, схема которых содержит кортеж, вложенный в другой кортеж. В публикуемых метаданных таблицы имена полей внутреннего кортежа заменялись позиционными именами
1,2, …, поэтому при формате по умолчаниюParquetоперацияINSERTзавершалась ошибкойINCORRECT_DATA, а приAvroстолбец невозможно было прочитать. #112480 (groeneai). - Исправлена взаимоблокировка, которая намертво блокировала базу данных
FilesystemилиHDFS, когда два запроса одновременно разрешали одно и то же имя таблицы. Все последующие запросы к этой базе данных зависали навсегда без возможности прерывания, и для восстановления приходилось перезапускать сервер. #112495 (groeneai). - Исправлена ситуация, когда таблицы
DeltaLakeвозвращали слишком мало строк, если предикат в предложенииWHEREсодержал подNOTподвыражение, которое транслятор предикатов delta-kernel не может обработать. Теперь такое подвыражение передаётся в delta-kernel как явно неизвестный предикат, а не как конец дочернего итератора, из-за чего раньше охватывающая конъюнкция молча усекалась. #112652 (groeneai). - Исправлена ошибка, из-за которой
ALTER TABLE ... EXECUTE remove_orphan_filesудалял действующий файлmetadata/version-hint.textтаблицы Iceberg. Запись для этого файла в множестве достижимых файлов формировалась конкатенацией строк в расчёте на завершающую косую черту, которой в значении никогда не бывает. Поэтому реальный файл подсказки не считался достижимым и удалялся, как только становился старше порогаolder_than. Приiceberg_use_version_hint = 1таблица после этого полностью переставала читаться. #113548 (groeneai). - Исправлена ошибка
LOGICAL_ERRORпри фильтрации по столбцу Iceberg, который сталNullableпослеALTER TABLE ... MODIFY COLUMN. #114521 (groeneai). - Исправлена ситуация, когда
ATTACH TABLEс определениемENGINE = URL(...)не проверял привилегиюTABLE ENGINEдля движка, на который перенаправляет схема URL. Пользователь, имеющий толькоTABLE ENGINE ON URL, мог подключить, а затем читать таблицу на основеFile,S3,AzureBlobStorageилиHDFS, хотяCREATE TABLEв таком случае корректно отклоняется. #115914 (groeneai). - Исправлены сбои исходящих HTTP-запросов (например, `aiGenerate`, табличная функция `url`, S3) с ошибкой `No route to host` на хостах, публикующих адреса как IPv4, так и IPv6, когда маршрутизируемо только одно семейство адресов. Теперь при сетевой ошибке на первом адресе пул HTTP-соединений переключается на следующий разрешённый адрес, а не возвращает ошибку сразу при первом же запросе. #103786 (alexey-milovidov).
- Добавлена возможность читать Avro
arrayиз записей с двумя полями{key, value}в столбец ClickHouse типаMap. Именно такое кодирование Iceberg и Spark используют дляMAP<K, V>с нестроковым ключом (нативные map в Avro поддерживают только строковые ключи). Ранее такой файл можно было прочитать какArray(Tuple(key, value)), но не какMap(K, V)— в этом случае возникала ошибкаType Map(...) is not compatible with Avro array. #109289 (groeneai). - Исправлено чтение таблицы Iceberg с файлом метаданных, номер версии которого состоит только из цифр, но выходит за пределы диапазона 32-битного целого (например,
v99999999999999999999.metadata.json). Ранее такое имя приводило к малоинформативному исключениюstd::out_of_range(STD_EXCEPTION) вместо понятной ошибкиBAD_ARGUMENTS. #109619 (groeneai). - Исправлено имя файлов метаданных Iceberg, сжатых gzip. ClickHouse записывал их как
v{N}.gzip.metadata.json(по токену HTTPContent-Encoding), тогда как спецификация Iceberg предполагает расширениеgz:v{N}.gz.metadata.json. Из-за этого Spark и другие считыватели каталога Hadoop не находили метаданные, записанные ClickHouse. Теперь ClickHouse записываетv{N}.gz.metadata.json, а для обратной совместимости по-прежнему читает устаревшее имя сgzip. #109812 (groeneai). - Исправлена ошибка, из-за которой таблица Iceberg с форматом записи
Avroсериализовала поле, объявленное как"required": falseи имеющее типlist,mapилиstruct, как обязательное, без union["null", T]. В результате собственная схема файла данных расходилась с метаданными таблицы, и другие считыватели Iceberg видели поле как обязательное. Теперь такое поле записывается как union["null", T], который спецификация Iceberg использует для необязательных полей. #112648 (groeneai). - Исправлена ошибка, из-за которой
made_current_atвsystem.iceberg_historyпоказывал самое раннее время, когда снимок становился текущим, а не самое позднее, если один и тот жеsnapshot-idвстречается в Icebergsnapshot-logболее одного раза (как бывает после отката). #113598 (groeneai). - Исправлено зависание продолжительностью до одного часа в
BACKUP/RESTORE ... TO S3, на дисках GCS и в табличной функцииs3, если именованная коллекция задаётhttp_client = 'gcp_oauth', а конечная точка выдачи токенов Google OAuth2 принимает соединение, но так и не отвечает. Запрос Bearer-токена больше не наследует таймаут запроса передачи данных вызывающей стороны: время ожидания ответа теперь ограничено 10 секундами — так же, как для запроса STSAssumeRole. #115531 (groeneai). - Исправлена логическая ошибка в файловом кэше (
Expected file ... not to exist), которая могла возникать, если фоновая загрузка в кэш завершалась сбоем с исключением, отличным отErrnoException(например, при выполненииOPTIMIZEдля таблицы Iceberg), и после неё оставался пустой осиротевший файл кэша. #110549 (groeneai). - Исправлена ошибка, из-за которой кэши с ограничением по максимальному числу записей (политика
SLRU) незаметно переставали принимать новые записи, как только такое же число записей было запрошено хотя бы дважды. Затронуты кэши файлов метаданных Iceberg и Paimon, кэш метаданных Parquet, кэши текстовых индексов, кэш индексов векторного сходства, кэш скомпилированных выражений и кэш статусов файлов ObjectStorageQueue. #115517 (groeneai). - Исправлено чтение таблиц Paimon, которое могло завершаться сбоем при одновременной замене изменяемой подсказки
snapshot/LATEST. Если подсказка недействительна или устарела, теперь выполняется безопасный переход к получению списка снимков. #112010 (JiaQiTang98). - Теперь выводится реальное исходное исключение, если zip-архив не удаётся распаковать из-за того, что входной буфер (например, буфер чтения S3 с
restricted_seek = true) отклоняет запрошенную minizip операцию seek или чтения. Ранее фактическая ошибка скрывалась за общим сообщениемCouldn't unpack zip archive: Code = -100/Couldn't open zip archive. #105103 (groeneai). - Исправлена запись в Iceberg для метаданных без refs #106896 (AVMusorin).
- Исправлено исключение при вставке в таблицу Iceberg, метаданные которой созданы внешним движком и не содержат необязательных массивов
snapshots,metadata-logилиsnapshot-log. Теперь такие вставки выполняются успешно. #107473 (tiandiwonder). - Исправлена ошибка
ReadBuffer is canceled. Can't read from it., которая могла возникать при повторной попытке загрузки в S3 (например, резервной копии) после временной ошибки чтения. #108573 (groeneai). - Исправлена ошибка
std::future_error(«The associated promise has been destructed prior to the associated state becoming ready»), которая могла возникать (а в отладочных сборках и сборках с санитайзерами — приводить к аварийному завершению сервера), если не удавалось запланировать финальную асинхронную задачу завершения multipart-загрузки в S3/Azure (например, при исчерпании пула потоков). Теперь вместо неё выводится реальная ошибка планирования. #108730 (groeneai). - Исправлено чтение временных меток ORC, выходящих за пределы ~2262 года, в столбец
DateTime64с масштабом меньше 9. Нативный считыватель ORC ранее преобразовывал каждую временную метку через промежуточный типDateTime64(9), который при наносекундном масштабе вызывает переполнениеInt64, и отклонял такие значения с ошибкойVALUE_IS_OUT_OF_RANGE_OF_DATA_TYPE, даже если запрошенный масштабDateTime64(например,DateTime64(6), который создаёт Iceberg) позволяет представить это значение. Теперь временные метки читаются сразу в запрошенном масштабе, а настройкаdate_time_overflow_behaviorучитывается, если значение не помещается даже в целевой масштаб. #109302 (groeneai). - При чтении таблицы Paimon, схема которой содержит неподдерживаемый вложенный тип (например, поле
ROW), теперь выдаётся понятная ошибкаBAD_ARGUMENTSс указанием неподдерживаемого типа вместо пустогоDB::Exception. (OK)с кодом ошибки 0 и без сообщения. #109762 (groeneai). - Исправлено чтение таблиц Iceberg, партиционированных по одному и тому же исходному столбцу более одного раза (например,
PARTITIONED BY (hours(ts), ts)). Ранее при чтении таких таблиц возникала ошибкаCannot add column ...: column with this name already exists (ILLEGAL_COLUMN). #109895 (groeneai). - Файлы данных, записываемые ClickHouse в таблицы Iceberg, теперь содержат идентификаторы полей Iceberg для форматов Avro (
field-id) и ORC (атрибуты типаiceberg.id/iceberg.required), а столбцыStringв ORC записываются как ORCstring, а не как двоичные данные. Ранее идентификаторы полей встраивались только в Parquet, поэтому считыватели, соответствующие спецификации (например, Spark/iceberg-java), после переименования столбца молча возвращали NULL для строк Avro, записанных ClickHouse, а ORC-файлы, записанные ClickHouse, не могли прочитать вовсе. #109994 (groeneai). - Исправлена логическая ошибка
ChunkInfoRowNumbers does not existпри выполненииOPTIMIZE TABLEдля таблицы Iceberg, содержащей файл данных в формате, отличном от Parquet (например,ORC), который новее всех файлов позиционного удаления. #110107 (alexey-milovidov). - Исправлено чтение больших файлов
Parquetиз несжатых записей zip-архива типаSTOREDчерезs3иfile. #110495 (Gudauu). - Сбой запуска фонового пула планировщика (например, пула
icebergпри исчерпании глобального пула потоков) больше не приводит к аварийному завершению сервера: теперь такая ошибка является восстанавливаемым исключением. Кроме того, чтениеsystem.background_schedule_poolбольше не создаёт эти пулы как побочный эффект. #111209 (groeneai). - Исправлена аутентификация DLF в REST-каталоге Paimon: подпись запроса вычислялась один раз и затем использовалась повторно, поэтому все запросы к каталогу, кроме первого, завершались ошибкой HTTP 401, а SHOW TABLES возвращал пустой список. Также исправлено распознавание HTTP 404 при проверке существования таблицы. #112015 (JiaQiTang98).
- Исправлена ошибка
LOGICAL_ERROR(partitions_count > 0) при партиционировании фрагментов данныхIceberg, ставших пустыми после позиционных удалений, например при компактизации партиционированной таблицыIcebergс полностью удалёнными файлами данных. #112432 (PedroTadim). - Исправлена ошибка, из-за которой при пакетном удалении объектов в Azure события Delete не записывались в
system.blob_storage_log, если сбоем завершался сам пакетный запрос, и в результате весь батч не попадал в лог. Теперь при сбое на уровне батча событие Delete записывается для каждого объекта. #112873 (arsenmuk). - Исправлено чтение таблиц
Paimon, партиционированных по столбцуTIMESTAMPс точностью выше миллисекунд, которое завершалось ошибкой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, метаданные которой описывают изменение схемы, запрещённое спецификацией Iceberg, больше не приводит к аварийному завершению сервера. Четыре нарушения спецификации в
IcebergSchemaProcessorлибо сообщались какLOGICAL_ERROR, что трактуется как сработавший assert, либо без какой-либо проверки доходили до фатального assert; теперь в этих случаях выбрасывается ошибкаICEBERG_SPECIFICATION_VIOLATION. #114518 (groeneai). - Исправлена ошибка, из-за которой виртуальный столбец
_timeтабличных функцийurl/urlClusterв сборках на основе musl всегда имел значениеNULL; причиной был непереносимый разбор HTTP-заголовкаLast-Modified. #111619 (thevar1able). - Исправлена ошибка, из-за которой сервер не запускался после создания таблицы с помощью
CREATE TABLE ... AS url('http://host/**/', ...)при включённой настройкеallow_experimental_url_wildcard_from_index_pages. При загрузке метаданных такой таблицы проверка экспериментальной функциональности выполнялась повторно и завершалась ошибкойSUPPORT_IS_DISABLED, что прерывало запуск. #115095 (groeneai). - Таблица движка баз данных
URLбольше не раскрывает пользователю без grant на чтение источника, существует ли локальный файл: ниEXISTS TABLE, для которого требуется лишь привилегияSHOW TABLES, ни разрешение имени таблицы больше не обращаются к файловой системе до подтверждения grant. #113029 (alexey-milovidov). query_masking_rulesтеперь применяются к сообщениям, добавляемым черезException::addMessage, поэтому при настроенных правилах маскирования URL-кодированные учётные данные в суффиксах(in file/uri ...)из ошибокjdbc()/odbc()больше не утекают. #106916 (gaurav0107).
Исправления в форматах и ингестии
- При чтении данных Arrow
time32/time64без схемы (например,SELECT * FROM file(..., 'Arrow')) теперь выводится типTime64вместоDateTime64. Ранее выводилсяDateTime64. Всё, что на последующих этапах обработки рассчитывает на прежний выведенный тип, перестанет работать после обновления. Также добавлена поддержка экспортаTime/Time64в Arrow: соответствующий тип времени Apache Arrow выбирается в зависимости от точности. #104316 (Maoyao233). - Исправлены возможные неверные результаты и чтение за пределами границ при откате
INSERTпосле ошибки в середине пакета (например, в таблицахBuffer, при асинхронных вставках или в движкахKafka/RabbitMQ/FileLog), когда включена отложенная репликация столбцов (enable_lazy_columns_replication). #108935 (groeneai). - Исправлена несогласованность парсера: список столбцов в
INSERTпринимал квалифицированный сопоставитель столбцов видаt.* LIKE '<pattern>'/t.* ILIKE '<pattern>', но отклонял его каноническую формуt.COLUMNS('<regexp>'). Из-за этого нарушалась обратимость форматирования запроса, а в отладочных сборках и сборках с санитайзерами сервер аварийно завершался. #109176 (groeneai). - Исправлена ошибка
IncorrectEndpointError(HTTP 400) приINSERTв таблицуDataLakeCatalogMicrosoft Fabric / OneLake: операции записи ADLS Gen2 (DFS) теперь направляются на хост конечной точки.dfsвместо хоста.blob. Примечание: при использованииremote_url_allow_hostsдля работыINSERTв список разрешённых необходимо добавить оба хоста Fabric —.blob(чтение) и.dfs(запись). #110290 (zlareb1). - Исправлена запись через табличные функции озёр данных (например,
INSERT INTO FUNCTION icebergS3(...)): в создаваемых файлах Parquet строковые столбцы теряли аннотацию типаString, из-за чего внешние системы, такие как Spark, не могли прочитать записанные данные. Теперь такая запись использует те же настройки формата, что и запись через движок таблицы. #110465 (tiandiwonder). - Исправлена ошибка, из-за которой таблица
system.session_logстановилась нечитаемой после входа через Arrow Flight: столбецinterfaceимеет типEnum8, но в его перечислении отсутствовало значениеArrowFlight. Поэтому при входе по протоколу Arrow Flight записывалось необработанное значение10, а любойSELECT, читающий такую строку, завершался исключениемUnexpected value 10 in enum. #110758 (alexey-milovidov). - Исправлен вывод схемы для семейства форматов
TSV: для десятичного значения с ведущим нулём, например0.0или0.5, выводился типString, тогда какCSVкорректно выводитFloat64. Кроме того, первая строка с такими значениями ошибочно распознавалась механизмом автоопределения заголовкаTSVкак заголовок и пропадала из результата. Также исправлена ошибка, при которойTSKVвыводил числовой тип для значения, записанного с escape-последовательностью, напримерx=1\x2E5, после чего это значение не удавалось разобрать. Для значений, в которых ведущий ноль служит дополнением целого числа, например007, по-прежнему выводитсяString, поскольку парсер значенийTSVне может прочитать их обратно. #112226 (groeneai). - Исправлена ошибка, из-за которой автоматический вывод схемы предлагал числовой тип для текстовых значений, которые парсер значений не может прочитать обратно. При выводе допускались висячая экспонента (
1e+), отсутствующая мантисса (.) или повторяющийся знак (++inf), которые затем отклонялись функциейreadFloatTextPreciseс ошибкойCANNOT_PARSE_NUMBERпри чтении данных по выведенной схеме; для столбцаDynamicэто приводило к ошибке во время INSERT. Теперь при выводе число проверяется тем же парсером, который фактически используется при чтении. Это также устраняет случай, когда выведенный тип зависел отmax_read_buffer_size, и позволяет корректным формам экспоненты с ведущим нулём, таким как0e5, выводиться какFloat64в TSV — так же, как это уже происходит в CSV. Кроме того, исправлена обработка некорректных форм экспоненты. #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, а геттер дляTemplateтеперь использует правило экранирования собственного формата строк. #113533 (groeneai). - Исправлено форматирование аргумента-подзапроса табличных функций
viewиviewIfPermitted, когда внешний запрос содержит завершающее предложениеSETTINGS. Такой запрос форматировался какview((SELECT ...)), что невозможно разобрать обратно, поэтому запрос не проходил внутреннюю проверку «форматирование — разбор — форматирование» и завершался ошибкойInconsistent AST formatting. #114658 (groeneai). - Исправлено ошибочное распознавание данных JSON как TSKV при автоматическом определении формата. #106009 (Avogar).
- Экспорт значений
Time/Time64за пределами допустимого времени суток (отрицательных или>= 24h) в форматArrowтеперь отклоняется с понятной ошибкой, а не приводит к записи некорректных данных Arrowtime32/time64. #107179 (tiandiwonder). - Исправлено чтение файлов
Arrow,ArrowStreamиORCна основе Arrow, у которых столбец временной метки содержит в качестве часового пояса фиксированное числовое смещение от UTC (например,+05:30,-08:00,00:00) или не относящийся к IANA маркерfixed; ранее такое чтение завершалось ошибкойCannot load time zone ...(BAD_ARGUMENTS). #108633 (groeneai). - Столбец
Nullable(Tuple(...))теперь сериализуется как одно поле CSV, а не разворачивается в отдельные столбцы. Ранее значение, отличное от NULL, записывалось как несколько полей CSV, аNULL— как одно\N, из-за чего число столбцов зависело от строки, что ломало заголовкиCSVWithNames/CSVWithNamesAndTypesи повторное чтение записанных данных. #108959 (groeneai). - Исправлено чрезмерное выделение памяти при автоматическом определении схемы для формата
MsgPack: если в повреждённых или сгенерированных фаззером входных данных заголовок массива/map/строки/бинарных данных указывает огромное число элементов, это больше не приводит к единовременному выделению нескольких гигабайт памяти (теперь такие данные отклоняются как некорректные). Это устраняет аварийное завершениеallocation-size-too-bigпри работе с санитайзерами и нехватку памяти в релизных сборках. #109019 (groeneai). - Исправлена ошибка
LOGICAL_ERRORпри записи столбцаLowCardinality(Time)в форматArrowсoutput_format_arrow_low_cardinality_as_dictionary = 1. #109730 (groeneai). - Исправлено чтение повреждённого потока в формате
Native, в котором количество типовDynamicили количество путейJSON/Objectблизко кSIZE_MAX: такие некорректные входные данные теперь отклоняются с понятной ошибкойINCORRECT_DATAвместо неперехваченного исключенияstd::length_error. #110590 (alexey-milovidov). - Исправлена ошибка
LOGICAL_ERROR: Cannot sum Bools(аварийное завершение сервера в отладочных сборках и сборках с санитайзерами) при слиянии состояний агрегатных функцийsumMap/sumMapWithOverflow/sumMapFilteredсо значениямиBool, сериализованными в старом формате состояния (версия 0). Это же исправление устраняет два случая, когда для состоянийBoolверсии 0 без каких-либо ошибок возвращался неверный результат: ключи map типаBoolне дедуплицировались между состояниями, а при удалении нулевых значений отбрасывались не те записи. #110922 (groeneai). - Исправлена ошибка, из-за которой табличная функция
formatгенерировала исключениеNOT_FOUND_COLUMN_IN_BLOCK, если при разборе входных данных получалось ноль строк (например, пустой JSON или GeoJSONFeatureCollectionбез объектов). Теперь возвращается пустой результат с корректными столбцами. #111428 (groeneai). - Теперь можно читать файлы GeoParquet, Arrow и ArrowStream, в которых столбец геометрии в кодировке WKT содержит ключевое слово типа не в верхнем регистре (
point(1 2)) или пустой контейнер (LINESTRING EMPTY,POLYGON(),POLYGON(())). Ранее импорт таких файлов завершался ошибкойBAD_ARGUMENTSилиCANNOT_PARSE_NUMBER, хотя те же строки успешно разбираются функциейreadWKT. Также исправлено обратное чтение файла, в котором хранится результатwktдля пустой геометрии, записываемый какLINESTRING(). #112020 (groeneai). - Исправлена ошибка
Unknown compression method, возникавшая для подсказок сжатияautoиnone, записанных в любом регистре, кроме полностью нижнего, напримерfile('data.csv.gz', 'CSV', 'x String', 'AUTO'). Имена кодеков, такие какGZIP, и раньше принимались без учёта регистра; теперь эти две специальные подсказки ведут себя так же. #113631 (groeneai). - Исправлено чтение столбца
Tuple, первый элемент которого равенNULL, в форматахCustomSeparated,RegexpиTemplateс правилом экранированияCSV. В этих форматах простой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). - Исправлена логическая ошибка
Inconsistent AST formatting(аварийное завершение сервера в отладочных сборках и сборках с санитайзерами) для выраженийCREATE INDEX/CREATE HYPOTHETICAL INDEX, которые не выдерживали цикл «форматирование — разбор — форматирование», напримерCREATE HYPOTHETICAL INDEX i0 ON t0 ((a())) TYPE aиCREATE INDEX i0 ON t0 ((a, b).1) TYPE minmax. #109175 (groeneai). - Исправлена логическая ошибка (
Logical error: 'KeyCondition uses PREWHERE output') в ридере Parquet v3, возникавшая, когда ключевое условие на уровне формата ссылалось на столбец, который не читается из файла Parquet. #109267 (groeneai). - Исправлено исключение в предопределённом HTTP-обработчике при отсутствии заголовка #108324 (vitlibar).
- Исправлена возможная ошибка
Logical error: 'ReadBuffer is canceled. Can't read from it.', возникавшая, когда построчный входной формат (например,TSV/CSV) не мог разобрать входные данные, а нижележащее чтение уже было отменено (например, из-за некорректного HTTP-чанка или усечённого тела запроса). При формировании подробной диагностики разбора больше не выполняется чтение из отменённого буфера. #109708 (groeneai). - Формат
Valuesбольше не записывает ошибки разбора вsystem.errorsиsystem.error_log, когда потоковый разбор успешно переключается на разбор SQL-выражений. #111141 (pamarcos). - Исправлена ситуация, когда
SYSTEM REFRESHдля остановленной таблицыRabbitMQиногда не обрабатывал накопившиеся в очереди сообщения. REFRESH разрешает ровно один внеочередной цикл стриминга, однако этот цикл мог сразу завершиться без строк, поскольку цикл доставки AMQP только что был асинхронно запущен; в результате единственное разрешение расходовалось впустую, а сообщения оставались необработанными до следующегоSYSTEM START. #111480 (groeneai). - Исправлена ситуация, когда таблица
NATSс заданнымnats_streamпосле перезапуска сервера NATS молча переставала получать сообщения. Теперь подпискаJetStreamвосстанавливается автоматически, без необходимости выполнятьDETACH TABLEиATTACH TABLE. #112828 (groeneai). - Чрезмерно большое значение
kafka_num_consumersтеперь отклоняется с понятной ошибкой, а не приводит к сбою выделения памяти внутри движка таблицыKafka. Ранее при включённой настройкеkafka_disable_num_consumers_limitтакое значение вызывало исключениеstd::length_error. #114764 (alexey-milovidov). - Сервер Arrow Flight: теперь принимаются учётные данные аутентификации
Basic, закодированные в Base64 без дополнения (padding), которые отправляют клиенты Flight на Go, например драйвер ADBC Flight SQL; кроме того, при некорректном заголовкеauthorizationвозвращается полноценная ошибка аутентификации вместо общей ошибкиUnexpected error in RPC handling. #115085 (alexey-milovidov). - Сервер Arrow Flight: теперь отклоняются некорректные учётные данные Basic-аутентификации, в которых отсутствует разделитель между именем пользователя и паролем. #115347 (alexey-milovidov).
Исправления в типах данных, функциях и сериализации
- Исправлена логическая ошибка
Stream <col>.variant_discr ... is not found(аварийное завершение сервера в отладочных сборках и сборках с санитайзерами), возникавшая, когдаALTER TABLE ... MODIFY COLUMNменяет тип столбца на тип с динамическими подстолбцами (например,VariantнаDynamic) в таблице с частями формата Wide, а затем эта часть читается или участвует в слиянии. #110204 (groeneai). - Исправлено чтение подстолбца столбца
Nullable(Tuple(...)), элемент которого имеет типLowCardinality(T)без поддержки NULL, если тот же запрос также читает родительский подстолбец. В части формата Compact родительский подстолбец возвращал неверные значения, запрос завершался ошибкойUnexpected return type from assumeNotNullили сервер аварийно завершался из-за защитной проверкиstring_view: извлечённый подстолбец десериализовался в буферLowCardinality(Nullable(T)), подпотоки которого затем совместно использовались при чтении родительского подстолбца. #112232 (groeneai). - Исправлены ошибка
LOGICAL_ERROR«Not-ready Set is passed as the second argument for functionglobalNullIn» и потеря исходного сообщения об ошибке запроса. Это могло происходить, когда при отсечении частей на основе статистики во время анализа индексов спекулятивно выполнялся подзапросIN/GLOBAL INи этот подзапрос завершался ошибкой. #114121 (groeneai). - Исправлена ошибка
Cannot read all data of type FixedStringпри чтении подстолбцаproduct_quantization_codebookстолбца с кодекомQuantized('product', ...). Кодовая книга каждой части записывается после данных всех гранул и потому не ограничена метками, поэтому при чтении с диапазоном меток, заканчивающимся до последней метки части, она могла быть прочитана не полностью. #112818 (alexey-milovidov). - Для значений
Mapвнутри столбцаDynamicбольше не записываются части, структураMapкоторых противоречит их собственным метаданным. Таблицы, отличающиеся только параметромmap_serialization_version, совместно использовали один кэшированный объект сериализации, поэтому часть могла получить структуру Mapbasic, хотя в её метаданных была указанаwith_buckets, и последующее чтение завершалось ошибкойLOGICAL_ERROR: Stream ...buckets_info ... is not found. Части, уже записанные таким образом предыдущими версиями, остаются нечитаемыми и подлежат удалению. #113514 (groeneai). - Исправлена ошибка, из-за которой кодеки
ALP,FPCиGCDне учитывали в своём хеше параметр, производный от типа. В части формата Compact механизм записи использует один сжатый поток на каждый уникальный хеш кодека, поэтому два столбца с разной шириной значений и одним и тем же кодеком конфликтовали и совместно использовали один объект кодека с неверной шириной. В результате при несовпадении ширин корректные вставки отклонялись с ошибкойCANNOT_COMPRESS, а в остальных случаях один из столбцов сжимался хуже, чем следовало. #114189 (groeneai). - Исправлено некорректное отсечение по индексу, когда ключ сортировки таблицы оборачивает столбец
DateвtoDateTime(например,ORDER BY toDateTime(date_column)), а запрос фильтрует по исходному столбцу с помощью сравнения видаWHERE date_column >= '...'.toDateTime(Date)переполняется для значенийDateза пределами диапазонаDateTime(после2106-02-07), поэтому сохранённый ключ немонотонен. ClickHouse больше не использует отсечение по первичному ключу для такой комбинации ключа и предиката, так как это могло привести к пропуску гранул с подходящими строками. #101814 (nihalzp). - Исправлен сбой
ALTER MODIFY COLUMNпри преобразовании столбцаNullableсDEFAULTв другой тип (например,Nullable(UInt8)→String,LowCardinality(String)илиArray(UInt8)). #102156 (il9ue). - Исправлено некорректное экранирование SQL-литералов в
StorageSQLiteи табличной функцииsqlite()при передаче предикатовWHEREв SQLite: одинарные кавычки и управляющие символы (\n,\r,\t,\) экранировались обратной косой чертой, которую SQLite не интерпретирует, что приводило к синтаксическим ошибкам или неверным результатам запросов. Также исправлено экранирование строковых литералов, передаваемых в PostgreSQL: строки, вложенные в спискиIN, сохраняли экранирование ClickHouse, а управляющие символы отправлялись в виде последовательностей с обратной косой чертой, которые PostgreSQL интерпретирует как другие байты. #104217 (tiandiwonder). - Исправлено исключение
NOT_FOUND_COLUMN_IN_BLOCKв запросахINNER JOIN ... ON arrayJoin(...) = ..., возникавшее, когда включена настройкаquery_plan_convert_join_to_in, а SELECT ссылается на исходный столбец типа Array. #104809 (tiandiwonder). - Исправлена работа выражений IN и NOT IN с неконстантными правыми операндами, ссылающимися на столбцы текущей строки; обработка правого операнда-кортежа в новом анализаторе приведена в соответствие с существующей семантикой IN в ClickHouse. В старом анализаторе исходный столбец в качестве правого операнда (
x IN (arr)) по-прежнему разрешается как имя таблицы и остаётся вне области видимости. #104993 (niyue). - Исправлен
JOINс таблицамиEmbeddedRocksDB,RedisиKeeperMap, который мог без каких-либо предупреждений возвращать пустой результат при использованииDirectKeyValueJoinс ключами типаStringилиNullable(String). #105253 (vdimir). - Исправлена ошибка
LOGICAL_ERROR(“Unexpected expression in JOIN ON section. Expected boolean (UInt8), got ‘Nothing’”), возникавшая, когда предикат неэквисоединенияJOIN ... ONссылается на столбец типаNothing, например полученный с помощьюARRAY JOIN []. #106981 (groeneai). - Исправлена логическая ошибка
Inconsistent AST formatting, которая могла приводить к аварийному завершению сервера в отладочных сборках и сборках с санитайзерами, если лямбда-выражение с псевдонимом использовалось как операнд оператора доступа (элемент кортежа.Nили элемент массива[]) не на первой позиции списка выражений, напримерSELECT 1, ((p0, p1) -> p0 AS a7).4[3] FROM t. #107092 (groeneai). - Кластерная табличная функция (
urlCluster,fileCluster,s3Cluster, …), вложенная в другой распределённый запрос, напримерclusterAllReplicas(..., urlCluster(...)), теперь отклоняется с ошибкойBAD_ARGUMENTS, а не завершается логической ошибкой (Distributed task iterator is not initialized). #107107 (groeneai). - Исправлен сбой табличной функции
valuesс ошибкойARGUMENT_OUT_OF_BOUNDпри использовании десятичного литерала, который не может быть точно представлен в столбце с плавающей запятой меньшей точности (например,0.1для столбцаFloat32):SELECT * FROM values('x Float32', 0.1). Теперь такие значения принимаются и преобразуются в ближайшее представимое значение — так же, как вCASTиINSERT ... VALUES. #108055 (alexey-milovidov). - Исправлена потеря
LowCardinalityв типах ключей и значенийMapфункциямиmapFilter,mapSort(и её вариантами) иmapConcat. РанееmapFilterдля столбцаMap(LowCardinality(String), String)возвращалаMap(String, String), что могло повредить метаданные таблицы, созданной черезCREATE TABLE ... AS SELECT, и приводить к сбоюCHECK TABLE. #108057 (alexey-milovidov). - Исправлена ошибка, из-за которой отменённый или завершённый через
KILLзапросINSERTпродолжал долго выполняться при построении skip-индекса (например, неограниченного индексаset(0)на столбце с высокой мощностью). Теперь при отмене запроса построение индекса сразу прекращается. #108351 (tiandiwonder). - Исправлена ошибка, из-за которой
SELECTиз табличной функцииprimesне реагировал на отмену: при большом значенииstep(илиlimit) запрос мог ещё долго выполняться послеKILL QUERYили тайм-аута. Теперь он сразу прекращается. #108353 (tiandiwonder). - Исправлен разбор имён типов данных, содержащих подстроку
INT(например, имени в стиле функции, такого какquantileInterpolatedWeighted, указанного на месте типа данных). Такие имена ошибочно принимались за целочисленные типы MySQL, а их первая группа аргументов(...)незаметно поглощалась как модификатор ширины отображения, что могло нарушить обратимость форматирования запроса. #108354 (groeneai). - Исправлена несогласованность, из-за которой некорректный
ARRAY JOIN, за которым следовали запятая и список таблиц в скобках, ошибочно разбирался как перекрёстное соединение, а не отклонялся. #108365 (Algunenano). - Исправлено исключение
LOGICAL_ERROR(“Invalid action query tree node …”), возникавшее, когда распределённый запрос одновременно выполнял дедупликацию структурно идентичных дублирующихся столбцовALIASи обращался к табличной функции с аргументом именованной коллекции видаkey = value(например,oss(s3_conn, filename = '...')). #108435 (groeneai). - Исправлена логическая ошибка (исключение в релизных сборках, аварийное завершение сервера в отладочных сборках и сборках с санитайзерами), которая могла возникать при вызове функции с несколькими аргументами
LowCardinalityнад distributed таблицей, например при использованииconcatAssumeInjective((SELECT toLowCardinality('p')), s)в качестве ключаGROUP BYсremote(). Выдавались сообщения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). - Исправлена ошибка, из-за которой настройка
use_client_time_zoneигнорировалась для строковых литераловDateTime/DateTime64, интерпретируемых на сервере (асинхронныйINSERT, литералы вSELECT). Теперь при включённойuse_client_time_zoneклиент передаёт свой локальный часовой пояс какsession_timezone, поэтому разбор на стороне сервера работает так же, как при синхронномINSERT. #109051 (groeneai). - Исправлена ошибка, из-за которой
max_execution_time(сtimeout_overflow_mode = 'throw') иногда так и не отменял запрос: если внутренний отслеживатель тайм-аутов уже ожидал запрос с более поздним сроком, то зарегистрированный позже запрос с более ранним сроком мог быть полностью пропущен и выполняться намного дольше установленного лимита времени. #109792 (tiandiwonder). - Исправлена ошибка
NOT_FOUND_COLUMN_IN_BLOCK, возникавшая при включённом анализаторе, когда запрос к таблицеDistributedиспользовал вместе сORDER BYстолбец_shard_num(илиshardNum()), ставшийNullable(например, приFULL JOINсjoin_use_nulls = 1). #109798 (groeneai). - Исправлена ошибка
NOT_IMPLEMENTED(“Method getDataAt is not supported for Nullable(String)”), которая могла возникать при JOIN сenable_join_runtime_filters = 1(включено по умолчанию начиная с версии 26.2), если ключ JOIN на стороне построения имел типLowCardinality(Nullable(...))и содержал NULL, а runtime-фильтр переключался на свой bloom-фильтр. #109824 (groeneai). - Исправлено аварийное завершение сервера при передаче лямбда-выражения туда, где функция высшего порядка ожидает конкретное значение (например, в качестве аккумулятора
arrayFold, как вarrayFold(lambda, arr, another_lambda)). Теперь приenable_analyzer = 0такие запросы отклоняются с ошибкойILLEGAL_TYPE_OF_ARGUMENT, а не приводят к аварийному завершению. #109840 (groeneai). - Псевдоним
unnestдляarrayJoinтеперь запрещён в фильтрах ROW POLICY. Это закрывает лазейку, из-за которой такая политика могла вызывать логическую ошибкуcolumn->size() == num_rowsпри чтении. #109973 (Algunenano). - Исправлена ситуация, когда индексы пропуска данных, определённые на подстолбцах
Tuple, не использовались при обращении к полю черезtupleElement(t, 'name'),tupleElement(t, N)илиt.N, если в том же запросе считывался и весь кортеж (например,SELECT *). Теперь все эти формы отсекают гранулы так же, как обращение к именованному подстолбцуt.name. #110056 (groeneai). - Исправлена ошибка
BAD_GETпри сравнении столбцаArray(String)с литералом массива (arr = ['x']), если у столбца есть индекс пропуска данныхtext,tokenbf_v1илиngrambf_v1. Теперь индекс обрабатывает такое сравнение как полное сканирование, и весь запрос больше не завершается ошибкой. #110057 (groeneai). - Исправлена ложная ошибка
ILLEGAL_COLUMNвALTER TABLE ... ADD COLUMN IF NOT EXISTS, возникавшая, если на этапе применения столбец уже существовал. Это происходило, когда один и тот же столбец добавлялся дважды сIF NOT EXISTSв одной инструкции или когда параллельныйALTERдобавлял столбец между фазами подготовки и применения. #110080 (groeneai). - Исправлена ошибка
LOGICAL_ERROR(Bad cast from type ColumnLowCardinality to ColumnString), возникавшая, когдаidentity()(или результат скалярного подзапроса) оборачивает значение, содержащее вложенныйLowCardinality, а в запросе используетсяWITH TOTALS/WITH ROLLUP. #110138 (groeneai). - Исправлена ошибка
NOT_FOUND_COLUMN_IN_BLOCKпри использованииGROUP BY ALLпо выражению с кортежем вместе сORDER BY. #110206 (alexey-milovidov). - Исправлена ошибка
NOT_FOUND_COLUMN_IN_BLOCKприINSERTв таблицу с ограничениемCHECK, ссылающимся на подстолбец (например,x.nullстолбцаNullableилиarr.size0столбцаArray). #110208 (alexey-milovidov). - Исправлены неверные результаты запросов, вызванные оптимизацией optimize_and_compare_chain (включена по умолчанию): условие, выведенное по транзитивности из a < b AND b < c, могло использовать иную семантику сравнения, чем исходные условия, если в цепочке смешивались типы с правилами преобразования, зависящими от конкретной пары (например, Enum и String, Decimal и Float64, FixedString разной ширины). Теперь транзитивные условия выводятся только в пределах групп типов с единым порядком сравнения. #110621 (yariks5s).
- Исправлена ошибка, из-за которой настройка
optimize_injective_functions_in_group_byизменяла результаты запроса дляGROUP BY GROUPING SETSиGROUP BY ... WITH TOTALS. Согласно документации, эта настройка не влияет на результат, однако исключение инъективной функции от ключа группировки приводило к неверному значению (или к потере строки) в строках, где этот ключ отсутствует в агрегируемом наборе (наборGROUPING SETS, не содержащий ключ), а также в строкеWITH TOTALS. Неверное значение могло совпасть с реальным значением ключа, и тогда строку суперагрегата было невозможно отличить от настоящей группы в том же результирующем наборе. #110721 (groeneai). - Исправлено зависание сервера при умножении состояния агрегатной функции
median/quantile(на основе ReservoirSampler) на очень большую целочисленную константу (например,medianState(x) * 18446744073709551615). Запрос переставал реагировать на отмену и мог выполняться бесконечно. #110779 (groeneai). - Исправлено аварийное завершение (разыменование нулевого указателя во время анализа запроса) при вызове
getSubcolumnдля аргумента типаJSONс именем внутреннего подстолбца-подсказки типа, то есть с именем, начинающимся с маркера типа в виде обратной кавычки. #110940 (groeneai). - Исправлена ошибка, из-за которой
map[key]возвращал значение последующего дубликата ключа вместо первого. Если столбецMapсодержал повторяющиеся ключи, результатmap[key]мог зависеть от предыдущих строк в том же блоке и от настройкиoptimize_functions_to_subcolumns, поэтомуSELECTиWHEREдля одной и той же строки могли давать разные результаты. #111246 (groeneai). - Исправлена логическая ошибка
!rhs_literal->getValue().isNull()в оптимизаторе логических выражений, возникавшая, когда в цепочкеANDстолбец сравнивается с константой со значением NULL, тип которой отличен отNullable(например,Variantсо значением NULL), приuse_variant_default_implementation_for_comparisons = 0. #111292 (groeneai). - Исправлены неверные результаты запросов с индексом пропуска
setи предикатом вида(x AND <null-value>) OR y, где NULL возвращается функцией (например,toInt64OrNull('x'),nullIf(1, 1),CAST(NULL AS Nullable(Int64))). Такое значение оборачивалось в__bitWrapperFuncи распространялоNULLвместо маски «неизвестно», из-за чего индекс set мог отсекать гранулы, на самом деле удовлетворяющие условию, и запрос возвращал меньше строк, чем следовало. #111604 (groeneai). - Исправлена ошибка, из-за которой
CREATE TABLE/ALTER TABLEс включённым анализатором допускали выражениеDEFAULT/MATERIALIZEDдля столбца, ссылающееся на виртуальный столбец, например_tableили_database. Вставка в такую таблицу завершалась ошибкойNOT_FOUND_COLUMN_IN_BLOCK, а столбецMATERIALIZED(значение которого нельзя передать явно) навсегда делал вставку в таблицу невозможной. Теперь такие выражения отклоняются уже на этапе определения — так же, как без анализатора. СтолбцыALIAS(вычисляемые при чтении) иEPHEMERAL(нехранимые входные данные для вставки), использующие виртуальные столбцы, по-прежнему работают. #111776 (groeneai). - Исправлена ошибка
UNKNOWN_QUERY_PARAMETERпри вызове параметризованного представления с аргументом-подзапросом типаArray,TupleилиLowCardinality, напримерSELECT * FROM v(param = (SELECT groupArray(x) FROM t)). #111790 (groeneai). - Исправлены три ошибки в преобразованиях анализатора, которые превращают цепочку сравнений в
IN/NOT IN(x = c1 OR x = c2 OR ...,x != c1 AND x != c2 AND ...иhas(const_array, x)). Для выражения типаVariantприuse_variant_default_implementation_for_comparisons = 0преобразование меняло тип результата выражения сUInt8наNullable(UInt8), из-за чего проверка дерева запроса в отладочных сборках и сборках с санитайзерами выдавалаLOGICAL_ERROR. Для выражения с динамической структурой (Dynamic,Array(Dynamic),JSON) после преобразования корректный запрос завершался ошибкойIllegal type ... of argument of function in, посколькуINне принимает такие аргументы. Кроме того, в обоих случаях возвращались неверные результаты, если константа не преобразуется к типу выражения без потерь, например при сравнении константыDateTimeс указанием времени суток со столбцом типаDate. #111924 (groeneai). - Исправлена ошибка, из-за которой
quantileDeterministic,quantilesDeterministicиmedianDeterministicпри каждом запуске возвращали разные результаты для одних и тех же данных, если в запросе используются параллельные реплики, distributed таблица или внешняя агрегация, а также если состояния хранятся в таблице (в том числе внутри значенияDynamic). Состояния, записанные до этой версии под старым названием типа без версии, сохраняют прежнее поведение, поскольку их формат изменить нельзя. #112052 (alexey-milovidov). - Исправлены неверные результаты, вызванные тем, что запросы векторного поиска засоряли кэш условий запроса. Запрос
SELECT ... WHERE <condition> ORDER BY <distance function> LIMIT nк таблице с индексомvector_similarityмог пометить гранулы как не соответствующие<condition>, из-за чего последующий обычный запросSELECT ... WHERE <condition>к той же таблице молча возвращал меньше строк. Чтение при векторном поиске больше не записывает данные в кэш условий запроса. #112086 (groeneai). - Исправлена потеря настройки
serialize_string_in_memory_with_zero_byteв сериализованном плане запроса. Приserialize_query_plan = 1в кластере, где эта настройка отключена, строковое представление в памяти могло различаться на инициаторе и на узле, выполняющем десериализованный план: настройка считывалась при десериализации, но не записывалась при сериализации, поэтому на выполняющем узле всегда принимала значение по умолчанию. #112131 (groeneai). - Исправлен неверный результат для
JOIN, выражениеONкоторого содержит константный конъюнкт, напримерON l.id = r.id AND CAST(NULL AS Nullable(UInt8)). Оптимизация плана запроса молча отбрасывала константу, и JOIN выполнялся так, будто её нет: соединенияINNER,LEFT SEMIиRIGHT SEMIвозвращали совпавшие строки, хотя при заведомо ложном условии результат должен быть пустым, аRIGHT ANTIне возвращал ни одной строки вместо всех. #112155 (vdimir). - Исправлены неверные результаты при вызове параметризованного представления с аргументом, который не является присваиванием вида
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). - Исправлена ошибка, из-за которой
CREATE VIEWилиCREATE FUNCTION, в определении которых вызываютсяsubstr,midилиbyteSliceв форме, которую грамматикаsubstringне может повторно разобрать, принимались, но записываемые ClickHouse метаданные не являлись корректным SQL. Последующее чтение такого определения завершалось ошибкойSYNTAX_ERROR, а при запуске сервера прерывало загрузку метаданных, так что сервер вообще не мог запуститься. Теперь такие определения поддерживают обратимый обмен, а существующие файлы метаданных видаsubstring(x, a, b, c)снова читаются, поэтому затронутый сервер запускается без ручного вмешательства. #112195 (groeneai). - Исправлены неверные результаты, неправильный порядок вывода
ORDER BYи исключениеBAD_TYPE_OF_FIELDв случаях, когда первичный ключ имеет типArrayилиTuple, а запрос применяет к немуplus,minus,multiply,divideилиintDiv. Арифметические операции над составным значением выполняются поэлементно, а составные значения сравниваются лексикографически, поэтому анализ первичного ключа больше не считает такое выражение монотонным. #112339 (groeneai). - Исправлена ошибка
Code: 62 ... You must not specify ANY or ALL for PASTE JOIN. (SYNTAX_ERROR), которую выдавал удалённый сервер для запроса сPASTE JOIN, передаваемого на другой сервер, например когда левая таблица является таблицейDistributedили табличной функцией*Cluster. Модуль форматирования выводилALL PASTE JOIN— запись, которую парсер отвергает, поэтому принимающий сервер не мог разобрать полученный запрос. #112404 (groeneai). - Исправлена ошибка, из-за которой список псевдонимов столбцов, например
(SELECT 1) AS t(x)илиWITH t(x) AS (SELECT 1), не был виден внутри табличной функцииview: обращение кt.xзавершалось ошибкойUNKNOWN_IDENTIFIER, хотя та же конструкция работает внеview. #112690 (groeneai). - Исправлена логическая ошибка при форматировании запроса, когда предложение
ARRAY JOINне содержит выражений. Теперь такое предложение отклоняется ещё на этапе разбора с ошибкойSYNTAX_ERROR— так же, как пустойUSING, — а не принимается и форматируется в текст, который невозможно разобрать обратно. #112699 (groeneai). - Исправлена ошибка, из-за которой
connectionIdвыбрасывалContext has expired, если действия выражения, подготовленные для подзапроса, выполнялись после освобождения контекста, в котором они были построены. #112870 (clickgapai). - Исправлены логическая ошибка и неверные результаты в случаях, когда условие
JOIN ONне на равенство, вычисляемое во время JOIN, содержитarrayJoin. Теперь JOIN с алгоритмамиhash,parallel_hashилиgrace_hashотклоняет такое условие с ошибкойINVALID_JOIN_ON_EXPRESSION. Если развёртывание массива зависит только от одной стороны, перенесите его вARRAY JOINв подзапросе перед JOIN; условие, в котором аргументarrayJoinчитает столбцы с обеих сторон, придётся переписать. #112889 (groeneai). - Исправлена ошибка, из-за которой
geohashesInBoxтратила неограниченное время на область нулевой площади, напримерgeohashesInBox(0., 0., 180., 0., 12). Такой запрос возвращал правильный единственный geohash, но выполнял около 5e8 холостых итераций цикла на строку и игнорировал какmax_execution_time, так иKILL QUERY. #112976 (groeneai). - Изменение
SETTINGS, помеченное как записанное без значения, теперь отклоняется, если оно содержит значение, отличное отtrue; кроме того, при форматировании запроса значение такого изменения больше никогда не опускается. Ранее специально сформированный JSON-фрагмент AST мог выполнить настройку типаBoolсо значениемfalse, тогда какsystem.query_logиformatQueryFromJSONпоказывали форму без значения. #113025 (alexey-milovidov). - Исправлена ошибка
UNKNOWN_IDENTIFIERпри выборке изVIEW, у которого объявленные типы столбцов отличаются от типов, возвращаемых его внутренним запросом, напримерSELECT sum(length(arr)) FROM v, гдеvобъявляетarr Array(UInt8)поверх столбцаString. При значении по умолчаниюoptimize_functions_to_subcolumns = 1оптимизатор переписывалlength(arr)в чтение подстолбцаarr.size0и передавал это имя во внутренний запрос, в котором такого подстолбца нет. #113057 (groeneai). - Исправлена отмена чтения через табличную функцию
postgresqlи движок PostgreSQL. Отмена на этапе запуска чтения могла приводить к гонке на указателе транзакции, а сама отмена могла полностью теряться, из-за чего запрос продолжал выполняться, пока PostgreSQL не завершал его. Отмена, поступившая в PostgreSQL до начала выполнения оператораCOPY, по-прежнему может быть отброшена. #113150 (groeneai). - Исправлена ошибка
LOGICAL_ERROR(Next task callback is not set for query), возникавшая, когда представление сSQL SECURITY DEFINERилиSQL SECURITY NONEповерх кластерной табличной функции (s3Cluster,urlCluster,fileCluster) читалось как вторичный запрос, например черезremoteилиclusterAllReplicas. Теперь такая неподдерживаемая вложенность отклоняется с обычной ошибкой запроса, а не приводит к аварийному завершению сервера в отладочных сборках и сборках с санитайзерами. #113371 (groeneai). - Исправлена логическая ошибка
IDENTIFIER is not a table expression, возникавшая, когда табличная функция семейства remote с аргументомview(...)использовалась в левой частиJOIN ... USING, ключом которого является псевдоним из спискаSELECT, приanalyzer_compatibility_join_using_top_level_identifier = 1. #113400 (groeneai). - Исправлена ошибка
Not-ready Set is passed as the second argument for function 'in', возникавшая, когда запрос фильтровалsystem.databasesпо столбцуnameс подзапросом внутриindexHint, напримерSELECT count() FROM system.databases WHERE indexHint(name IN (SELECT 'foo')). Такой запрос отклонялся с ошибкойLOGICAL_ERRORв релизных сборках и приводил к аварийному завершению сервера в отладочных сборках и сборках с санитайзерами. #113556 (groeneai). - Исправлена ошибка, из-за которой запрос по столбцу
Variantигнорировалmax_execution_timeиKILL QUERY. При вызове функции с несколькими аргументамиVariantфункция разрешалась отдельно для каждой альтернативы каждого аргумента, и ни один из двух циклов, выполняющих эту работу, не проверял отмену, поэтому такой запрос невозможно было остановить до его завершения. #113612 (groeneai). - Исправлен сбой
ALTER TABLE ... MODIFY COLUMNс ошибкойCannot specify codec for column type ALIAS, когда один оператор одновременно превращает столбецALIASв физический (DEFAULTилиMATERIALIZED) и задаётCODEC. #113853 (groeneai). - Исправлено аварийное завершение сервера при JOIN с константным выражением
ON, когда правая часть содержитARRAY JOIN. При чтении лениво реплицируемого столбца правой части использовался уже освобождённыйColumnReplicated. #113901 (groeneai). - Исправлена утечка памяти при
optimize_aggregation_in_order = 1, возникавшая, когда ключ сортировки таблицы является строгим префиксом ключаGROUP BYи используется агрегатная функция, состояние которой владеет памятью в куче, напримерquantileDD. Потребление памяти сервером росло с каждым таким запросом вплоть до перезапуска. #114010 (groeneai). - Исправлена ошибка, из-за которой
isProbablePrimeдляUInt128/UInt256игнорировалаmax_execution_timeиKILL QUERY. Блок широких значений обрабатывался целиком в рамках одного вызова функции без точки отмены, поэтому запрос мог выполняться ещё несколько минут после истечения отведённого времени. #114032 (groeneai). - Исправлена ошибка
Code: 46. DB::Exception: Unknown function exists. (UNKNOWN_FUNCTION), возникавшая, когда предложениеPREWHEREсодержит предикатIN (subquery)и задана настройкаrewrite_in_to_join = 1(илиmake_distributed_plan = 1, которая принудительно её включает). Тот же запрос сWHEREвыполнялся корректно. #114067 (RohithPariki). - Исправлена ошибка
LOGICAL_ERRORвarrayAutocorrelation, возникавшая, когда аргументом является непустой массив с типом элементовNothing, напримерSELECT arrayAutocorrelation([arrayMax([])]). Теперь такой аргумент отклоняется с ошибкойILLEGAL_COLUMN. Литерал пустого массива[]по-прежнему возвращает[]. #114249 (groeneai). CREATE TABLEиALTER TABLEтеперь запрещают использовать кодеки сжатия с потерями, такие какSZ3, для столбцов, входящих в ключ сортировки. #114531 (groeneai).- Исправлен бесконечный неотменяемый цикл в функциях
hopиwindowID, возникавший, когда длительность аргумента-интервала в секундах кратна 2^32 (например,toIntervalDay(2147483648)): из-за переполнения при вычитании проверка выхода времени за допустимые пределы не срабатывала, а при постоянных аргументах цикл выполнялся на этапе анализа, где запрос нельзя было даже завершить. Тот же интервал мог также бесконечно нагружать фоновый потокWINDOW VIEW; теперь такое оконное представление отклоняется при создании. #114607 (alexey-milovidov). - Исправлена логическая ошибка
Not-ready Set is passed as the second argument for function 'in'для запроса с подзапросомIN, читающим данные с удалённого кластера: теперь запрос завершается с фактической ошибкой подзапроса, например ошибкой соединения. #114983 (alexey-milovidov). - Исправлена проблема с
INSERTв таблицуLog,TinyLogилиStripeLog, завершавшимся сбоем при фиксации записанных размеров файлов. Такая вставка могла оставить свои строки в таблице, несмотря на сообщение об ошибке, либо привести к рассогласованию файлов данных столбца типа Array. Чтение таблицыLogилиTinyLog, в которой столбец типа Array не содержит элементов, хотя смещения указывают на их наличие, теперь завершается ошибкой с указанием имени столбца, а не чтением за пределами элементов. Частично записанный столбец элементов отклонялся и ранее. #115027 (groeneai). - Исправлена ошибка
TYPE_MISMATCH(“CAST AS Array can only be performed between same-dimensional array types”) для запроса с константой типаArray(Map(...)), напримерhas([map('k', 'v')], m), выполняемого над таблицейDistributedили с параллельными репликами. #115883 (alexey-milovidov). - Исправлены неверные результаты при JOIN с представлением или
view(), у которого проецируемый столбец имеет то же имя, что и столбец одного из его собственных внутренних отношений, напримерSELECT expr(x.c0) AS c0 FROM a AS x, b AS y. Оптимизатор порядка JOIN встраивал такое выражение в развёрнутый граф JOIN, а затем применял его дважды, из-за чего запрос без каких-либо предупреждений возвращал искажённые значения. Если выражение к тому же меняло тип столбца, по той же причине на этапе построения плана возникала ошибкаAMBIGUOUS_COLUMN_NAME. #116152 (groeneai). - Исправлено исключение в коррелированных подзапросах, возникавшее, когда внешние столбцы становятся
Nullableприgroup_by_use_nullsс ROLLUP/CUBE. #100365 (alexey-milovidov). - Значение
max_replication_lag_to_enqueue = 0теперь отклоняется для баз данныхReplicated. При этом значении проверка несинхронизированности после восстановления всегда оказывалась истинной, что приводило к аварийному завершению сервера сLOGICAL_ERRORв отладочных сборках и сборках с санитайзерами. Теперь0отклоняется на этапе разбора с ошибкойBAD_ARGUMENTSнезависимо от источника (CREATE DATABASE ... SETTINGS, блок<database_replicated>в конфигурации сервера, повторное применениеATTACHи повторное применение существующих метаданных при обновлении). Минимальное допустимое значение —1. #106006 (groeneai). - Запрещено создание индекса пропуска minmax для столбцов JSON (Object), чтобы предотвратить исключение NO_COMMON_TYPE при вставке массивов со смешанными типами. Вместо этого используйте типизированные подстолбцы (например,
INDEX idx json.field TYPE minmax). #106094 (linhaojie). - Исправлена ошибка, из-за которой
JSON_QUERY/JSON_VALUE/JSON_EXISTSвозвращали Dynamic вместо String/UInt8 для аргументов типа Dynamic. #106877 (Avogar). - Исправлено переполнение знакового целого при установке очень большого значения для настройки тайм-аута ожидания, например
interactive_delay: ожидание могло сразу завершаться по тайм-ауту, а сервер — аварийно завершаться под Undefined Behavior Sanitizer. #106961 (groeneai). - Исправлена ошибка
LOGICAL_ERROR(«Unsupported argument types») в функцииgeohashesInBox, возникавшая, когда в аргументах-координатах смешивались константные и неконстантные значения или когда координата имела типBFloat16. Смешанные константные и неконстантные аргументыFloat32теперь работают корректно, а аргументыBFloat16отклоняются с понятным сообщением об ошибке. #107063 (groeneai). - Исправлена ошибка, из-за которой заголовок в форматах
CSVWithNamesиCSVWithNamesAndTypesсодержал меньше столбцов, чем данные, при включённой настройкеoutput_format_csv_serialize_tuple_into_separate_columns(включена по умолчанию). Теперь заголовок (и строка типов) разворачивает столбцыTupleв конечные поля с именами через точку (например,t.a,t.b), поэтому число столбцов в заголовке совпадает с данными. Это поведение управляется новой настройкойoutput_format_csv_header_serialize_tuple_into_separate_columns(по умолчанию1); чтобы вернуть прежний заголовок с одним именем, установите её в0. #107371 (groeneai). - Исправлена утечка памяти во встроенном
mongo-c-driver, которая могла возникать при чтении из MongoDB (например, через словарь MongoDB или табличную функциюmongodb), если после ошибки чтения, допускающей повтор, не удавалось выбрать сервер для повторной попытки. #107448 (groeneai). - Исправлены логическая ошибка (
WhichDataType(const_type).isArray()) и аварийное завершение сервера при анализе первичного ключа, когдаpointInPolygonвызывается с константным аргументом-полигоном оберточного типа, такого какVariantилиDynamic(например,pointInPolygon((x, y), if(c, [(0, 0), ...], NULL))). #107589 (groeneai). - Исправлены логические ошибки (
Bad cast), вызванные несогласованным удалениемLowCardinality, вложенного в столбцыVariantиDynamic, например вconcat,formatи при анализе первичного ключа. #107773 (Avogar). - Исправлен разбор параметров команды исполняемых пользовательских функций: плейсхолдеры с пустыми или недопустимыми именами больше не принимаются в качестве параметров. #107983 (goutamadwant).
- Исправлена работа
accurateCastOrNullдляTuple, элемент которого имеет типDynamic/Variant: настоящийNULLв исходных данных воспринимался как ошибка преобразования. Если целевой элемент имеет типNullable, исходныйNULLтеперь сохраняется какNULLв этом элементе (так же, как для обычного исходногоTuple(Nullable(...))); если целевой элемент неNullable, исходныйNULLтеперь превращает вNULLвесь кортеж (как в эталонном поведении безDynamic), а не подставляет значение элемента по умолчанию. При ошибках разбора и переполнения весь кортеж, как и раньше, становитсяNULL. #108023 (groeneai). - Табличная функция
mongodbтеперь принимаетoid_columns, переданный как именованный аргумент (например,oid_columns='_id'), и больше не отклоняет его с ошибкойBAD_ARGUMENTS. #108039 (alexey-milovidov). - Теперь можно выполнять запросы к словарю
range_hashedилиcomplex_key_range_hashedс диапазоном типаDateTime64,Decimalили с плавающей запятой, передавая соответствующий аргумент вdictGet/dictHas. Ранее такие запросы завершались ошибкойmust be convertible to Int64, а для открытых интервалов диапазоновDecimal/DateTime64ошибочно возвращалось значение по умолчанию. #108052 (alexey-milovidov). - Исправлено аварийное завершение сервера (
Logical errorвIColumn::insertFrom) при приведенииArray(Dynamic)илиArray(Variant)кQBitс помощьюaccurateCastOrNull, напримерaccurateCastOrNull(CAST(range(114), 'Array(Dynamic)'), 'QBit(Float32, 114)'). #108288 (groeneai). - Исправлен сбой сервера (
Received signal 4, недопустимая инструкция), который мог возникать из-за некорректного или рассинхронизированного потока собственного TCP-протокола. Теперь перед разбором поляinitial_addressвClientInfoпроверяется, что оно имеет числовой форматhost:port; раньше нечисловой порт мог попасть в перехватываемую функцию libcgetservbyname. #108410 (groeneai). - Исправлено чрезмерное выделение памяти при десериализации специально сформированных состояний агрегатных функций
mannWhitneyUTest,rankCorr,largestTriangleThreeBuckets,quantileGK,sequenceMatch/sequenceCountиgroupArrayIntersect. Некорректное состояние могло указывать огромное количество элементов, из-за чего сервер пытался выделить десятки гигабайт, получив на вход всего несколько байт; теперь такие состояния отклоняются с ошибкойTOO_LARGE_ARRAY_SIZE. #108465 (groeneai). - Исправлена логическая ошибка (
Bad cast from type DB::ColumnNullable to DB::ColumnString) и возможные неверные результаты при использованииgroup_by_use_nullsс константным ключом группировки типаLowCardinalityвGROUPING SETS/ROLLUP/CUBE. #108771 (alexey-milovidov). - Исправлена ошибка
TYPE_MISMATCHвmapFilter,mapSort,mapReverseSort,mapPartialSortиmapConcat, возникавшая, когда значениеMapсодержит вложенныйMapсLowCardinality, напримерmapFilter((k, v) -> 1, map('a'::LowCardinality(String), map('x'::LowCardinality(String), 'y'))). #108798 (groeneai). - Исправлена ошибка
LOGICAL_ERROR(“Inconsistent AST formatting”), которая приводила к аварийному завершению сервера в отладочных сборках и сборках с санитайзерами при форматировании типа данныхTuple, сочетающего именованные и безымянные элементы (например,Tuple(a UInt8, UInt16)). #108915 (groeneai). JSONExtractтеперь учитываетcast_string_to_date_time_modeпри преобразовании строковых значений JSON вDateTime/DateTime64— так же, какCAST. #109252 (Utkal059).- Исправлено поведение
INсо столбцом-массивом в качестве правого аргумента: раньше без каких-либо предупреждений возвращался неверный (всегда ложный) результат или выбрасывалось исключение. Теперьx IN arrработает какhas(arr, x). #109416 (alexey-milovidov). - Исправлена ошибка
LOGICAL_ERRORвarrayFoldс неконстантным аргументомArray(LowCardinality(T))(например,arrayFold((acc, x) -> acc + x, materialize([1, 2, 3]::Array(LowCardinality(Int64))), toInt64(0))): вызов завершался ошибкой “Arguments of ‘plus’ have incorrect data types” (а в отладочных сборках и сборках с санитайзерами — аварийным завершением сервера). #109462 (groeneai). - Исправлено исключение
ILLEGAL_COLUMNвconv: теперь аргументыFixedStringкорректно приводятся кString. #109771 (hp77-creator). - Исправлены неверные результаты при чтении через табличные функции с
FINAL/SAMPLEприserialize_query_plan = 1, а также ключ кэша статистики хеш-таблицы агрегации для табличных функций (ранее все табличные функции использовали одну общую запись для предварительного выделения памяти). #109847 (azat). - Исправлен разбор числовых значений
1/0как значенийBoolвнутри составных типов (например,Array(Bool),Tuple(Bool, ...)). Ранее разбор[1,0]завершался ошибкойCANNOT_READ_ARRAY_FROM_TEXT, тогда как[true,false]обрабатывался корректно. #109976 (groeneai). - Исправлена ошибка
NOT_IMPLEMENTED(Method getDataAt is not supported for Nullable(String) in case if value is NULL), возникавшая, когда индексtextпостроен наArray(LowCardinality(Nullable(String)))(включая хранящиеся таким образом поляNested), а индексируемый массив содержит элементNULL. Теперь элементы массива со значениемNULLпропускаются при построении индекса — так же, как дляArray(Nullable(String)). #110055 (groeneai). - Исправлены некорректные результаты
subBitmap,bitmapSubsetInRangeиbitmapSubsetLimitдля битмапов, всё ещё хранящихся в компактном представлении, в том числе для значений элементовUInt64иInt64больше2^32, которые усекались до 32 бит. Сравнения в функциях для битмапов со знаковыми типами элементов теперь единообразно используют беззнаковое значение типа элемента: например, в битмапеInt8элемент-1сравнивается как255, а не как расширенное со знаком значение4294967295. Это также исправляет работу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*с экстремальными приращениями: теперь экстремальные значения интервалов обрабатываются детерминированно, без расчёта на знаковое переполнение. Также исправлено зависаниеWITH FILLс интервальным шагом при очень большом шагеYEAR, из-за которого календарь ранее шёл в обратную сторону. #110158 (groeneai). - Исправлен квадратичный рост времени выполнения (и игнорирование
max_execution_time) при агрегации в порядке сортировки (aggregation in order) с группировкой по нескольким ключам, когда порядок сортировки совпадает лишь с префиксом ключа группировки. #110159 (alexey-milovidov). - Исправлены сравнения, которые ранее завершались ошибкой
ILLEGAL_TYPE_OF_ARGUMENT, если у операндов нет наименьшего общего супертипа. Массивы, напримерArray(Int64)иArray(UInt64)илиArray(Int256)иArray(UInt256), теперь можно сравнивать лексикографически с помощью=,!=,<,<=,>,>=,IS DISTINCT FROMиIS NOT DISTINCT FROM. Безопасные дляNULLсравнения, такие какisDistinctFrom/isNotDistinctFrom, теперь также сравнивают поддерживаемые пары числовых или десятичных значений (не массивов) по значению, вместо того чтобы завершаться ошибкой. Кроме того, сравнения на равенство теперь работают для массивов с вложенными элементамиTuple(Nullable(...)). #110245 (diegomestre2). - Исправлено переполнение знакового целого (UBSan) при преобразовании экстремального значения
DateTime64(например,INT64_MIN) вTime/Time64в часовом поясе с отрицательным смещением. #110451 (groeneai). - Преобразование выходящих за допустимый диапазон значений с плавающей запятой (
BFloat16,Float32,Float64) и значенийUInt64, превышающихInt64::max(), вDateTimeиTimeтеперь на всех архитектурах надёжно ограничивается границами диапазона (ранее результат такого преобразования зависел от архитектуры и на x86-64 мог «заворачиваться» при переполнении), а для неконечных значений (NaN,inf) теперь генерируется исключение вместо произвольного результата. То же исправление применено к преобразованию чисел с плавающей запятой вDateв функцииtoDate, а также к преобразованиюUInt64и широких целых чисел ((U)Int128,(U)Int256) вDateиDate32, которое вместо ограничения могло возвращать день до начала эпохи. Преобразование числа вTimeтеперь ограничивается диапазоном типа для любого числового исходного типа (ранее значения из узких беззнаковых или широких целочисленных типов сохранялись без ограничения и ограничивались только при выводе), а точное приведение кTimeбольше не отклоняет отрицательные значения, которые поддерживаетTime, и не ограничивает молча значения, которые в него не помещаются. Точное приведение числа кDate32(accurateCast,accurateCastOrNull) больше не ограничивает молча выходящее за диапазон или неконечное значение, а генерирует исключение или возвращаетNULL— так же, как это уже происходило дляDateиDateTime; вариантыOrDefaultдля таких входных данных возвращают значениеDate32по умолчанию. Точное приведение нецелого числа с плавающей запятой кDate,Date32,DateTimeилиTimeтеперь отклоняется, а не молча усекается. Также исправлена документация функцииtoDateTime32, в которой по ошибке приводились примерыtoDateTime64и описывался диапазон значенийDateTime64. #110459 (alexey-milovidov). - Исправлен сбой вывода схемы с ошибкой
Map cannot have a key of type LowCardinality(Nullable(String))при чтении ORC-файлов, в которых ключи map закодированы словарём, — включая ORC-файлы, записанные Spark, и файлы, записанные самим ClickHouse при включённой настройкеoutput_format_orc_dictionary_key_size_threshold. #110492 (tiandiwonder). - Исправлена логическая ошибка (
Function node with name '...' is not resolved as ordinary function), которая могла возникать при включённой настройкеoptimize_or_like_chain, если агрегатная или оконная функция находилась в левой частиLIKE/ILIKE/matchвнутри цепочкиOR. #110641 (groeneai). - Исправлено переполнение знакового целого в
toStartOfIntervalпри экстремально большом количестве интерваловMONTH,WEEKилиDAYдля значенийDate/Date32/DateTime64. #110688 (groeneai). - Исправлена ошибка, из-за которой
readWKTиreadWKTPointвозвращали дляPOINT EMPTYнеинициализированные (в скалярном режиме) или устаревшие координаты предыдущей строки (в векторизованном режиме). ТеперьPOINT EMPTYотклоняется с ошибкойCANNOT_PARSE_TEXT, посколькуPointв ClickHouse — это фиксированныйTuple(Float64, Float64), не имеющий пустого представления. #110692 (groeneai). - Исправлена потеря типа
GeometryфункциейflipCoordinates: для аргумента типаGeometryрезультат снова имеет типGeometry, а не базовыйVariant(...), поэтому его можно напрямую передавать в такие функции, какareaCartesian. #110694 (groeneai). - Исправлена неканоническая WKB-сериализация пустого полигона:
wkb(POLYGON EMPTY)теперь выдаётnumRings = 0вместо лишнего кольца из нуля точек, поэтому стандартный пустой полигон после обратимого обмена через WKB остаётся неизменным. #110796 (groeneai). - При разборе JSON
Boolчисловые значения1/0теперь обрабатываются с учётом настройкиallow_special_bool_values. Ранее входные данные JSON, например{"v":1}дляVariant(Bool, UInt32), считывались какBoolдаже приallow_special_bool_values_inside_variant = 0, поскольку парсеры JSONBoolигнорировали эту настройку, а уBoolприоритет десериализации вVariantвыше, чем у целочисленных типов. #110835 (groeneai). - Исправлена ошибка, из-за которой
throwIf(notLike(col, pattern))(и другие вызовыthrowIfповерх функции) безусловно генерировали исключение, еслиcolимеет типLowCardinality. Стандартная реализация дляLowCardinalityвыполнялаthrowIfнад всем словарём, а он всегда содержит зарезервированное значение по умолчанию, даже если ни одна строка на него не ссылается. В результате ненулевое значение в этой неиспользуемой ячейке заставлялоthrowIfгенерировать исключение для данных, не удовлетворяющих условию. #110864 (groeneai). - Исправлено аварийное завершение при использовании агрегатной функции с комбинатором
-Tupleвместе сRESPECT NULLS, если она формировала промежуточное состояние (-State, распределённая агрегация,WITH ROLLUP/WITH CUBE). Комбинированная функция получала имя неверного варианта состояния, из-за чего после сериализации и десериализации её типAggregateFunctionразрешался в несовместимую структуру в памяти. #110930 (groeneai). - Исправлена ошибка
Nested type LineString cannot be inside Nullable type (ILLEGAL_TYPE_OF_ARGUMENT)при чтении допускающего NULL пространственного столбца MySQL (LINESTRING,POLYGON,MULTILINESTRING,MULTIPOLYGON,MULTIPOINTили обобщённогоGEOMETRY) через табличную функциюmysqlили движки таблиц/баз данныхMySQL. Теперь такие столбцы отображаются вNullable(String)и содержат значение в том виде, в каком его возвращает MySQL (4-байтовый префикс SRID, за которым следуют данные WKB).POINTпо-прежнему отображается вNullable(Point). #110943 (groeneai). - Исправлена сериализация
Nativeдля обёртокSimpleAggregateFunction, содержащих версионированные состояния агрегатных функций, при взаимодействии с узлами более старых версий. #110997 (groeneai). - Исправлена ошибка
CANNOT_CONVERT_TYPEдля констант типаVariant(включаяGeometry) в распределённых запросах и запросах с параллельными репликами. #111136 (fm4v). - Исправлена ошибка
LOGICAL_ERROR(«Lambda resolved type … is not equal to type from actions DAG …»), возникавшая, если тело лямбда-выражения функции высшего порядка представляло собойif/multiIfс константным условием, где ветвь с литераломBoolсочеталась с ветвью сравнения типаUInt8, напримерarrayFilter(p -> multiIf(false, true, p = 'ALL'), ['ALL']). #111245 (groeneai). - Исправлено переполнение знакового целого в
toStartOfIntervalс интервалами меньше секунды: для значенийDateTime64, отстоящих от нижней границыInt64не более чем на один интервал, округлённый результат незаметно превращался в бессмысленное положительное значение; теперь функция генерирует исключениеDECIMAL_OVERFLOW. #111370 (alexey-milovidov). - Исправлено исключение (
CANNOT_CONVERT_TYPEили логическая ошибка) в распределённых запросах, использующих комбинатор-Tupleс модификаторомRESPECT NULLS/IGNORE NULLSпри вложенных комбинаторах, напримерanyRespectNullsStateTuple(...) IGNORE NULLS. #111570 (alexey-milovidov). - Исправлена попытка текстового разбора
FixedString, которая при неудачном разборе оставляла в столбце частично добавленные байты. Это могло приводить к логической ошибкеSizes of nested column and null map of Nullable column are not equalпри сериализации столбцовVariant/Array/Nullableлибо к незаметному смещению байтов результата. #111908 (groeneai). - Исправлены исключение и незаметный пропуск данных при чтении динамического подстолбца (пути внутри столбца
JSONилиDynamic) через таблицуBuffer. #111948 (alexey-milovidov). - Устранена квадратичная сложность в
countSubstringsCaseInsensitiveUTF8, из-за которой на строке размером в несколько мегабайт с большим количеством совпадений функция выполнялась несколько минут. Теперь символьное смещение каждого совпадения вычисляется инкрементально, а не пересчитывается с начала строки. #112003 (groeneai). - Исправлено переполнение знакового целого в трёхаргументной перегрузке
toStartOfInterval: если значение аргументаoriginбыло близко к нижней границеInt64, функция вместо сообщения об ошибке возвращала значение, полученное в результате переполнения. #112045 (alexey-milovidov). - Запрещено использование состояний агрегатных функций в параметрах табличных функций, поскольку они там вообще не поддерживаются. #112087 (PedroTadim).
- Исправлено поведение табличной функции
values, которая выводила нелитеральную константуBool(например,CAST(true, 'Nullable(Bool)')), вставляемую в столбецStringили другой текстовый столбец, как1/0вместоtrue/false. #112308 (yakov-olkhovskiy). - Исправлена логическая ошибка (приводящая к аварийному завершению в отладочных сборках и сборках с санитайзерами), возникавшая при применении
finalizeAggregationк столбцу, в котором состояния агрегатных функций получены от разных функций с общим представлением состояния, но разными типами итогового результата, — например,quantileStateиquantilesState(0.9), объединённых черезUNIONили полученных с помощьюarrayReduce. Теперь такие запросы завершаются обычной ошибкой, а не аварийно. #112662 (zainulabidin302). - Исправлен разбор целых чисел, не помещающихся в целевой тип, в
Poco::NumberParser, который используется для чтения чисел JSON. Такое число не отклонялось, а незаметно разбиралось в неверное значение (например,18446744073709551617превращалось в1), а числоUInt64, превышающее максимумInt64, искажалось при преобразовании AST в JSON и обратно. #112904 (alexey-milovidov). - Исправлено преобразование константы
Boolв правой частиINк типуStringлевой части в виде'1'/'0'вместо канонических'true'/'false'(теперь поведение согласовано сCASTи табличной функциейvalues). #113051 (yakov-olkhovskiy). - Исправлено несогласованное форматирование AST для
viewIfPermitted: устранены проблемы с функцией, обычно записываемой как оператор (например,not), в ветвиELSEформы табличной функции, а также с ошибочным форматированием формы выраженияviewIfPermitted(...)сELSE. #113652 (alexey-milovidov). - Исправлены неопределённое поведение и неверные результаты
avgдляDate/DateTime/DateTime64/Time/Time64: среднее теперь вычисляется точно в целочисленной арифметике, что устраняет как переполнение на границеInt64(UB, неверный результат на x86), так и потерю точностиFloat64для значений больше 2^53 (заметную при наносекундной точности). #113912 (alexey-milovidov). - Исправлена утечка памяти в экспериментальном кодеке сжатия
SZ3: если сжатие плохо сжимаемых или повреждённых данных завершалось исключением, временные рабочие буферы не освобождались. #113916 (alexey-milovidov). - Исправлена ошибка, из-за которой
hasAny,hasAll,has,indexOf,mapContainsKey,mapContainsValueиmapContainsвозвращали слишком мало строк или завершались ошибкойTOO_LARGE_STRING_SIZEпри обращении к индексуbloom_filterс константой типаFixedString. Индекс хешировал константу в дополненном виде, тогда как функция сравнивает её без дополнения, поэтому подходящая гранула пропускалась. #114089 (alexey-milovidov). - Исправлена ошибка, из-за которой
minиmaxдля столбцовDateTime64возвращали неверные результаты, если агрегатная функция JIT-компилировалась, а данные содержали временные метки до 1970 года.is_signedне был специализирован дляDateTime64иTime64, производных отDecimal64, поэтому сгенерированный код сравнивал количество тиков как беззнаковые целые числа, и временная метка до 1970 года ошибочно оказывалась максимальной вmaxи не учитывалась вmin. #114168 (groeneai). - Исправлена ошибка, из-за которой
arrayExists(x -> x = needle, arr)возвращала неверный результат или завершалась ошибкойTOO_LARGE_STRING_SIZE, если элемент массива и искомая подстрока имели разные строковые типы (например, искомая подстрока типаStringи элементArray(FixedString(N))). Оптимизацияoptimize_rewrite_array_exists_to_has, включённая по умолчанию, заменяла такой вызов наhas, которая, в отличие от=, не учитывает дополнение нулями при сравнении. #114496 (groeneai). - Исправлено применение текстового индекса для оператора
LIKE/ILIKE, используемого с контейнерами Map или JSON. #114544 (ahmadov). - Исправлены неопределённое поведение и неверные результаты на граничных значениях в
quantileиquantilesдляDateTime64и широких типовDecimal. #114919 (alexey-milovidov). - Исправлена ошибка, из-за которой
ifиmultiIfвозвращали большое положительное значение вместо отрицательного, если ветвь типаTimeсочеталась сTime64,DateTimeилиDateTime64, а выражение JIT-компилировалось. #115146 (groeneai). - Исправлена ошибка, из-за которой
timezoneOffset(псевдонимtimeZoneOffset) возвращала смещение, ошибочное ровно на сутки, для часовых поясов, чьё смещение от UTC отличается от смещения на 1970-01-01 на целые сутки (например,Pacific/KiritimatiиPacific/Apiaпосле их перехода через международную линию перемены дат), а также для большинства поясов до 1970 года. Заодно исправленыparseDateTime,parseDateTimeOrNull,parseDateTime64,parseDateTimeInJodaSyntax,EXTRACT(TIMEZONE_HOUR / TIMEZONE_MINUTE ...),%zвformatDateTime,toUTCTimestampиfromUTCTimestamp, которые используют это смещение. #115332 (groeneai). - Исправлена ошибка
Code: 349. Cannot convert NULL value to non-Nullable type, возникавшая, когда предикатhasилиnotHasсодержит элемент массива со значением NULL, а первичный ключ имеет типString,Array(String)илиMap(String, String). Также исправлены неверные результаты в случае, когда этот элемент имеет типDynamicилиVariantи содержит NULL. Теперь при анализе ключа значение NULL исключается из множества, как это уже делалось для ключей других типов. #115647 (groeneai). - Исправлена ошибка, из-за которой настройка
cast_keep_nullableне сохраняла допустимость NULL, если целевой тип —LowCardinality. Приведение значения, которое может быть NULL, кLowCardinality(T)завершалось ошибкойCANNOT_INSERT_NULL_IN_ORDINARY_COLUMNвместо того, чтобы возвращатьLowCardinality(Nullable(T)). #115851 (groeneai).
Исправления индексов и кэша запросов
- Исправлено чтение подстолбцов столбца, у которого задано выражение
DEFAULTи который не материализован в части (например, послеALTER TABLE ADD COLUMNили во времяALTER TABLE MATERIALIZE COLUMN): подстолбец заполнялся значениями по умолчанию для типа вместо вычисленного выраженияDEFAULT, а транспонированные функции векторного расстояния (cosineDistanceTransposedи другие) для таких столбцовQBitзавершались ошибкойSIZES_OF_ARRAYS_DONT_MATCH. #110636 (alexey-milovidov). - Исправлено исключение
Not-ready Set is passed as the second argument, которое могло возникать, если построение множества для подзапросаINво время анализа первичного ключа молча завершалось неудачей (например, при тайм-ауте подзапроса сoverflow_mode = 'break'), из-за чего множество так и оставалось непостроенным для конвейера запроса. #107924 (alexey-milovidov). - Исправлена ошибка
NOT_FOUND_COLUMN_IN_BLOCKпри выполненииSELECTдля таблицы с индексом пропуска данных типаset, если политика строк фильтрует её с помощью всегда истинного условия в сочетании с проверкой неиндексированного столбца. #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, а удаление refreshable materialized view или выполнение для негоSYSTEM STOP VIEWблокировалось, если его обновление застряло в таком ожидании. #109116 (murphy-4o). - Исправлены неверные результаты запросов, вызванные некорректным отсечением гранул индексом первичного ключа для таблиц с ключевым столбцом в обратном порядке (
DESC), когда у частей нет финальной метки (неадаптивная гранулярность,index_granularity_bytes = 0). #109901 (nihalzp). - Исправлены логическая ошибка
Expected CommonSubplanReferenceStep to reference CommonSubplanStep, ошибкаSubplan cannot be used to build pipelineи логическая ошибкаTrying to extract chunk from ChunkBuffer before all inputs are finishedдляIN (subquery), когда подзапрос содержит коррелированный подзапрос, а множество строится во время анализа индекса. #110491 (alexey-milovidov). - Исправлена ошибка
NOT_FOUND_COLUMN_IN_BLOCKдля транспонированных функций расстояния над столбцамиQBit(например,cosineDistanceTransposed), вызываемых со скалярным подзапросом или константным опорным вектором при включённых параллельных репликах. #110729 (alexey-milovidov). - Исправлена ситуация, когда текстовый индекс не использовался, если его выражение содержит сравнение с пустой строкой, например
arrayFilter(s -> s != '', ...): настройкаoptimize_empty_string_comparisonsпереписывает сравнение вnotEmptyтолько на стороне запроса. #112115 (Ergus). - Столбцы больше не удаляются, если на них ссылаются одновременно условия фильтрации
PREWHEREиWHERE, даже если они переписаны в виртуальный столбец текстового индекса. #114460 (ahmadov). - Исправлена логическая ошибка
Multi-block postings must be compressedв запросах к таблицам с текстовым индексом в режиме ленивого применения posting-list, возникавшая при отмене запроса во время чтения. #114636 (CurtizJ). - Исправлены неверные результаты в случаях, когда предложение
WHEREсодержало выражениеNULLвнутриNOT, напримерSELECT count() FROM t WHERE NOT (id >= 20 AND NULL). Анализ индекса считал такое условие заведомо истинным для всего диапазона, поэтому фильтр пропускался:count()учитывал строки, отбрасываемые запросом, аALTER TABLE ... DELETEс этим условием удалял строки, которые должны были остаться. #115152 (groeneai). - Исправлена ошибка
LOGICAL_ERROR(Join is supported only for pipelines with one output port) для JOINfull_sorting_mergeпри включённомquery_plan_join_shard_by_pk_ranges, когда у одной из сторон после отсечения не остаётся ни одной части — по первичному ключу, по статистике столбцов или из-за того, что таблица пуста. #115352 (alexey-milovidov). - Кэш условий запроса отключён для фильтров по _part_starting_offset #115358 (azat).
- Исправлена ошибка
LOGICAL_ERROR: Index with name auto_minmax_index_<column> already exists, возникавшая, когда в одном оператореALTER TABLEкомандаRENAME COLUMNсочеталась с другой командой, напримерMODIFY SETTING, для таблицы с неявными индексами minmax (add_minmax_index_for_numeric_columnsи аналогичные настройки). Кроме того, после переименования обычного столбца последующийDROP COLUMNбольше не завершается ошибкойUNKNOWN_IDENTIFIER, а последующийADD COLUMNбольше не создаёт столбец без неявного индекса. #116063 (groeneai). - Шаблон
LIKE/NOT LIKEбез подстановочных символов (%,_) теперь использует точный диапазон первичного ключа и поэтому читает столько же гранул, сколько эквивалентный предикат=/!=, а не более широкий префиксный диапазон. #107077 (groeneai). - Исправлены ошибка
LOGICAL_ERROR(Invalid binary search result in MergeTreeSetIndex) и отсутствие отсечения по индексу в релизных сборках, когда условиеIN/NOT INпо первичному ключу оборачивает ключ вintDivна константу, а ключ является беззнаковым целым числом, значения которого пересекают знаковую границу типа результатаintDiv(например,intDiv(uint64_column, -9223372036854775807)). #107586 (groeneai). - Исправлена ошибка, из-за которой
numericIndexedVectorPointwiseMultiplyвозвращала пустой результат при умножении на вектор из одних единиц с другой битовой конфигурацией BSI. #108027 (alexey-milovidov). - Исправлено переполнение буфера в куче (heap-buffer-overflow) при построении текстового индекса с
positions = 1по большому количеству различных коротких токенов. #108659 (groeneai). - Выражения
preprocessorиpostprocessorтекстового индекса теперь могут ссылаться на столбцыALIAS. #110014 (Ergus). - Оптимизация векторного поиска теперь не применяется при использовании
LIMIT ... WITH TIES, поскольку она ограничивает ANN-поиск ровно n кандидатами, из-за чего строки с тем же значением, что и у n-й строки, отбрасываются. #110453 (tamish560). - Исправлена ошибка, из-за которой текстовый индекс не использовался для
ILIKE, если индекс построен по выражению, а не просто по столбцу (например,assumeNotNull(col)с препроцессоромlower(...)). Теперь такие запросы используют индекс, а не читают все гранулы. #110595 (ahmadov). - Исправлена ошибка
LOGICAL_ERROR(LazyMaterializingTransform: Number of rows in lazy chunk N does not match number of offsets M), которая могла возникать в запросах векторного поиска сvector_search_with_rescoring = 1в сочетании с отложенной материализацией, если несколько расстояний совпадали. #111003 (groeneai). - При использовании индекса
vector_similarityс квантованиемi8теперь отклоняются векторы, квадрат модуля которых переполняется до бесконечности (ранее такие векторы вызывали неопределённое поведение в usearch и молча порождали мусорные данные). #111085 (groeneai). - Исправлено чтение устаревших данных с дисков
plain_rewritableпри включённом страничном кэше. #111105 (Michicosun). - Исправлены неверные результаты
count()и потеря строк при фильтрации ключа или minmax-индекса пропуска данных поString(или более узкомуFixedString) путём сравнения с более широкой константойFixedString, напримерtoFixedString('abc', 257) = string_col. Отсечение по первичному ключу и minmax строило диапазон по константе, дополненной символами NUL, и ошибочно пропускало подходящие гранулы. #111106 (groeneai). - Исправлено чтение файлов Parquet, у которых индекс смещений начинается не со строки 0. Из-за таких файлов нативный ридер Parquet мог возвращать неверные строки или выдавать ошибку
LOGICAL_ERRORвместоINCORRECT_DATA. Теперь индекс смещений проверяется при чтении. #114530 (groeneai).
Исправления в области безопасности, доступа, резервного копирования и восстановления
RESTOREтеперь выполняет fsync для восстановленных файлов частей, если для целевой таблицы включён параметрfsync_after_insert, поэтому восстановленная часть так же устойчива к отключению питания, как и вставленная. Ранее восстановленные файлы лишь записывались и закрывались (fsync не выполнялся), поэтому отключение питания сразу после того, какRESTOREвернулRESTORED, могло оставить части повреждёнными, а таблицу — пустой. #111378 (groeneai).- Исправлена уязвимость, из-за которой неаутентифицированный TCP-клиент мог через межсерверный порт проверять существование таблиц и состояние репликации. #99854 (tiandiwonder).
- Исправлена ошибка, из-за которой для
DELETE FROM(легковесное удаление) помимоALTER DELETEтребовалась ещё и привилегияALTER UPDATE. Пользователь, которому выдана только привилегияALTER DELETE, теперь может выполнятьDELETE FROM, как и указано в документации. #107491 (tiandiwonder). - Исправлена ошибка, из-за которой
CREATE TABLE ... AS SELECTв базах данных Atomic оставлял пустую таблицу при сбое запроса — например, когда у пользователя нет доступа к таблице, на которую ссылается подзапрос. Ранее при повторной попытке вместо исходной ошибки выдавалось сообщение о том, что таблица уже существует. Теперь таблица создаётся через временную таблицу и становится видимой только после полного заполнения. #108048 (alexey-milovidov). - Исправлена ошибка
LOGICAL_ERROR(No available columns) при выполненииSELECT count()(или других тривиальных запросов) к таблице, в которой пользователю выдан доступSELECTтолько к столбцуALIAS. #108056 (alexey-milovidov). - Исправлена проблема, из-за которой неаутентифицированные запросы могли заставить ClickHouse разрешать имена хостов, переданные в заголовках с перенаправленным адресом клиента. Теперь ClickHouse принимает из этих заголовков только числовые IP-адреса. Недопустимые значения игнорируются при учёте квот по перенаправленному адресу, DNS-разрешение для них не выполняется. Если включён параметр
auth_use_forwarded_address, недопустимые перенаправленные адреса отклоняются при аутентификации. Отказы записываются в лог на уровне debug. #111060 (otselnik). - Исправлено игнорирование
SQL SECURITY DEFINER(иSQL SECURITY NONE) для параметризованных представлений при отключённом анализаторе (enable_analyzer = 0). Ранее выборка из такого представления пользователем без привилегий на базовую таблицу завершалась ошибкойACCESS_DENIED, хотя при включённом анализаторе то же представление работает. #111458 (groeneai). - Исправлен дефект в интеграциях
MySQL: переопределение TLS-учётных данных именованной коллекции пустым значениемssl_ca_pem/ssl_cert_pem/ssl_key_pemпринималось, если коллекция хранила учётные данные в виде содержимого. В результате настроенный CA или клиентский сертификат незаметно отбрасывался, хотя переопределение должно было отклоняться. #113947 (alexey-milovidov). - Исправлена потеря статистики JOIN в
EXPLAIN ANALYZEдля представления, объявленного сSQL SECURITY DEFINERилиSQL SECURITY NONE, тело которого содержит JOIN. В отладочных сборках и сборках с санитайзерами запрос аварийно завершался с логической ошибкойJoinStep analyzed without the analyze mode. #115156 (groeneai). - Исправлена ошибка, из-за которой после
RESTORE ... AS <new name>списокREFRESH ... DEPENDS ONу refreshable materialized view продолжал указывать на исходную базу данных. Восстановленное представление обновлялось в ответ на изменения таблицы, которую оно больше не читало, игнорировало обновления собственного родителя и полностью переставало обновляться после удаления исходной базы данных. #115689 (groeneai). - Исправлено исключение
LOGICAL_ERRORпри создании резервной копии базы данныхReplicated, которая параллельно удаляется и создаётся заново; теперь такое резервное копирование корректно завершается ошибкойCANNOT_GET_REPLICATED_DATABASE_SNAPSHOT. #100651 (alexey-milovidov). - Запрос
GRANT role TO roleдля одной и той же роли теперь отклоняется с ошибкойBAD_ARGUMENTS, а не создаёт без предупреждения запись вsystem.role_grants, ссылающуюся на саму себя. #103315 (zxuhan). BACKUPбазы данныхMaterializedPostgreSQLбольше не зависает навсегда с сообщением «Table … were created or changed its definition during scanning» и теперь действительно сохраняет данные таблиц (делегируя это базовому движкуReplacingMergeTree); их можно восстановить как автономную таблицуReplacingMergeTree. #107433 (alexey-milovidov).- Запрос
EXISTS <dictionary>теперь разрешён пользователю, у которого есть только привилегияSHOW DICTIONARIESна словарь (ранее требоваласьSHOW TABLES). #108084 (alexey-milovidov). - Исправлена очистка после
BACKUP ... TO Memory(...), завершившегося ошибкой до финализации: неудавшаяся резервная копия оставалась зарегистрированной, и её имя нельзя было использовать повторно. #109947 (jkartseva). - Исправлена логическая ошибка
ReadBuffer is canceled. Can't read from it.(аварийное завершение сервера в сборках debug/sanitizer), которая могла возникать при чтении zip-архива (например, приRESTOREиз резервной копии в формате zip), если предыдущее чтение из того же архива прервалось с ошибкой на середине потока. #110197 (groeneai). - Исправлено повреждение кучи, которое могло приводить к аварийному завершению сервера при остановке:
const-методAccessRights::getFiltersизменял дерево прав доступа, совместно используемое параллельными запросами. #112692 (groeneai).
Распределённое выполнение, таблицы, представления и словари
- Исправлена ложная ошибка
Inconsistent AST formattingдляALTER TABLE ... MOVE PART ... TO SHARD '<path>'. Форматировщик запросов терял ключевое словоSHARD, из-за чего переформатированный запрос не удавалось разобрать обратно и возникала ошибкаLOGICAL_ERROR(обрабатываемое исключение в релизных сборках, аварийное завершение в отладочных сборках и сборках с санитайзерами). #109060 (groeneai). - Исправлена логическая ошибка (
!part.empty()), возникавшая, когда таблицаDistributed, определённая с пустым именем удалённой базы данных, использовалась в JOIN приdistributed_product_mode = 'local'. #110677 (groeneai). - Исправлена ошибка, из-за которой запрос с
DISTINCTи упорядоченнымLIMIT/OFFSETвозвращал неверные строки, если подсказка раннего останова DISTINCT не могла ограничить начало результата: при отрицательномLIMIT(возвращалось начало вместо конца), при дробномLIMIT/OFFSET(дробь вычисляется только после полного чтения) и при одиночномOFFSETбезLIMIT(конец после смещения отбрасывался). Например,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).
- Исправлено аварийное завершение сервера (
Logical error: 'Block structure mismatch'), которое могло происходить при конкурентномINSERTво время выполненияALTER RENAME COLUMNв базе данныхAtomicсlazy_load_tables = 1послеDETACH DATABASE/ATTACH DATABASE. #104852 (groeneai). - Исправлены повреждение имён столбцов и исключение
BAD_ARGUMENTS, вызванные настройкойinject_random_order_for_select_without_order_by. При включённой настройке SELECT-запросы с несколькими столбцами больше не завершаются ошибкой, а имена выходных столбцов (например, дляCREATE TABLE AS SELECT,CREATE VIEW AS SELECT,JSONEachRow) сохраняются и не заменяются внутренними псевдонимами__subquery_column_<UUID>. #105896 (groeneai). - Исправлена вводящая в заблуждение подсказка «Maybe you meant X?» после перезапуска сервера (или
DETACH/ATTACH DATABASE): при удалении уже удалённой таблицы в качестве альтернативы предлагалось только что удалённое имя. Теперь при отключении задачи асинхронной загрузки удаляются изDatabaseOrdinary::startup_tableиload_table. #106238 (groeneai). - Исправлены движки таблиц и баз данных
MaterializedPostgreSQL: теперь отдельную таблицу или базу данных можно реплицировать из нестандартной схемы PostgreSQL (materialized_postgresql_schema), в том числе когда таблицы с одинаковым именем существуют в нескольких схемах одной базы данных (ранее они использовали общие публикацию и слот репликации и мешали друг другу). #107425 (alexey-milovidov). - Исправлены ошибки:
NO_SUCH_COLUMN_IN_TABLE, когда запрос с параллельными репликами выбирает столбецALIASтаблицы, передаваемой как временная таблицаGLOBAL JOIN;MULTIPLE_EXPRESSIONS_FOR_ALIAS, когда в обеих частях распределённогоJOINобъявлен столбецALIASс одинаковым именем;UNKNOWN_IDENTIFIER, когда в таблицеDistributedобъявлен столбецALIAS, основанный на другом столбцеALIAS, в том числе используемый в качестве ключаJOIN USING. #107700 (yakov-olkhovskiy). - Исправлено знаковое целочисленное переполнение, возникавшее, когда refreshable materialized view повторяет неудачное обновление при очень большом значении
refresh_retries(близком к максимумуInt64). В сборках с санитайзером неопределённого поведения это переполнение могло приводить к аварийному завершению сервера. #108005 (groeneai). - Исправлено исключение (
CANNOT_PARSE_TEXT) при загрузке словаря с составным ключом, столбцы ключа которого не являются первыми столбцами в определении словаря, если используется локальный источникClickHouseс явно заданным запросом. Теперь столбцы источника сопоставляются со структурой словаря по имени, а не по позиции. #108053 (alexey-milovidov). - Исправлен сбой (разыменование нулевого указателя) при запросе к таблице
Hiveбез предложенияWHERE, напримерSELECT * FROM hive_table. #108094 (alexey-milovidov). - Исправлен сбой сервера (ошибка сегментации), который мог возникать, когда распределённый запрос ссылался на ещё не материализованный CTE
MATERIALIZEDкак на внешнюю таблицу, а удалённый источник создавался отложенно (delayed source). Причиной сбоя было разыменование нулевого указателя наLoggerвнутриRemoteQueryExecutor::sendExternalTables(). #108547 (groeneai). - Исправлена логическая ошибка (
Equal values are not contiguous within the range assumed to be sorted) при выполненииDISTINCTповерх чтенияSTREAM(SELECT DISTINCT ... FROM table STREAM). Оптимизации чтения в порядке сортировки больше не применяются к чтениюSTREAM, поскольку оно возвращает строки в порядке фиксации, а не в порядке ключа сортировки. #108568 (groeneai). - Исправлено исключение (
Cannot find sharding key column, а в debug-сборках и сборках с санитайзером — аварийное завершение сервера), возникавшее, когда ключ сегментирования таблицыDistributedпредставляет собой выражение, которое анализатор сворачивает в константу, напримерif(1, toInt32(id), toInt32(id) + 1), приoptimize_skip_unused_shards = 1. #108737 (groeneai). - Исправлено аварийное завершение сервера (
LOGICAL_ERROR/ срабатывание assertion в debug-сборках и сборках с санитайзером) при отменеINSERT ... SELECTчерез таблицуAliasбез исключения, например приtimeout_overflow_mode = 'break'. #108783 (groeneai). - Исправлено аварийное завершение сервера (
LOGICAL_ERROR/ срабатывание assertion в debug-сборках и сборках с санитайзером) при отменеINSERT ... SELECTв таблицуTimeSeriesбез исключения, например приtimeout_overflow_mode = 'break'. #108796 (tiandiwonder). - Исправлены периодические сбои распределённых запросов с ошибкой
UNEXPECTED_PACKET_FROM_SERVER(«expected TablesStatusResponse, got ProfileInfo»), возникавшие при повторном использовании из пула соединения, которое предыдущий отменённый запрос оставил в рассинхронизированном состоянии. #108854 (alexey-milovidov). - Исправлена ошибка
LOGICAL_ERROR(CTE '...' does not have query tree, but was not planned yet), возникавшая, когда на CTEMATERIALIZEDссылались из нескольких позиций дерева JOIN (например, из двух соединяемых подзапросов или из соединяемого подзапроса и скалярного подзапроса вWHERE) в запросе к таблицеDistributed. Теперь запрос выполняется успешно, а не завершается исключением (в debug-сборках и сборках с санитайзером это приводило к аварийному завершению сервера). #108924 (groeneai). - Исправлена проблема безопасности памяти, из-за которой асинхронные задачи, запланированные при обработке materialized view, могли продолжать использовать учёт ресурсов на уровне запроса уже после его завершения. #108988 (filimonov).
- Исправлена ошибка
LOGICAL_ERROR(“Cannot find__grouping_setcolumn in header of MergingAggregatedTransform with grouping sets” или “Chunk info was not set for chunk in MergingAggregatedTransform”), которая могла возникать без анализатора в запросах сUNION ALL/INTERSECT/EXCEPT, если одна ветвь используетGROUP BY GROUPING SETSс параллельными репликами, а другая —FINAL. #109003 (groeneai). - Исправлен сбой
CREATE TABLE ... AS SELECT FROM s3Cluster(...)(и других кластерных табличных функций, таких какfileCluster/urlCluster) с ошибкойNOT_FOUND_COLUMN_IN_BLOCKв базе данныхReplicated. #109266 (groeneai). - Исправлена ошибка (
NOT_FOUND_COLUMN_IN_BLOCKилиstd::bad_function_callв более ранних версиях) при выполненииCREATE TABLE ... ON CLUSTER ... AS SELECTс чтением из таблицыDistributedв кластере с двумя и более шардами. #109407 (alexey-milovidov). - Исправлена малопонятная внутренняя ошибка (
Method getResultType is not supported for TABLE query tree node), возникавшая при использовании табличного выражения в качестве левого аргумента оператораIN; теперь для таких запросов выводится понятное сообщение об ошибке. #109412 (alexey-milovidov). - Исправлена логическая ошибка
Bad cast from type DB::FunctionNode to DB::ConstantNode(аварийное завершение сервера в отладочных сборках и сборках с санитайзерами) при выполненииSELECT ... ORDER BY ... WITH FILLк таблицеDistributedс низким значениемoptimize_const_name_size. #109938 (groeneai). - Исправлена ошибка
LOGICAL_ERROR(Left and right columns have same names) в оптимизаторе порядка JOIN, которая могла возникать при JOIN через запятую над многотабличным представлением, если включена настройкаquery_plan_merge_expression_into_join. #110227 (groeneai). - Исправлена редкая ошибка
Logical error: 'No more packets are available.', возникавшая при выполнении корректного распределённого запроса сLIMITи приводившая к аварийному завершению сервера в отладочных сборках и сборках с санитайзерами. #110334 (groeneai). - Исправлена ошибка парсера, из-за которой COMMENT ошибочно воспринимался как неявный псевдоним, если запрос SELECT заканчивался сразу после идентификатора таблицы (например,
... FROM t COMMENT 'x'): вместо применения комментария к представлению/таблице возникала вводящая в заблуждение синтаксическая ошибка. #110372 (adityaksolves). - Исправлен неверный результат:
length()(и размерность QBit) для столбцаFixedStringвозвращала0вместо фиксированного размераNпри использовании параллельных реплик, если в запросе был селективный фильтр. #110427 (groeneai). - Исправлена ошибка
NOT_FOUND_COLUMN_IN_BLOCKдля запросов с подзапросом воFROMпри работе параллельных реплик в режимеcustom_key_sampling/custom_key_range. Ранее такие запросы (например,SELECT * FROM (SELECT id, k, v FROM t WHERE id < 20) ORDER BY k) завершались ошибкойNot found column __table2.id in block .... #110690 (groeneai). - Исправлена ошибка
Logical error: 'clock'(в отладочных сборках и сборках с санитайзерами сервер аварийно завершается, а в релизных сборках происходит бесконечное зависание) при выполненииEXPLAIN ANALYZEдля запроса с потоковым чтением (FROM ... STREAM), которое не является простым табличным выражением верхнего уровня, а вложено в подзапрос (например, внутриWHERE ... IN (...)или CTE) либо скрыто за обычным или параметризованным представлением. ТеперьEXPLAIN ANALYZEотклоняет такие запросы с ошибкойNOT_IMPLEMENTED— так же, как уже отклоняет потоковое чтение верхнего уровня. #110935 (groeneai). - Исправлено разрешение полностью квалифицированных имён столбцов, таких как
db.table.column, в анализаторе для таблиц, имя которых совпадает с именем их базы данных. #110976 (alexey-milovidov). - Исправлены ошибки
NOT_FOUND_COLUMN_IN_BLOCK/THERE_IS_NO_COLUMN(а в некоторых релизах — неверные результаты без каких-либо ошибок) дляRIGHT JOIN, когда задан параметрparallel_replicas_min_number_of_rows_per_replicaи в проекцию попадает столбец левой таблицы. #111332 (groeneai). - Исправлено состояние гонки в исполняемых UDF, движке таблицы
executableи исполняемых словарях, при котором вызовfcntlдля уже закрытого файлового дескриптора мог повредить посторонний дескриптор параллельного запроса (сбросив флагO_NONBLOCK), из-за чего запросы могли зависать на неопределённое время. #111779 (Algunenano). - Исправлена ошибка
LOGICAL_ERROR(«Invalid number of rows in Chunk»), а в усиленных сборках — связанное с ней аварийное завершение из-за выхода за границы, дляORDER BY ... WITH FILL ... INTERPOLATEнад таблицейDistributedс двумя или более сегментами, надclusterAllReplicasили над параллельными репликами с пользовательским ключом, в том числе при пустых результатах. ТеперьWITH FILLприменяется только на узле, формирующем итоговый результат, что также устраняет дублирование сгенерированных строк заполнения между сегментами/репликами. #111919 (yakov-olkhovskiy). - Исправлено бесконечное зависание
DROP TABLE ... SYNC, если запрос кsystem.replicasбыл прерван до того, как были обработаны его запросы статуса. #112164 (evillique). - Исправлено исключение
LOGICAL_ERROR(Block structure mismatch in joined block stream) при JOIN нескольких таблиц, когда оба вложенных JOIN не возвращают выходных столбцов, напримерSELECT count() FROM t1, t2, t3, t4 WHERE (t1.b = t2.b) AND (t3.a = t4.a)при значенииquery_plan_optimize_join_order_limit, равном0или1. #112205 (groeneai). - Исправлена логическая ошибка
Cannot add step Expression to QueryPlan because it has incompatible header with root step JoinLazyColumnsStepдля запроса сFINAL, фильтромPREWHERE, небольшимLIMITиmake_distributed_plan = 1, когда выбираемые столбцы перечислены в порядке, отличном от порядка столбцов таблицы. Механизм отложенной материализации заменял узел плана, не сохраняя его выходной заголовок, из-за чего план запроса становился несогласованным. #112303 (groeneai). - Исправлены неверные результаты и логическая ошибка, возникавшие при использовании старого анализатора, когда аргумент, который должен быть константой (например, масштаб в
toDecimal32или часовой пояс вtoDateTime), берётся из скалярного подзапроса. Такой аргумент анализировался так, будто его значение равно нулю или пусто, поэтому объявленный тип результата не совпадал с вычисленным значением, аCREATE VIEWиCREATE MATERIALIZED VIEWсохраняли неверный тип столбца. #112492 (groeneai). - Исправлены логическая ошибка и неверная запись зависимости, возникавшие, когда тело обычного
VIEWссылается на таблицу или словарь через параметр запроса, напримерCREATE VIEW v AS SELECT x FROM {db:Identifier}.t. Такое представление больше не регистрирует ссылочную зависимость от одноимённой таблицы текущей базы данных, поэтому не связанные с ним таблицы снова можно удалять. #112704 (groeneai). - Исправлена логическая ошибка, возникавшая при использовании движка таблицы
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). - Исправлены неопределённое поведение и незаметная ошибка планирования при постановке фоновой задачи с очень большой задержкой — например, в refreshable materialized view с огромным периодом
REFRESH AFTER. Теперь задержка ограничивается максимальным представимым значением и не переполняется. #113041 (groeneai). - Исправлено сообщение об ошибке, возникавшей, когда асинхронному
INSERTв таблицуDistributedтребуется каталог очереди, имя которого превышает ограничение файловой системы в 255 байт (что возможно приuse_compact_format_in_distributed_parts_names = 0). Для шарда сinternal_replicationэто была ошибкаLOGICAL_ERROR, а в остальных случаях —Code: 1001. std::exceptionбез указания источника; теперь в обоих случаях выдаётсяARGUMENT_OUT_OF_BOUNDс указанием таблицы, кластера и ограничения. #113083 (groeneai). UNDROP TABLEтеперь можно прервать с помощьюKILL QUERY, пока он ожидает, когда выполняющиеся запросы освободят удалённую таблицу. #113263 (alexey-milovidov).- Исправлены бесконечное зависание
DROP TABLEи утечка памяти после сбоя запроса, использующего материализованное CTE. Таблица оставалась в очереди удаления вплоть до перезапуска сервера. #113397 (tiandiwonder). - Исправлены segfault и ошибка
LOGICAL_ERROR(No host found for exchange stream final_result__0_0), возникавшие, когда подзапрос задаётdistributed_plan_execute_locallyв собственной секцииSETTINGSпри включённомmake_distributed_plan. Распределённый план и выполняющий его код считывали настройку из разных контекстов и могли получать разные значения, из-за чего инициатор строил внутренне противоречивый конвейер. #113422 (groeneai). - Исправлена проблема, из-за которой запрос
CREATE TABLE ... AS SELECTс завершившимся ошибкой заполняющимSELECTневозможно было прервать при включённой настройкеdatabase_atomic_wait_for_drop_and_detach_synchronously: внутреннийDROPвременной таблицы для очистки ожидал фоновую очередь удаления и игнорировал какKILL QUERY, так иmax_execution_time. #113504 (groeneai). - Исправлены неверные результаты, а в сборке с включёнными assertion — аварийное срабатывание assertion для
JOINсо словарём, секцияONкоторого содержит условие неравенства по обеим таблицам, напримерON (t.key = d.key) AND (t.a * 10 < d.a), при включённой настройкеjoin_use_nulls. Условие вычислялось по столбцу, прочитанному с несоответствующим типом, поэтому строки могли сопоставляться произвольно. #113534 (alexey-milovidov). - Исправлена ошибка, из-за которой параметризованное представление теряло свою базу данных, когда запрос, ссылающийся на него без указания базы данных, отправлялся на сегмент: в результате сегмент искал имя в собственной базе данных по умолчанию. В зависимости от содержимого этой базы данных запрос либо завершался ошибкой
UNKNOWN_FUNCTION, либо молча возвращал строки из другого представления. Проблема затрагивалаIN,JOINиremote()через таблицуDistributed. #113550 (groeneai). - Исправлена ошибка
Unsupported JOIN keys of type keys256 in StorageJoinпри чтении таблицы на движкеJoinс составным ключом (из нескольких столбцов) или ключом из одного 16/32-байтового значения, напримерUUID,Int256илиFixedString(4). Такую таблицу можно было создать, записать в неё данные и выполнять с ней JOIN, но прочитать её с помощьюSELECTбыло невозможно. #113578 (groeneai). - Исправлена логическая ошибка
Sending a distributed query with unknown (zero) client version, возникавшая при подключении таблицыDistributedбез описания структуры поверх удалённого сегмента или при её загрузке из метаданных, записанных сервером более старой версии. #113675 (alexey-milovidov). - Исправлена ошибка
LOGICAL_ERROR, возникавшая, когда вSELECTмодификаторSTREAMприменялся к именованной таблице одновременно с параллельными репликами в режиме задач чтения. Если materialized CTE использовалось как множествоINвPREWHERE, сервер выдавал ошибкуReading from materialized CTE ... DelayedPortsProcessor gate is missing in the query plan(а в отладочных сборках и сборках с санитайзерами аварийно завершался). Теперь таблица сSTREAMотклоняется при запросе параллельных реплик: приenable_parallel_replicas = 2запрос завершается ошибкойSUPPORT_IS_DISABLED, а при1выполняется без них — точно так же, как это уже происходит дляFINAL. #113754 (groeneai). - Устранена квадратичная сложность разбора аргумента адреса в табличных функциях
remote,mysqlи аналогичных: очень длинный адрес (например, дополненный нулямиFixedStringразмером в мегабайт) приводил к зависанию запроса на этапе анализа, где его невозможно было отменить. #113918 (alexey-milovidov). - Исправлена ложная ошибка
Failed to drop temporary table after refresh. Table ... is left behind and requires manual cleanup., которая записывалась в лог при отмене обновления refreshable materialized view (например, из-за остановки сервера) при включённой настройкеdatabase_atomic_wait_for_drop_and_detach_synchronously. На самом деле временная таблица удалялась, так что ручная очистка не требовалась. #113957 (groeneai). - Исправлено отсутствие строки в
system.query_views_logдля materialized view, завершающегося ошибкой во время сбора его зависимостей при включённой настройкеmaterialized_views_ignore_errors. В отладочных сборках и сборках с санитайзерами это также приводило к аварийному завершению сервера сstd::out_of_rangeвместо записи представления в лог. #114064 (groeneai). - Исправлены несогласованные результаты, возникавшие, когда фильтр по неключевому столбцу правой таблицы проталкивался ниже ANY INNER JOIN. #114313 (kirillshokhin).
- Исправлены утечка внутренней таблицы
_tmp_replace_*при выполненииCREATE OR REPLACEи ошибкаNOT_IMPLEMENTEDпри выполненииCREATE OR REPLACE VIEW, возникавшие при заданной настройкеignore_drop_queries_probability. Внутренние операции DROP являются шагами одной пользовательской инструкции, поэтому внедрение сбоев DROP к ним больше не применяется. #114420 (groeneai). - Исправлена ошибка
LOGICAL_ERRORпри чтении таблицы Delta Lake, у которой вmetaData.partitionColumnsуказан столбец, не объявленный вmetaData.schemaString. Теперь такие метаданные отклоняются с ошибкойBAD_ARGUMENTSв считывателе delta-kernel иINCORRECT_DATAв устаревшем считывателе при любом чтении таблицы или её схемы из снимка, а не только когда запрос содержит предикат. #114538 (groeneai). - Исправлена ошибка, из-за которой статистика хеш-таблиц, а вместе с ней и предварительное выделение памяти под хеш-таблицы агрегации, незаметно и навсегда отключалась для всего сервера, если первой агрегацией после запуска сервера оказывался запрос с отложенной оптимизацией
FINAL(query_plan_optimize_lazy_final). #114597 (alexey-milovidov). - Исправлена утечка вытесненной при ротации целевой таблицы refreshable materialized view при включённом параметре
ignore_drop_queries_probability. ЗапросDROP, который выполняется при обновлении для удаления предыдущей целевой таблицы, является шагом обновления, а не запрошенным пользователемDROP, поэтому внедрение сбоев к нему больше не применяется. #114622 (groeneai). - Исправлена ошибка, из-за которой
ANY RIGHT JOINиSEMI RIGHT JOINс несколькими условиями, объединёнными черезOR, в секцииONвозвращали некоторые строки правой таблицы дважды и теряли совпадения для других. Проблема затрагивала и явно указанныйANY LEFT JOIN, поскольку планировщик может поменять таблицы местами и выполнить его какANY RIGHT JOIN. #114676 (vdimir). - Исправлена ошибка
LOGICAL_ERROR(Cannot find input column ... on its position in inputs of expression actions DAG), возникавшая, если в запросе естьJOINнад таблицей, столбец с текстовым индексом которой используется в предикатах полнотекстового поиска одновременно вPREWHEREиWHERE. #114771 (groeneai). - Исправлена ошибка
NOT_FOUND_COLUMN_IN_BLOCKпри каждомINSERTв таблицу, в которой объявленоSTATISTICS(...)для столбцаALIASилиEPHEMERAL, из-за чего такие таблицы фактически становились доступны только для чтения. #115231 (groeneai). - Исправлена работа
dictGetи его вариантов в распределённых запросах: неполное имя словаря теперь привязывается к текущей базе данных инициатора, а не разрешается относительно текущей базы данных каждого шарда, где словарь либо не находился, либо разрешался в другой словарь с тем же именем. #115541 (alexey-milovidov). - Исправлена ошибка, из-за которой при восстановлении базы данных или таблицы под новым именем из тел сохранённых представлений удалялись псевдонимы таблиц, и чтение восстановленного представления завершалось ошибкой
UNKNOWN_IDENTIFIER. #115645 (groeneai). - Исправлена ошибка
LOGICAL_ERROR«Reading from materialized CTE ‘X’ before its materialization completed - DelayedPortsProcessor gate is missing in the query plan», возникавшая при чтении CTE сMATERIALIZEDвнутри подзапросаINнад таблицейDistributed. #115740 (groeneai). - Исправлена ошибка BAD_ARGUMENTS «Dictionary not found» при вызове dictGet после команды DETACH DICTIONARY … PERMANENTLY, отклонённой проверкой зависимостей (HAVE_DEPENDENT_OBJECTS). Теперь, если отсоединение отклонено, словарь остаётся полностью работоспособным. #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).
- Исправлено зависание
SYSTEM RELOAD DICTIONARIES(иRELOAD DICTIONARY), когда множество словарей MySQL, определённых в XML, использовали общий пул соединений черезshare_connection. Теперь такие пулы учитывают параметрыconnection_pool_sizeиconnection_wait_timeout(по умолчанию 5 секунд) из конфигурации — так же, как словари, определённые через именованные коллекции. #108083 (alexey-milovidov). - Исчерпание повторных попыток для реплицируемых распределённых DDL-запросов, выполняемых лидером, больше не блокирует навсегда последующие DDL-запросы с
ON CLUSTER. #108505 (ahaanlimaye). - Исправлено возможное аварийное завершение (use-after-free) при одновременном выполнении
SYSTEM FLUSH DISTRIBUTEDиDROP TABLEдля одной и той же таблицыDistributed. #108684 (groeneai). - Исправлена ошибка
LOGICAL_ERROR(local_replica_plan_reading_step->getAnalyzedResult() == nullptr) в планировщике автоматических параллельных реплик, которая могла возникать при включённомautomatic_parallel_replicas_modeи значенииparallel_replicas_min_number_of_rows_per_replicaбольше 0. #109011 (groeneai). - Исправлена ошибка
LOGICAL_ERROR(creation_csn is not set while removal_csn is set to 1), которая могла возникать, когда нетранзакционныйTRUNCATEвыполнялся одновременно с незакоммиченной транзакцией, вставлявшей данные в ту же таблицу. Теперь такойTRUNCATEне удаляет части, созданные ещё не закоммиченными транзакциями. #109598 (tuanpach). - Движки внешних баз данных (например,
PostgreSQL) больше не передают во внешнюю СУБД сравнения диапазонов (>=,>,<=,<) для столбцов типаUUID. ClickHouse и внешние СУБД упорядочивают UUID по-разному, поэтому передача таких условий незаметно приводила к потере строк в результате; теперь эти предикаты вычисляет сам ClickHouse. #109833 (vismaytiwari). - Исправлено аварийное завершение сервера в движке баз данных
MaterializedPostgreSQL, которое могло происходить, если таблицу отсоединяли (или меняли её структуру), пока она ещё находилась в очереди на синхронизацию. #110596 (alexey-milovidov). - Исправлена перезапись типа столбца
EPHEMERALсерверными правиламиquery_masking_rules. Если правило срабатывало внутри типа,CREATE TABLEсохранял неверный тип или завершался ошибкой. #112048 (alexey-milovidov). - Исправлен выход за нижнюю границу диапазона беззнакового целого при проверке длины имени таблицы, из-за которого можно было создать таблицу, которую затем невозможно удалить. Когда экранированное имя базы данных достигало 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). - Исправлен столбец
viewsвquery_logпри вставке в таблицуAlias, целевая таблица которой запускает materialized view: ранее он всегда оставался пустым. #113076 (eclbg). - Некорректные выражения
parallel_replicas_custom_key, напримерtuple()или(x, y), теперь отклоняются с ошибкойILLEGAL_TYPE_OF_COLUMN_FOR_FILTER, а не приводят к чтению за пределами списка типов пользовательского ключа. #113359 (nickitat). - Исправлена ошибка, из-за которой
RENAME DATABASEдопускал настолько длинное целевое имя, что таблицы базы данных становилось невозможно удалить. Проверка длины имени таблицы теперь выполняется независимо отcheck_table_dependenciesи распространяется также на отсоединённые таблицы, которые раньше вообще не проверялись и поэтому были подвержены проблеме даже при настройках по умолчанию. #113557 (groeneai). - При фоновых вставках в таблицы с движком
Distributedзадержки, вызванные повторяющимися ошибками отправки данных на удалённые шарды, теперь сокращаются после устранения ошибок. Раньше задержка только росла и никогда не сбрасывалась. #87378 (Blackmorse). - Теперь отклоняются рукопожатия по собственному протоколу, использующие
USER_INTERSERVER_MARKERдля неизвестного кластера или для кластера, настроенного без<secret>. Раньше такое рукопожатие позволяло неаутентифицированному клиенту перейти в режим межсерверного взаимодействия и отправлять пакеты протокола, доступные до аутентификации (например,TablesStatusRequest), которые обрабатывались с использованиемfake_interserver_context. Так клиент мог получать сведения о локальных таблицах, не подтверждая знание секрета кластера. #99675 (MillaFleurs).
Исправления в SQL, анализаторе и JOIN
- Исправлена подстановка параметров запроса внутри определений именованного предложения
WINDOW. Ранее параметры в нём молча оставались без подстановки, а незаданный параметрIdentifierмог приводить к исключениюLogical error: '!part.empty()'при выполненииEXPLAIN SYNTAX. #110506 (alexey-milovidov). - Исправлено редкое аварийное завершение сервера при одновременном удалении или замене refreshable materialized view. В
RefreshTask::doSchedulingпроисходило разыменование нулевого указателя, если другой поток устанавливалviewзадачи вnullptr, пока код планирования временно освобождал свой мьютекс. #105588 (groeneai). - Исправлен неверный результат после
DETACH/ATTACHили перезапуска сервера для представления, определённого сEXCEPTилиINTERSECT, операндом которого является цепочкаUNION. Форматировщик не добавлял скобки вокруг дочернихUNIONуINTERSECT/EXCEPT, поэтому при повторном разборе сохранённого SQL приоритет операций оказывался обратным. #105935 (groeneai). - Исправлены неверные результаты (дублирующиеся строки) для
SELECT DISTINCTповерхGROUP BYсWITH CUBE,WITH ROLLUPилиGROUPING SETSпо тем же ключам. Оптимизацияquery_plan_remove_redundant_distinctбольше не удаляетDISTINCTв этих случаях, поскольку модификаторы группировки выдают дополнительные строки, в которых столбцы ключа заполнены значениями по умолчанию, и они могут совпасть с реальными значениями групп. #107072 (groeneai). - Исправлен неверный результат OUTER JOIN, когда фильтр в предложении
WHEREявляется конъюнкцией с постоянным членом (например,p AND 1илиWHERE p QUALIFY NULL, гдеQUALIFY NULLобъединяется сWHERE). Постоянный конъюнкт мог проталкиваться в несохраняемую сторону JOIN и удаляться из фильтра после JOIN, из-за чего JOIN выдавал несопоставленные строки, в которых столбцы этой стороны были заполнены значениями по умолчанию, и такие строки ошибочно проходили фильтр. #107084 (groeneai). - Исправлена ошибка
LOGICAL_ERROR(“Cannot find input column … on its position in inputs of expression actions DAG”), приводившая к аварийному завершению сервера для коррелированного скалярного подзапроса над источником, который дважды проецирует один и тот же идентификатор столбца (например,SELECT number, *), приcorrelated_subqueries_default_join_kind = 'left'. #107112 (groeneai). - Исправлена ошибка
LOGICAL_ERROR(аварийное завершение сервера в отладочных сборках и сборках с санитайзерами), возникавшая при старом анализаторе (enable_analyzer = 0), когдаJOINиспользует null-безопасный оператор сравнения (<=>/IS NOT DISTINCT FROM), а один из ключей является скалярным подзапросом, например... JOIN t2 ON (SELECT x FROM t1) <=> t2.k. Теперь такой запрос возвращает обычную ошибкуNOT_FOUND_COLUMN_IN_BLOCKвместо логической ошибки. #108123 (groeneai). - Исправлены исключения
LOGICAL_ERROR(Join is supported only for pipelines with one output port) иNOT_IMPLEMENTED(MergeJoinAlgorithm is not implemented for strictness Semi) при использованииjoin_algorithm = 'full_sorting_merge'дляSEMI/ANTIJOIN, включая JOIN, полученные в результате декорреляции коррелированного подзапросаEXISTS. Теперьfull_sorting_mergeотклоняет сочетания строгости и вида JOIN, которые не может выполнить, поэтому планировщик переключается на другой включённый алгоритм или сообщает, что JOIN выполнить невозможно. #108658 (groeneai). - Исправлена ошибка, из-за которой строка
WITH TOTALSвJOINмогла содержать значения по умолчанию (например,0) вместо константных значений, получаемых из константного подзапроса на одной из сторон JOIN. Неверный результат возникал только при некоторых порядках соединения таблиц или при использовании настройкиquery_plan_join_swap_table. #108807 (vdimir). - Исправлено аварийное завершение при запуске (
Cannot allocate ThreadStack,EINVAL) в сборках с glibc на процессорах с большим размером стека сигналов (например, Intel Sapphire Rapids / Granite Rapids с ядром, поддерживающим AMX): размер альтернативного стека сигналов не округлялся вверх до значения, кратного размеру страницы, перед вызовомaligned_alloc. #108813 (groeneai). - Исправлена логическая ошибка
Block structure mismatch in JoinStep(аварийное завершение сервера в отладочных сборках и сборках с санитайзерами), возникавшая, когда коррелированный подзапрос декоррелируется в JOIN, а исходное отношение содержит одно и то же имя столбца несколько раз, напримерWITH t AS (SELECT number, * FROM numbers(3)) SELECT *, (SELECT t.number WHERE t.number >= 0) FROM tприcorrelated_subqueries_default_join_kind = 'right'. #109114 (groeneai). - Исправлено поведение
CREATE USER ... HOST LIKE 'a', 'b'(и аналогичногоALTER USER), при котором без каких-либо предупреждений сохранялся только первый шаблон. Теперь все указанные шаблоныHOST LIKEсохраняются в списке разрешённых хостов пользователя. #109187 (groeneai). - Исправлен неожиданный результат
ANY JOINс константным условиемON(например,t1 ANY INNER JOIN t2 ON 1): запрос возвращал полное декартово произведение вместо результата ANY JOIN #109207 (vdimir). - Исправлена ошибка, из-за которой глобальное ограничение
max_rows_in_join/max_bytes_in_joinне соблюдалось для алгоритма JOIN parallel_hash: запрос сjoin_overflow_mode = 'throw'мог без ошибок завершиться успешно вместо того, чтобы выдать ошибкуSET_SIZE_LIMIT_EXCEEDED. #109488 (m-selmi). - Исправлена скрытая потеря данных, возникавшая, когда за
INSERT ... VALUESв потоке из нескольких запросов следовал завершающий SQL-комментарий (например,VALUES (1) -- comment) при разборе встроенных данных вставки на стороне сервера (send_table_structure_on_insert_with_inline_data = 0). Завершающий комментарий считывался как данные строки за пределами завершающего;, из-за чего последующие запросы в потоке незаметно пропускались. #109643 (groeneai). - Исправлена работа отложенного
PREWHEREприoptimize_move_to_prewhere = 1, когдаPREWHEREвыполняется послеFINAL: условияWHEREбольше не переносятся впереди отложенной политики строк, что могло изменять результаты запросов. #109703 (yariks5s). - Исправлена ошибка
LOGICAL_ERROR(query tree node does not have valid source node), возникавшая, когда рекурсивное CTE разрешало идентификатор из внешней области видимости как коррелированный столбец (приallow_experimental_correlated_subqueries = 1). Теперь такие запросы возвращают понятную ошибкуUNSUPPORTED_METHOD. #109863 (groeneai). - Исправлено переполнение знакового целого, возникавшее, когда
ORDER BY ... WITH FILLпропускает очень большой разрыв в столбце типаInt64/UInt64(например, шаг 2 через разрыв около 2^63). При работе с санитайзерами переполнение приводило к неопределённому поведению, а в релизных сборках значения незаметно переносились по кругу. #109937 (groeneai). - Исправлена логическая ошибка
Invalid number of rows in Chunk, возникавшая при использовании старого анализатора (enable_analyzer = 0), когда цельюINTERPOLATEявляется псевдоним столбцаWITH FILL. Теперь такие запросы отклоняются с понятной ошибкойINVALID_WITH_FILL_EXPRESSION. #110103 (groeneai). - Исправлена логическая ошибка (
Unexpected number of columns in result sample block), возникавшая при оптимизации фильтра, содержащего коррелированный подзапрос (например,exists((SELECT ...))), с помощьюconvert_query_to_cnfилиoptimize_and_compare_chain. #110187 (alexey-milovidov). - Вложенный коррелированный подзапрос
EXISTS, ссылающийся на столбец из области видимости за пределами непосредственно объемлющего запроса (в обход промежуточной области видимости), теперь завершается понятной ошибкойNOT_IMPLEMENTEDвместо внутренней ошибкиNOT_FOUND_COLUMN_IN_BLOCK. #110310 (groeneai). - Исправлены неверные результаты коррелированных скалярных подзапросов в случаях, когда внешний запрос содержит повторяющиеся значения коррелированного столбца, а подзапрос декоррелируется через CROSS JOIN. Ранее результаты агрегатных функций, таких как
count()иsum(), умножались на число дубликатов. Исправление касается экспериментальной функциональностиallow_experimental_correlated_subqueries. #110311 (groeneai). - Исправлена ошибка, из-за которой
ORDER BY ... WITH FILLне учитывалmax_execution_timeи медленно отменялся при генерации большого диапазона заполнения (особенно сINTERPOLATE). #110332 (alexey-milovidov). - Оптимизация отложенного
FINAL(query_plan_optimize_lazy_final, по умолчанию отключена) больше не применяется, если запрос читает данные в порядке ключа сортировки: заменяющий план не выдаёт строки в порядке ключа сортировки, тогда как вышестоящая часть плана после оптимизации чтения в порядке ключа может уже на это полагаться, что могло приводить к неверному порядку результатов. Она также больше не применяется, когдаLIMIT, меньший числа читаемых строк, применяется непосредственно к шагу чтения: обязательный проход построения множества свёл бы на нет досрочное завершение. #110576 (KochetovNicolai). - Фоновый сброс на диск асинхронной вставки теперь оперативно останавливается при завершении через
KILL QUERY; ранее при сбросе большого объёма буферизованных данных разбор продолжался до конца, а отмена игнорировалась. #110652 (tiandiwonder). - Исправлены неверные результаты
GROUP BY ... optimize_aggregation_in_orderиDISTINCT ... optimize_distinct_in_order, расположенных поверх JOIN типаpartial_merge. Оптимизация чтения в порядке ключа распространялась черезPartialMergeJoin, который пересортировывает левый вход по ключу соединения и потому не сохраняет исходный порядок левого потока, из-за чего строки группировались неправильно. #110671 (groeneai). - Исправлена ошибка UNKNOWN_IDENTIFIER, возникавшая при использовании псевдонимов столбцов CTE в запросах с
INTERSECTилиEXCEPT, напримерWITH t (a, b) AS (SELECT 1, 2 INTERSECT SELECT 1, 2) SELECT a, b FROM t. #110885 (yariks5s). - Исправлена ошибка
LOGICAL_ERROR: ReadBuffer is canceled. Can't read from it., которая могла возникать в JOIN типаgrace_hash, если чтение сброшенных на диск блоков завершалось сбоем посреди операции, когда несколько потоков совместно использовали объект чтения. #111056 (groeneai). - Исправлена ошибка, из-за которой при материализации столбцов правой стороны во время *_hash JOIN использовался неверный часовой пояс. #111074 (yariks5s).
- Исправлены команды
CREATEс секциейCOMMENT: теперь при отсутствии строкового литерала комментария выдаётся синтаксическая ошибка, а не принимается молча неверно разобранный запрос (например,CREATE VIEW v COMMENT AS SELECT 1больше не создаёт представление без комментария). #111159 (tiandiwonder). - Исправлена ошибка
LOGICAL_ERROR(Reading from materialized CTE '...' before its materialization completed - DelayedPortsProcessor gate is missing in the query plan), возникавшая при чтении повторно используемого материализованного CTE (enable_materialized_cte) в ветви, выводWITH TOTALSилиextremesкоторой отбрасывается, в том числе при внешней агрегации,INSERT ... SELECT, операциях над множествами иEXPLAIN ANALYZE. #111194 (groeneai). - Исправлено поведение
join_algorithm = 'full_sorting_merge', при котором несоединённые строкиLEFT/RIGHT/FULL/ASOFJOINзаполнялись «сырым» нулём вместо значения по умолчанию для типа столбца. Для столбцаEnum(значением по умолчанию которого является его первый элемент, а не0) это приводило к неверным результатам (фильтр по дополненному значению отбрасывал несопоставленные строки, и внешний JOIN незаметно превращался во внутренний) и к ошибкеUNKNOWN_ELEMENT_OF_ENUMпри выборке этого столбца. #111197 (groeneai). - Исправлены неверные результаты
SummingMergeTree(иCoalescingMergeTree) сFINALприoptimize_move_to_prewhere_if_final = 1, когда предложениеWHEREсодержит неявное булево условие по столбцу ключа сортировки (например,WHERE k). Вместо того чтобы сохраняться, значение ключевого столбца суммировалось по неслитым частям. #111342 (groeneai). - Исправлена логическая ошибка (
Unexpected number of columns in result sample block), которая могла возникать приRIGHT/FULL JOIN, если левая сторона содержит дублирующийся одноимённый столбец (например,1 AS b, 1 AS b), сохраняющийся послеUNION ALL. #111554 (groeneai). - Исправлен сбой клиента при форматировании запроса
EXECUTE AS, в AST которого заменён дочерний узел (как это делает AST-фаззер). ТеперьASTExecuteAsQueryвладеет своими дочерними узламиtarget_userиsubquery, а не хранит невладеющие указатели на элементыchildren. #111725 (groeneai). - Исправлены неверные результаты, возникавшие, когда
query_plan_join_swap_tableменяет местами стороныANY JOINприjoin_any_take_last_row = 1: теперь ClickHouse сохраняет исходный порядок сторон JOIN, поэтомуANY JOINпо-прежнему возвращает последнюю совпадающую строку. #112458 (vdimir). - Исправлено исключение
Context has expiredпри использованииgetClientHTTPHeaderвнутри подзапроса. #112533 (alexey-milovidov). - Исправлены неверные результаты для
JOIN, секцияONкоторого содержит смешанное условие, то есть остаточное условие неравенства между сторонами, напримерON (t1.key = t2.key) AND (t1.a * 10 < t2.a). Такое условие вычисляют только алгоритмы семейства hash, однакоfull_sorting_merge,partial_mergeи прямой JOIN типа ключ-значение заявляли о поддержке таких JOIN, а затем молча игнорировали остаточное условие и возвращали лишние строки. Теперь они отказываются от выполнения, и вместо них используется hash-алгоритм. #112831 (groeneai). - Исправлены неверные результаты для JOIN через запятую или
CROSSJOIN, в которых предложениеWHEREсравнивает столбцы двух таблиц с помощью недетерминированного выражения, напримерrand. Такой запрос мог возвращать строки, противоречащие его собственному предложениюWHERE, поскольку при переписывании JOIN вINNERJOIN выражение переносилось в ключ JOIN, где оно повторно вычисляется для каждой строки каждой из сторон. #112938 (groeneai). - Исправлено квадратичное замедление при разборе запроса PromQL с длинным хвостом нераспознанных символов (например, значения
FixedString, дополненного байтами NUL): разбор некорректных входных данных размером около мегабайта занимал поток на десятки минут, и его нельзя было отменить, поскольку он выполняется на этапе анализа запроса. Теперь парсер останавливается на первой же ошибке. #112944 (alexey-milovidov). - Исправлено поведение
intDivдля непостоянного столбца с постоянным делителем -1: при делении минимального знакового числа (например,intDiv(-9223372036854775808, -1)) происходило незаметное переполнение вместо выбрасывания исключенияILLEGAL_DIVISION, как в других путях выполнения. Такое незаметное переполнение также могло приводить к неверным результатамORDER BY/DISTINCT, поскольку оптимизация чтения в порядке сортировки корректно считаетintDivна отрицательную константу монотонной функцией, а значение после переполнения нарушало итоговый порядок сортировки. #113048 (alexey-milovidov). - Исправлена ошибка
UNKNOWN_IDENTIFIERприenable_analyzer = 0, когда предложениеWHEREссылается на столбец, полученный с помощьюuntupleвнутри подзапроса, напримерSELECT t.keys FROM (SELECT untuple(arrayJoin(m)) AS t FROM ...) WHERE t.values > 0. Переписывание запроса, выполняемоеenable_optimize_predicate_expression, переносило такой предикат в подзапрос в видеHAVING, где это имя ещё не определено. #113760 (groeneai). - Исправлены неверные результаты
JOINсjoin_algorithm = 'partial_merge', когда правая сторона содержит итоговые значения (totals): правая сторона могла остаться без слияния, из-за чегоLEFTJOIN подставляли значения по умолчанию вместо реальных совпадений, аINNER/RIGHTJOIN вообще не возвращали строк. При обработке несовпавших строк дляRIGHT/FULLто же состояние приводило к разыменованию нулевого указателя и аварийному завершению сервера. #113936 (groeneai). - Исправлены неверные результаты
SELECT DISTINCTсLIMIT, которому необходимо прочитать все входные данные:LIMIT n WITH TIESотбрасывал строки с равными значениями,exact_rows_before_limit = 1возвращал усечённое значениеrows_before_limit_at_least, аGROUP BY ... WITH TOTALSвычислял строку итогов лишь по начальной части потока. #114025 (groeneai). - Исправлена ошибка
LOGICAL_ERROR(«Unexpected number of kept output positions after removing unused columns fromReadFromMergeTree»), возникавшая в запросеSELECT ... FINAL, в которомPREWHEREиспользует столбец, необходимыйFINALдля слияния (ver,is_deleted,sign), но сам этот столбец не выбирается. #114746 (groeneai). - Исправлена проблема времени жизни объектов при сбросе буфера асинхронных INSERT, обработке материализованных представлений и выполнении
EXPLAIN ANALYZE, из-за которой могло происходить обращение к уже освобождённому состоянию отслеживания запроса. #114940 (azat). - Исправлено поведение
CREATE QUOTAиALTER QUOTA, которые без каких-либо сообщений отбрасывали все блокиFOR INTERVAL, кроме последнего, если между интервалами не была указана разделяющая запятая. Такой оператор выполнялся успешно, но не устанавливал ни одного из предшествующих ограничений. Теперь интервалы снова накапливаются, как это было до 2020 года. #115320 (groeneai). - Исправлена ошибка, из-за которой
randConstantвозвращала два разных значения в одном запросе, если её вызовы имели разные псевдонимы. Согласно документации,randConstantвозвращает одно и то же значение в пределах всего запроса, иSELECT randConstant() = randConstant()уже возвращал1, однако при добавлении псевдонимов, как вSELECT randConstant() AS a, randConstant() AS b, получались два никак не связанных значения. #115384 (alexey-milovidov). - Исправлена ошибка, из-за которой
SELECT count()для повреждённого файлаMsgPackилиProtobufListлибо никогда не завершался, либо возвращал выдуманное количество строк. Быстрый путьoptimize_count_from_filesподсчитывал строки, не проверяя, что позиция чтения сдвигается, поэтому двухбайтовый файлProtobufListдавал миллиарды строк, и запрос так и не завершался. Теперь такие входные данные отклоняются с той же ошибкой, что и при обычном пути чтения. #115884 (groeneai). - Исправлена ошибка, из-за которой
broken_data_filesвsystem.distribution_queueи метрикаBrokenDistributedFilesToInsertвсегда показывали0: при сканировании очереди асинхронных вставок во время запуска сервераDistributedAsyncInsertDirectoryQueue::initializeFilesFromDiskучитывала повреждённые байты, но не увеличивала счётчик повреждённых файлов. #92124 (squalfof).
Прочие исправления ошибок
- Вторичные запросы, выполняемые в рамках внутренних запросов, теперь записываются в журнал как внутренние запросы. #108506 (mstetsyuk).
- Исправлена ошибка, из-за которой отсутствующий в части DEFAULT-столбец заполнялся значением по умолчанию для типа вместо DEFAULT-выражения, если условие PREWHERE разбивалось на несколько шагов чтения. #111795 (yariks5s).
- Квоты с ключом
normalized_query_hashтеперь учитывают все ресурсы (read_rows,read_bytes,result_rows,result_bytes,execution_time,written_bytes,errors) отдельно для каждого шаблона запроса — так же, как счётчики количества запросов, — а не в едином общем бакете на пользователя. #107681 (alexey-milovidov). - Исправлена ошибка, из-за которой не действовали
connect_timeout, а также тайм-ауты чтения и записи MySQL: попытка соединения с не отвечающим сервером MySQL могла зависать более чем на две минуты даже приconnect_timeout = 1, поскольку периодические сигналы выборочного профилировщика запросов постоянно сбрасывали внутренний дедлайн опроса в клиенте MySQL. #109592 (tiandiwonder). - Исправлена ошибка, из-за которой тайм-аут ожидания блока при потоковых вставках (
input_format_max_block_wait_ms) мог никогда не истекать при активном профилировщике запросов: опрос файлового дескриптора перезапускался с полным тайм-аутом после каждого сигнала профилировщика, поэтому зависший источник входных данных мог бесконечно откладывать сброс частичного блока, вместо того чтобы сбросить его по достижении лимита ожидания. #109602 (tiandiwonder). - Исправлена ошибка
LOGICAL_ERROR(std::length_error), возникавшая, когда в запросе с экспериментальной настройкойmake_distributed_plan = 1использовалось очень большое значениеdistributed_plan_default_reader_bucket_countилиdistributed_plan_default_shuffle_join_bucket_count. Теперь такие значения отклоняются с ошибкой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). - Исправлено аварийное завершение сервера (в отладочных сборках и сборках с санитайзерами) при чтении значения из PostgreSQL-источника семейства
mysql/postgresql/sqliteв объявленный тип, к которому это значение невозможно привести при разборе (например, столбецtext, объявленный какInt32). Теперь о таком несоответствии типов сообщается как об ошибке запроса, и сервер не завершается аварийно. #110264 (groeneai). - Исправлено аварийное завершение сервера при разборе некоторых запросов PRQL (
SET dialect = 'prql'). Паника внутри компилятораprqlcприводила к аварийному завершению процесса, вместо того чтобы возвращаться как ошибка запроса. #110316 (groeneai). - Исправлена ошибка
NOT_FOUND_COLUMN_IN_BLOCK, возникавшая, когда политика строк иadditional_table_filtersссылаются на один и тот же столбец, который больше нигде в запросе не выбирается. #111099 (groeneai). - Исправлено зависание
randChiSquared,randStudentT,randFisherFиrandBinomialпри экстремальных значениях параметров. Такой запрос невозможно было прервать ни с помощьюmax_execution_time, ни с помощьюKILL QUERY. Теперь подобные параметры отклоняются, даже еслиmax_rand_distribution_parameterилиmax_rand_distribution_trialsустановлены в 0, а значениеmax_rand_distribution_trialsдляrandBinomialбольше нельзя поднять выше значения по умолчанию 10^9. #111909 (alexey-milovidov). - Исправлена работа
connection_pool_max_wait_ms: указанное в документации значение по умолчанию0теперь действительно означает бесконечный тайм-аут. Ранее запрос, обнаружив, что пул соединений заполнен, повторял попытки в плотном цикле, нагружая CPU и записывая в логNo free connections in pool. Waiting 0 ms.на каждой итерации. Теперь он ждёт, пока соединение не вернётся в пул. #112380 (groeneai). - Исправлена проблема, из-за которой
replaceOne,replaceAll,replaceRegexpOneиreplaceRegexpAllигнорировалиmax_execution_timeиKILL QUERY. Теперь даже отдельный вызов проверяет отмену в процессе работы, поэтому длительная замена в большом значении или в большом количестве строк прерывается, а не занимает поток сервера до своего завершения. Частичного результата у такого вызова нет, поэтому приtimeout_overflow_mode = 'break'превышение лимита времени выдаётся как ошибка: всегда при свёртке констант, а в конвейере — всякий раз, когда эта контрольная точка достигается раньше межблочной проверки исполнителя, которая по-прежнему останавливает запрос без ошибки. #112483 (groeneai). - Исправлена проблема, из-за которой
countSubstrings,countSubstringsCaseInsensitiveиcountSubstringsCaseInsensitiveUTF8игнорировалиKILL QUERYиmax_execution_time: вызов на большом числе строк или совпадений мог выполняться ещё несколько минут после отмены запроса. #113369 (groeneai). - Исправлено возможное зависание запроса (на
receive_timeoutсекунд), если он очень быстро завершается на узле-initiator. #113551 (nickitat). - Исправлена проблема, из-за которой
countMatchesиcountMatchesCaseInsensitiveигнорировалиmax_execution_timeиKILL QUERYпри подсчёте совпадений в одном большом значении, и отменённый запрос продолжал выполняться ещё несколько минут. При константном аргументе вызов происходит на этапе анализа запроса, когда конвейера, который мог бы его отменить, ещё нет. #113886 (groeneai). - Запрос мог быть отменён раньше истечения
max_execution_time(вплоть до 1 мс) с противоречивой ошибкойTimeout exceeded: elapsed 999.672 ms, maximum: 1000 ms. #114559 (alexey-milovidov). - Исправлено чтение за пределами буфера в
pointInPolygonпри константном полигоне с неограниченным ограничивающим прямоугольником, например когда координата достигает+-DBL_MAX. Теперь такой полигон отклоняется с ошибкойBAD_ARGUMENTS, а полигон с пустым кольцом считается не имеющим внутренней области. Ранее запрос мог вернуть неверный результат или аварийно завершить сервер в сборках с усиленной защитой (hardening) или санитайзерами. #115035 (groeneai). - Исправлено состояние гонки, из-за которого запрос
STREAM BOUNDEDмог вернуть меньше строк, чем было закоммичено до его запуска (как правило, ни одной). #115543 (alexey-milovidov). - Исправлена ошибка
Unknown identifier, возникавшая при оптимизации плана запроса сmake_distributed_plan = 1, когда столбец сортировки оконного запроса проходит через шагExpression, в котором он не упоминается. #115890 (groeneai). - Исправлена ошибка, из-за которой
h3kRing,h3HexRing,h3Lineиh3ToChildrenигнорировалиmax_execution_timeиKILL QUERYпри развёртывании блока строк. #115893 (alexey-milovidov). - Исправлена ошибка
NOT_FOUND_COLUMN_IN_BLOCKв нативном считывателе Parquet V3 (появившаяся в результате предыдущей регрессии), возникавшая, когда в условииPREWHEREбыли конъюнкты с общим промежуточным выражением. #107059 (groeneai). - Исправлено зависание при записи Parquet с включённым параметром
output_format_parquet_parallel_encoding(включён по умолчанию) и значениемmax_threadsбольше 1. Если кодировщику не удавалось запланировать дополнительный поток, счётчик активных потоков выходил за нижнюю границу диапазона, и запись могла навсегда остановиться, вместо того чтобы завершиться или сообщить об ошибке. #112959 (groeneai). - Исправлено неограниченное выделение памяти при чтении файла Parquet, в метаданных Thrift которого объявлена длина контейнера или строки, превышающая размер самих метаданных. Теперь такая длина отклоняется, и память под неё не выделяется. #113212 (groeneai).
- Исправлено исключение
std::out_of_range(Logical error: 'std::exception. Code: 1001, type: std::out_of_range', которое в отладочных сборках и сборках с санитайзерами также приводит к аварийному завершению сервера) в считывателе Parquet v3, возникавшее, когда столбец, нужный только для вычисления фильтра, ставился в очередь на декодирование уже после удаления его выходного слота. #113956 (groeneai). - Исправлены гонки данных в profile events и трекере памяти. #112466 (mstetsyuk).
- Исправлена теоретически возможная гонка данных в profile events при использовании настройки
trace_profile_events_listдля записи трассировок стека определённых profile events вsystem.trace_log. #113553 (mstetsyuk). - Исправлена ошибка, из-за которой
intDivOrNull,moduloOrNullиpositiveModuloOrNullвозвращали0вместоNULL, аintDivOrNullиintDivOrZeroвыбрасывали исключение вместо того, чтобы вернутьNULL/0, когда деление приводило к исключению с плавающей запятой (деление на ноль илиINT_MIN / -1), в том числе для смешанных знаковых и беззнаковых аргументов. #101976 (yariks5s). - Исправлена работа
IS DISTINCT FROMдля значенийArrayиMapпри сравнении сNULL. #103162 (ylw510). - Исправлена работа
groupConcatпри смешивании параметрической и двухаргументной форм записи, напримерgroupConcat(',', 2)(x, '/'): параметр ограничения числа строк молча отбрасывался, и вместо запрошенного количества возвращались все строки; теперь разделитель из второго аргумента корректно переопределяет параметр. #104882 (yariks5s). - Исправлены ошибки при использовании CAST для преобразования из меньших единиц интервала в большие. #105058 (yariks5s).
- Исправлена логическая ошибка (
Assertion 'row < chunk.getNumRows()' failed) в запросахLIMIT ... WITH TIES, выполняемых с конвейером чтения в порядке сортировки (optimize_read_in_order = 1иread_in_order_use_virtual_row_per_block = 1). #105102 (groeneai). - Исправлена ошибка
Logical error: 'Pipeline stuck'в запросах, использующихenable_sharding_aggregator = 1вместе сUNION ALLи значениемmax_streams_for_union_step, меньшим ширины конвейера.BufferedShardByHashTransformтеперь закрывает выходные порты с пустыми очередями сразу после того, как входные данные исчерпаны, и продолжает считывать входные данные, если запрошенному пустому порту нечего выдать, даже когда соседняя очередь достигла предела обратного давления (back-pressure). #106251 (groeneai). - Исправлено поведение
removeDirectoryна дисках объектного хранилища типаplain(например,s3_plain): при удалении непустого каталога удалялись все файлы внутри него, как если бы удаление было рекурсивным. Теперь попытка удалить непустой каталог завершается ошибкойCANNOT_RMDIR, а при рекурсивном удалении содержимое обрабатывается явно. #106281 (RinChanNOWWW). - Исправлена проблема, из-за которой пользовательские функции типа
executable_pool, настроенные с<lifetime>, не подхватывали изменения в исходном скрипте. Ранее изменённый скрипт перечитывался только командойSYSTEM RELOAD FUNCTIONS, а при периодических перезагрузках по<lifetime>продолжала выполняться старая версия. #107087 (groeneai). - Исправлена гонка данных в глобальном сборщике трассировок сервера между запуском профилировщика в рабочем потоке и остановкой сервера. #107307 (groeneai).
- Исправлено редкое аварийное завершение сервера при остановке (
std::future_error, “The associated promise has been destructed prior to the associated state becoming ready”), возникавшее из-за того, что задача, запланированная черезthreadPoolCallbackRunnerUnsafe, удалялась из очереди пула потоков до своего выполнения. #107383 (groeneai). - Исправлена логическая ошибка
FileLog(Last stored last_written_position in meta file ... is bigger than current last_written_pos), которая могла возникать, если отслеживаемый файл удалялся и создавался заново с тем же inode. #107617 (groeneai). - Исправлена проблема, из-за которой
toTime64иCAST(... AS Time64)в режимах обработки переполненияsaturateиignoreне приводили значения, выходящие за пределы диапазонаTime64, к его границам. Из-за этого могли получаться значения, которые отображаются одинаково, но при сравнении считаются разными. #108028 (alexey-milovidov). - Исправлена некорректная обработка утверждений нулевой ширины (
\b,^,$) в функциях regexp, ищущих все совпадения:extractAll,extractAllGroupsVertical,extractAllGroupsHorizontal,countMatchesиsplitByRegexp. Например,extractAll('new york is the greatest', '\b(\w)')теперь корректно возвращает первую букву каждого слова, а не все буквы подряд. #108047 (alexey-milovidov). - Исправлены некорректные результаты
hasTokenпри использовании текстовых индексов с токенизатором, отличным отsplitByNonAlpha. #108066 (rschu1ze). - Исправлена проблема, из-за которой
toStartOfIntervalиdateTruncвозвращали округлённое значение вместо начала интервала, в который попадает входное значение, если точность входного значения была выше единицы интервала. Например,toStartOfInterval(toDateTime64('2023-10-09 10:11:12.000999', 6), INTERVAL 1 millisecond)возвращал10:11:12.001вместо10:11:12.000. Ошибка затрагивала и перегрузку с явно заданной точкой отсчёта. #108186 (yariks5s). - Исправлены функции
replaceRegexpOneиreplaceRegexpAll: теперь.по умолчанию соответствует символам перевода строки, как и в других функциях для работы с регулярными выражениями. #108265 (linjiayu1025-collab). - Исправлено двойное вычисление условий в легковесных UPDATE/DELETE. #108323 (ofeliacode).
- Исправлена работа
arrayPartialSort()с неконстантным аргументом limit. #108327 (vitlibar). - Исправлены функции для работы с регулярными выражениями (
match,extract,extractAll,replaceRegexpOne,replaceRegexpAllи др.), которые молча возвращали неверные результаты, если шаблон регулярного выражения содержал байт NUL (\0). Теперь NUL обрабатывается как обычный литеральный байт, что соответствует поведению RE2. #108427 (alexey-milovidov). - Исправлена ошибка, из-за которой
changeYear/changeMonth/changeDay/changeHour/changeMinute/changeSecondс аргументомDateTime64(N)создавали результирующий столбец с жёстко заданным масштабом по умолчанию (3) вместоN. Значения вычислялись с масштабомN, однако в объекте столбца был объявлен масштаб 3, из-за чего столбец оказывался структурно несогласованным со своим типом. #108551 (groeneai). - Исправлена ошибка
LOGICAL_ERROR(«Trying to extract chunk from ChunkBuffer before all inputs are finished»), возникавшая, когда операция над множествами (INTERSECT/UNION ALL/EXCEPT) объединяла ветви с коррелированными подзапросами приcorrelated_subqueries_default_join_kind = 'left'. #108554 (groeneai). - Исправлены ошибки при работе с
DateTime64вchangeYear,changeMonth,changeDay,changeHour,changeMinuteиchangeSecond: входные значения с наносекундной точностью (масштаб 9) больше не вызываютDECIMAL_OVERFLOW, а для значений с долями секунды до начала эпохи теперь возвращается правильная календарная секунда. #108681 (takumihara). - Устранены избыточный вывод в лог сервера и чрезмерно большое сообщение об ошибке при компиляции очень большого регулярного выражения (например, шаблона
LIKEилиmatchс сотнями тысяч подстановочных символов); теперь такие шаблоны завершаются понятной ошибкойCANNOT_COMPILE_REGEXP. #108821 (Algunenano). - Исправлена ошибка, из-за которой
reinterpret(x, 'Decimal128(scale)')(а также с целевыми типамиDecimal32/Decimal64/Decimal256/DateTime64) создавал результирующий столбец, внутренний масштаб которого совпадал с исходным, а не с запрошенным целевым масштабом, если исходный и целевой типы имели одинаковое физическое представление. Значения были корректными, однако объект столбца был структурно несогласован с объявленным типом. #108878 (groeneai). - Исправлено неопределённое поведение при преобразовании в строку типа пакета протокола, выходящего за допустимый диапазон (например, в сообщениях об ошибках «Unexpected packet from server» / «Received … packet»), при рассинхронизированном соединении или при фаззинге. #108885 (groeneai).
- Исправлена ошибка, из-за которой
changeYear/changeMonth/changeDay/changeHour/changeMinute/changeSecondдляDateTime64(N)формировали результирующий столбец с жёстко заданным масштабом по умолчанию 3 вместоN, аtimeSlotsдляDateTime64не учитывала масштаб необязательного аргументаSizeв объявленном типе возвращаемого значения. В обоих случаях физический масштаб получаемого столбца расходился с объявленным типом, что приводило кLOGICAL_ERROR(writeSlice expects same column types) при передаче результата вarrayPushBack/arrayPushFront/arrayConcat, аtimeSlotsс наибольшим масштабом вSizeвозвращала неверные временные метки. #108994 (groeneai). - Исправлены немонотонные приращения ProfileEvents #109180 (azat).
- Исправлена ошибка, из-за которой коэффициенты
SAMPLEс показателем степени, модуль которого выходит за пределыInt32(например,SAMPLE 1e-3000000000), без каких-либо предупреждений обрабатывались какSAMPLE 1. #109197 (Algunenano). - Исправлены две ошибки при обработке
DateTime64вtoUTCTimestamp/fromUTCTimestamp(и их псевдонимахto_utc_timestamp/from_utc_timestamp) иtoTime64. Во-первых, переполнение знакового целого вблизи границыInt64(теперь вычисление выполняется вInt128, а результат ограничивается допустимым диапазоном). Во-вторых, неверный результат для отрицательных дробных значений вблизи границы смены смещения часового пояса: при выделении секунд выполнялось усечение к нулю, поэтомуtimezoneOffset()проверяла следующую секунду и могла оказаться не по ту сторону перехода на летнее время (DST) или смены смещения. #109738 (groeneai). - Исправлена логическая ошибка (
column->size() == num_rows), возникавшая, если выражение фильтра row policy используетarrayJoin; такие фильтры теперь отклоняются. #109753 (Algunenano). - Исправлена ошибка, из-за которой
generateRandomStructure()иногда формировала некорректную строку структуры с двумя слитными типами данных (например,Decimal32(7)IPv4), если вложенность типов превышала внутренний предел глубины; такой результат невозможно было разобрать. #109928 (groeneai). - Исправлена передача настроек запроса в
accurateCastOrDefaultи сохранение исходных значенийNULL, закодированных вDynamicиVariant. #109946 (Avogar). #114912 (alexey-milovidov). - Исправлены
max_bytes_in_distinctиmax_bytes_in_set: строковые ключи хранятся в арене, которая не учитывалась при проверке ограничений, поэтому DISTINCT / IN по строковым ключам могли занимать память сверх лимита в байтах на весь объём данных ключей (без ограничения сверху, в зависимости от длины ключа). Теперь ограничения учитывают арену, как и указано в документации; запросы со строковыми ключами, приближающиеся к лимиту в байтах, теперь могут превышать его раньше (что корректно). #110120 (skuznetsov-clickhouse). - Исправлено чтение файлов Npy с внутренними размерностями нулевого размера: теперь материализованные строки и результаты оптимизированного и неоптимизированного
count()совпадают. #110146 (qiuyanjun888). - Исправлена логическая ошибка (аварийное завершение сервера в отладочных сборках и сборках с санитайзерами), возникавшая, если функциям
indexHint/ignore/isZeroOrNullпередавался аргумент, тип которого разрешается вNothing, например в выражениях видаindexHint(assumeNotNull(materialize(NULL))). #110192 (groeneai). - Исправлено чтение файлов на дисках
plain_rewritableпосле перезаписи существующего пути содержимым другого размера: в метаданных в памяти оставался устаревший размер файла, из-за чего чтение могло завершаться ошибкойUNEXPECTED_END_OF_FILE. #110304 (thevar1able). - Значения
vector_search_index_fetch_multiplierменьше 1.0 теперь отклоняются: это предотвращает пустые результаты ANN-поиска в случаях, когда вычисленное количество извлекаемых записей при усечении обращается в ноль. #110452 (tamish560). - Исправлена эпизодически возникающая ошибка
Cannot parse string ... as UInt64 ... While executing ValuesBlockInputFormat, которая могла появляться при вставке значений, чьи выражения содержат числовое приведение типа, напримерinitializeAggregation('sumState', 0::UInt64). #110637 (groeneai). - Функция
readWKTбольше не отклоняет WKT-строки с начальными пробельными символами (например,readWKT(' POINT(1 2)')), которые принимаются типизированными считывателямиreadWKTPoint/readWKTPolygon/… и допускаются грамматикой WKT. #110706 (groeneai). - Исправлено аварийное завершение сервера (целочисленное деление на ноль) при расходовании квоты с интервалом нулевой длины (например, CREATE QUOTA q FOR INTERVAL 0 SECOND MAX queries = 1000). Теперь неположительная длительность интервала квоты отклоняется уже при создании квоты. #110846 (PedroTadim).
- Исправлено аварийное завершение в FIPS-сборках при использовании SSH-ключа Ed25519 (
CREATE USER ... IDENTIFIED WITH ssh_key ... TYPE 'ssh-ed25519'или такого ключа вusers.xml). Ed25519 не входит в число алгоритмов, одобренных FIPS, поэтому такие ключи теперь отклоняются с понятной ошибкойLIBSSH_ERROR. #110891 (thevar1able). - Транспонированные функции расстояния над
QBit(cosineDistanceTransposed,L2DistanceTransposed,dotProductTransposed) теперь используют ограниченное восстановление с низкой точностью для значения, усечённого доprecisionбитовых плоскостей, вместо восстановления до нижней границы грубой ячейки (с заполнением отброшенных битов нулями). Заполнение нулями смещало каждое восстановленное значение к нулю и при низкой точности приводило к вырожденному результату: дляQBit(BFloat16)при точности 1 сохраняется только знаковый бит, поэтому любое значение восстанавливалось в±0.0, а расстояние для всех строк было одной и той же константой и не несло никакой информации для ранжирования. Теперь способ восстановления зависит от того, какие биты отбрасываются: необработанные кодыInt8восстанавливаются к центру своей ячейки (что соответствует восстановлению по методуLloyd-Max, уже применявшемуся в пути...TransposedQuantized); значение с плавающей запятой при точности 1 превращается в полноценное знаковое квантование; значение с плавающей запятой, у которого сохраняется весь порядок, а отбрасываются только биты мантиссы, восстанавливается к ограниченной средней точке своей бинады (при этом настоящий ноль или±0.0остаётся точным нулём, а ячейка неконечных значений выделяется отдельно, чтобы±infоставалась точной бесконечностью; о неоднозначной ячейкеNaNсм. примечание ниже); пока же усекаются биты порядка, сохраняется ограниченная нижняя граница, так что меньшее значениеprecisionпозволяет пожертвовать точностью ради скорости, не завышая величину на порядки. Результаты с полной точностью не изменились. #110911 (alexey-milovidov). - Исправлено чтение за пределами допустимого диапазона в нативном считывателе ORC при выводе схемы повреждённого ORC-файла, в дереве типов которого объявлено больше столбцов, чем имеется кодировок столбцов в футере страйпа. Теперь такой файл отклоняется с ошибкой
CANNOT_EXTRACT_TABLE_STRUCTURE, а не приводит к аварийному завершению сервера в отладочных сборках и сборках с санитайзерами. #110967 (groeneai). - Каждый SSH-ключ теперь учитывается отдельно в лимите
max_authentication_methods_per_user, поэтому лимит применяется единообразно независимо от синтаксиса. Ранее несколько ключей в одном методеssh_keyсчитались за один. #111181 (TheMC47). - REST-каталоги Iceberg теперь сообщают об устаревших учётных данных с указанием исходной ошибки, а не молча возвращают
UNKNOWN_TABLE. #111379 (alesapin). - Исправлена ошибка, из-за которой
readWKTPoint/readWKTвозвращали неинициализированные (в скалярном режиме) или взятые из предыдущей строки (в векторизованном режиме) координаты для пустой точки с тегом размерности, напримерPOINT M EMPTY. Теперь такие входные данные отклоняются с ошибкойCANNOT_PARSE_TEXT— так же, как иPOINT EMPTY. #111517 (groeneai). - При создании статистики
minmaxтеперь выводится предупреждение, а не генерируется исключение. #111785 (hanfei1991). - Функция
randBinomialтеперь корректно работает с вырожденными вероятностями0и1при любом числе испытаний. #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 с ошибкойBAD_ARGUMENTS, как это уже делалаSYSTEM ENABLE FAILPOINT. Ранее при опечатке в имени команда сообщала об успехе, оставляя нужный fail point включённым и никак не указывая, что ничего не было отключено. #112680 (groeneai).- Исправлено чтение с неверным типом подстолбца элемента
Nested, столбец которого был удалён и добавлен заново. При выборке такого подстолбца вместе с его родительским столбцом на месте подстолбца возвращался весь элемент, хотя в блоке по-прежнему был объявлен тип элемента; это приводило к произвольным значениям в релизных сборках и к логической ошибке в отладочных сборках и сборках с санитайзерами. #112769 (groeneai). - Теперь отклоняются длительности PromQL, в которых единицы измерения повторяются или не упорядочены от наибольшей к наименьшей. #112954 (fallintoplace).
- Исправлено неопределённое поведение (передача нулевого указателя в
memcpy) вreplaceRegexpOne/replaceRegexpAll, когда строка замены подставляет захватывающую группу, не участвовавшую в совпадении, напримерreplaceRegexpAll('abc', '(a)|(b)', '\\2'). #113012 (alexey-milovidov). - Исправлена несовместимость, из-за которой текстовые индексы, созданные в ClickHouse 26.3 с токенизатором
unicode_word, не загружались в более поздних версиях #113061 (rschu1ze). - Теперь отклоняются недопустимые суррогатные кодовые точки Unicode в escape-последовательностях строк PromQL. #113203 (fallintoplace).
- Теперь отклоняется недопустимое экранирование разделителей другого типа в строках PromQL. #113587 (fallintoplace).
- Исправлена ошибка, из-за которой
theilsUв рамке окна возвращала произвольное значение вместо 0, если первый аргумент постоянен в пределах рамки окна. #113691 (alexey-milovidov). - Исправлен код ошибки, возвращаемый для некоторых некорректных столбцов, сериализованных как
Replicatedи полученных по собственному протоколу: теперь они отклоняются сINCORRECT_DATAвместоLOGICAL_ERROR(что приводило к аварийному завершению сервера в отладочных сборках и сборках с санитайзерами). #114186 (Avogar). - Исправлены некорректные (часто с инвертированным знаком) литералы
Time64и константы в спискахIN, возникавшие при переполненииInt64во время масштабированияDecimal64с меньшим масштабом. Теперь при таком преобразовании выдаётся ошибкаDECIMAL_OVERFLOW— так же, как в веткеDateTime64и при явномCAST. #114546 (groeneai). - Добавлена поддержка имён метрик и меток в кавычках в селекторах PromQL. #114551 (fallintoplace).
- Исправлена ошибка, из-за которой таблицы
ReplicatedMergeTreeнеограниченно долго оставались в режиме только для чтения после неудачной попытки запуска, выполнявшейся через поток присоединения. Теперь повторный перезапуск планируется корректно, благодаря чему снова работают автоматическое восстановление и связанные с ним проверки сессии. #114802 (azat). timeSeriesRangeиtimeSeriesFromGridвыдавали ложную ошибкуDECIMAL_OVERFLOWдля временных меток до 1970 года, поскольку начальная и конечная временные метки считывались как беззнаковые значения. Кроме того, для временных метокDateTime/UInt32шаг молча усекался до младших 32 бит. Теперь все вычисления выполняются вInt64. #114815 (vitlibar).- Исправлено возможное исключение в асинхронных вставках после сбоя запроса с
MEMORY_LIMIT_EXCEEDED, а также исправлена работа настройкиasync_insert_queue_flush_on_shutdown: теперь вставки из очереди сбрасываются на диск при остановке сервера. #114839 (azat). - Исправлено исключение
out_of_range, выбрасываемое как внутренняя ошибкаCode: 1001, когда шаблонsequenceMatch,sequenceCountилиsequenceMatchEventsсодержит номер события0, напримерsequenceMatch('(?0)'). Теперь такой шаблон отклоняется сBAD_ARGUMENTS. Временное условие, содержащее только знак, напримерsequenceMatch('(?1)(?t>+)(?2)'), молча интерпретировалось как(?t>0), а теперь отклоняется сSYNTAX_ERROR. #115056 (groeneai). - Исправлено сообщение об ошибке
geoToH3, в котором указывались неверная позиция аргумента и неверный тип, если координата не имеет типFloat64. При значении по умолчаниюgeotoh3_argument_order = 'lat_lon'сообщение указывало на другой аргумент и выводило его тип. #115503 (groeneai). - Исправлены некорректные escape-последовательности с обратной косой чертой в индексах text, tokenbf_v1 и ngrambf_v1. #115634 (ahmadov).
- Исправлена проблема: сервер не запускался, если переменная окружения
TZбыла пустой. #68921 (ardenwick).