Skip to main content
Легковесные обновления сейчас в бете. Если у вас возникнут проблемы, пожалуйста, создайте issue в репозитории ClickHouse.
Оператор легковесного UPDATE обновляет строки в таблице [db.]table, которые соответствуют выражению filter_expr. Он называется “легковесным обновлением” в отличие от запроса ALTER TABLE ... UPDATE, который представляет собой ресурсоёмкий процесс и переписывает целые столбцы в частях данных. Он доступен только для семейства движков таблиц MergeTree.
filter_expr должен иметь тип UInt8. Этот запрос обновляет значения указанных столбцов значениями соответствующих выражений в тех строках, где filter_expr принимает ненулевое значение. Значения приводятся к типу столбца с помощью оператора CAST. Обновление столбцов, используемых при вычислении основного ключа или ключа партиционирования, не поддерживается. Клауза IN PARTITION ограничивает обновление перечисленными партициями. Без неё в таблицах семейства ReplicatedMergeTree, когда включена настройка optimize_mutations_with_partition_pruning (по умолчанию), ClickHouse автоматически определяет условия ключа партиционирования в filter_expr и обновляет только затронутые партиции. В нереплицируемых таблицах MergeTree используйте явную клаузу IN PARTITION, чтобы ограничить обновление конкретными партициями.

Примеры

Легковесные обновления сразу видны в запросах

Легковесный UPDATE делает обновлённые значения сразу видимыми в SELECT-запросах за счёт применения патч-частей. Запросам не нужно ждать слияния, чтобы прочитать обновлённые значения. Патч-часть — это особый вид части данных, содержащий только обновлённые столбцы и строки. Их создание не приводит к немедленному физическому изменению исходных данных в хранилище. Процесс обновления похож на запрос INSERT ... SELECT ..., при этом запрос UPDATE возвращает управление только после завершения создания патч-части. Видимость в запросах и физическая материализация — это разные вещи:
  • Видимость в запросах: SELECT-запросы применяют патчи и читают обновлённые значения ещё до того, как эти патчи будут материализованы в исходных частях данных.
  • Физическая материализация: последующие слияния и мутации переносят обновлённые значения в части данных.
  • Очистка: патч-части удаляются автоматически, как только патчи будут материализованы во всех активных частях.
О согласованности параллельных обновлений см. Параллельные операции.

Требования к легковесным обновлениям

Легковесные обновления поддерживаются для движков MergeTree, ReplacingMergeTree, CollapsingMergeTree, VersionedCollapsingMergeTree, а также их версий Replicated и Shared. Чтобы использовать легковесные обновления, нужно включить материализацию столбцов _block_number и _block_offset с помощью настроек таблицы enable_block_number_column и enable_block_offset_column.

Легковесные удаления

Запрос легковесного DELETE можно выполнить как легковесный UPDATE, а не как мутацию ALTER UPDATE. Реализация легковесного DELETE управляется настройкой lightweight_delete_mode.

Особенности производительности

Преимущества легковесных обновлений:
  • Задержка обновления сопоставима с задержкой запроса INSERT ... SELECT ...
  • Записываются только обновлённые столбцы и значения, а не столбцы целиком в частях данных
  • Не нужно ждать завершения уже выполняющихся слияний/мутаций, поэтому задержка обновления предсказуема
  • Возможно параллельное выполнение легковесных обновлений
Возможное влияние на производительность:
  • Добавляют накладные расходы для запросов SELECT, в которых нужно применять патчи
  • Индексы пропуска данных не будут использоваться для столбцов в частях данных, к которым нужно применить патчи. Проекции не будут использоваться, если у таблицы есть патч-части, в том числе для частей данных, к которым патчи применять не нужно.
  • Небольшие, но слишком частые обновления могут привести к ошибке “слишком много частей”. Рекомендуется объединять несколько обновлений в один запрос, например поместив идентификаторы обновляемых строк в одно условие IN в WHERE
  • Легковесные обновления рассчитаны на обновление небольшого количества строк (примерно до 10% таблицы). Если нужно обновить больший объём данных, рекомендуется использовать мутацию ALTER TABLE ... UPDATE

Параллельные операции

Легковесные обновления, в отличие от тяжёлых мутаций, не ждут завершения текущих слияний/мутаций. Согласованность параллельных легковесных обновлений определяется настройками update_sequential_consistency и update_parallel_mode.

Разрешения для UPDATE

Для UPDATE требуется привилегия ALTER UPDATE. Чтобы разрешить команды UPDATE для конкретной таблицы указанному пользователю, выполните:

Детали реализации

Патч-части — это обычные части, но они содержат только обновлённые столбцы и несколько системных столбцов:
  • _part - имя исходной части
  • _part_offset - номер строки в исходной части
  • _block_number - номер блока строки в исходной части
  • _block_offset - смещение строки в блоке исходной части
  • _data_version - версия обновлённых данных (номер блока, выделенный для запроса UPDATE)
В среднем это даёт около 40 байт накладных расходов (несжатых данных) на каждую обновлённую строку в патч-частях. Системные столбцы помогают находить строки в исходной части, которые нужно обновить. Системные столбцы связаны с виртуальными столбцами в исходной части, которые добавляются при чтении, если требуется применить патч-части. Патч-части сортируются по _part и _part_offset. Патч-части принадлежат другим партициям, чем исходная часть. Идентификатор партиции патч-части имеет вид patch-<hash of column names in patch part>-<original_partition_id>. Поэтому патч-части с разными столбцами хранятся в разных партициях. Например, три обновления SET x = 1 WHERE <cond>, SET y = 1 WHERE <cond> и SET x = 1, y = 1 WHERE <cond> создадут три патч-части в трёх разных партициях. Патч-части могут сливаться между собой, чтобы уменьшить число применяемых патчей в запросах SELECT и снизить накладные расходы. Для слияния патч-частей используется алгоритм слияния replacing с _data_version в качестве version column. Поэтому патч-части всегда хранят последнюю версию для каждой обновлённой строки в части. Легковесные обновления не ждут завершения текущих слияний и мутаций и всегда используют текущий снимок частей данных, чтобы выполнить обновление и создать патч-часть. Из-за этого возможны два случая применения патч-частей. Например, если мы читаем часть A, нужно применить патч-часть X:
  • если X содержит саму часть A. Это происходит, если A не участвовала в слиянии на момент выполнения UPDATE.
  • если X содержит части B и C, которые покрываются частью A. Это происходит, если на момент выполнения UPDATE выполнялось слияние (B, C) -> A.
Для этих двух случаев есть два соответствующих способа применения патч-частей:
  • Использование слияния по отсортированным столбцам _part, _part_offset.
  • Использование JOIN по столбцам _block_number, _block_offset.
Режим JOIN медленнее и требует больше памяти, чем режим слияния, но используется реже.

Связанные материалы

  • ALTER UPDATE — тяжёлые операции UPDATE
  • Легковесный DELETE — операции легковесного DELETE
  • APPLY PATCHES — принудительная физическая материализация патчей в частях данных (операция мутации)
Последнее изменение 26 сентября 2026 г.