Легковесные обновления сейчас в бете.
Если у вас возникнут проблемы, пожалуйста, создайте issue в репозитории ClickHouse.
UPDATE обновляет строки в таблице [db.]table, которые соответствуют выражению filter_expr.
Он называется “легковесным обновлением” в отличие от запроса ALTER TABLE ... UPDATE, который представляет собой ресурсоёмкий процесс и переписывает целые столбцы в частях данных.
Он доступен только для семейства движков таблиц MergeTree.
filter_expr должен иметь тип UInt8. Этот запрос обновляет значения указанных столбцов значениями соответствующих выражений в тех строках, где filter_expr принимает ненулевое значение.
Значения приводятся к типу столбца с помощью оператора CAST. Обновление столбцов, используемых при вычислении основного ключа или ключа партиционирования, не поддерживается.
Примеры
Легковесные обновления не обновляют данные сразу
UPDATE реализован с помощью патч-частей — особого вида частей данных, которые содержат только обновлённые столбцы и строки.
Легковесный UPDATE создаёт патч-части, но не вносит немедленных физических изменений в исходные данные в хранилище.
Процесс обновления похож на запрос 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)
_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.
ALTER UPDATE— тяжёлые операцииUPDATE- Легковесный
DELETE— операции легковесногоDELETE APPLY PATCHES— принудительная физическая материализация патчей в частях данных (операция мутации)