Легковесное UPDATE 语句
Легковесные обновления в настоящее время находятся в стадии бета-тестирования. Если вы столкнетесь с проблемами, пожалуйста, откройте 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
и их версий 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
требует привилегии ALTER UPDATE
. Чтобы разрешить операторы UPDATE
на конкретной таблице для данного пользователя, выполните:
Подробности реализации
Патч-части такие же, как и обычные части, но содержат только обновленные колонки и несколько системных колонок:
_part
- имя оригинальной части_part_offset
- номер строки в оригинальной части_block_number
- номер блока строки в оригинальной части_block_offset
- смещение блока строки в оригинальной части_data_version
- версия данных обновленных данных (номер блока, выделенный для запросаUPDATE
)
В среднем это добавляет около 40 байт (несжатые данные) накладных расходов на каждую обновленную строку в патч-частях.
Системные колонки помогают находить строки в оригинальной части, которые должны быть обновлены.
Системные колонки связаны с виртуальными колонками в оригинальной части, которые добавляются для чтения, если патч-части должны быть применены.
Патч-части сортируются по _part
и _part_offset
.
Патч-части принадлежат к разным партициям, чем оригинальная часть.
Идентификатор партиции патч-части - patch-<hash имен колонок в патч-части>-<original_partition_id>
.
Поэтому патч-части с разными колонками хранятся в разных партициях.
Например, три обновления SET x = 1 WHERE <cond>
, SET y = 1 WHERE <cond>
и SET x = 1, y = 1 WHERE <cond>
создадут три патч-части в трех разных партициях.
Патч-части могут сливаться между собой, чтобы уменьшить количество применяемых патчей в запросах SELECT
и снизить накладные расходы. Слияние патч-частей использует алгоритм слияния replacing с _data_version
в качестве версии колонки.
Таким образом, патч-части всегда хранят последнюю версию для каждой обновленной строки в части.
Легковесные обновления не ждут завершения текущих слияний и мутаций и всегда используют текущую снимок данных частей для выполнения обновления и создания патч-части. Из-за этого могут быть два случая применения патч-частей.
Например, если мы читаем часть A
, нам нужно применить патч-часть X
:
- если
X
содержит частьA
саму по себе. Это происходит, еслиA
не участвовала в слиянии, когда был выполненUPDATE
. - если
X
содержит частьB
иC
, которые охватываются частьюA
. Это происходит, если происходило слияние (B
,C
) ->A
, когда был выполненUPDATE
.
Для этих двух случаев есть два способа применения патч-частей соответственно:
- Используя слияние по сортированным колонкам
_part
,_part_offset
. - Используя соединение по колонкам
_block_number
,_block_offset
.
Режим соединения медленнее и требует больше памяти, чем режим слияния, но используется реже.
Связанное содержание
ALTER UPDATE
- Тяжелые операцииUPDATE
- Легковесный
DELETE
- Операции легковесногоDELETE