Перейти к содержимому
Последнее обновление

Обновление и удаление данных

Кратко Apache Doris поддерживает SQL-операторы UPDATE и DELETE, как транзакционная база данных, а также upsert с частичным обновлением столбцов через потоковую загрузку, массовое удаление по предикату и атомарную замену партиций. В таблицах Unique Key движок Merge-on-Write обеспечивает низкую задержку запросов: удалённые строки помечаются в битовой карте каждого rowset во время записи, поэтому объединять версии при чтении не требуется. Начиная с версии 2.1, Merge-on-Write используется по умолчанию для Unique Key.

Обновление и удаление данных в Apache Doris: SQL UPDATE, DELETE по предикату, upsert с частичным обновлением столбцов и атомарная замена партиций на основе Merge-on-Write в таблицах Unique Key.

Зачем нужны обновление и удаление данных в Apache Doris?​

Обновление и удаление данных в Apache Doris позволяют выполнять транзакционные изменения на уровне строк в аналитическом движке, поэтому для CDC, удаления данных по требованиям GDPR и разовых исправлений не приходится переписывать партиции. Большинство аналитических движков создавались исходя из того, что в хранилища данные только добавляются. Затем появились CDC и GDPR, а ещё никуда не делся простой факт: в рабочих данных бывают ошибки. Если ваше хранилище не может исправить одну некорректную строку без перезаписи партиции, каждое запоздавшее исправление превращается в заявку команде эксплуатации.

  • Задание Flink CDC отслеживает изменения в MySQL, и каждое обновление строки должно попадать в хранилище за считаные секунды.
  • Пользователь запрашивает удаление данных по GDPR. Данные нужно удалить из хранилища, а не отложить их удаление «до следующей компактации».
  • Один отчёт показывает неверное число из-за опечатки в единственной строке таблицы фактов на 10 миллиардов строк.

Apache Doris решает все три задачи с помощью полноценных SQL-операторов: UPDATE, DELETE FROM ... WHERE, upsert с частичным обновлением столбцов через Stream Load, а также TRUNCATE или атомарной замены партиций для массовой очистки. Ни один из этих способов не требует, чтобы таблица была маленькой, и ни один не заставляет вас затем планировать задание на перезапись данных.

Что представляют собой обновление и удаление данных в Apache Doris?​

Обновление и удаление данных в Apache Doris включают четыре механизма: SQL-оператор UPDATE, DELETE по предикату, upsert с частичным обновлением столбцов и замену партиций. В таблицах Unique Key их работу обеспечивает движок Merge-on-Write. SQL-оператор UPDATE на уровне строк работает в таблицах Unique Key, удаление по предикату через DELETE FROM ... WHERE работает в любых таблицах, upsert с частичным обновлением столбцов выполняется при загрузке данных (с заголовком Stream Load partial_columns: true или соответствующей переменной сеанса), а операции на уровне партиций включают TRUNCATE PARTITION и атомарную замену с использованием временных партиций. В основе модели Unique Key лежит Merge-on-Write (MoW), благодаря которому удаления и обновления вступают в силу при записи, а не при выполнении запросов. MoW появился в версии 1.2 и стал режимом по умолчанию для Unique Key в версии 2.1.

Основные термины

  • Unique Key model: модель таблицы, в которой для каждого первичного ключа хранится одна строка. Необходима для UPDATE и пакетных операций upsert.
  • Merge-on-Write (MoW): при записи Apache Doris ищет каждый новый ключ в существующих данных, помечает старую строку в битовой карте удаления и записывает новую строку в новый rowset.
  • Delete bitmap: битовая карта для каждого rowset с идентификаторами строк, которые запросы должны пропускать. Она заменяет объединение версий по каждому ключу при чтении.
  • Partial column update: запись, затрагивающая только часть столбцов. Apache Doris считывает недостающие значения из существующих строк и записывает обратно полную строку.
  • Sequence column (function_column.sequence_col): выбранный пользователем столбец, который указывает MoW, какая версия ключа имеет приоритет, если записи поступают не по порядку.
  • __DORIS_DELETE_SIGN__: скрытый столбец, которому присваивается значение 1 для логического удаления строки через любой способ загрузки.

Как работают обновление и удаление данных в Apache Doris?​

Обновление и удаление данных в Apache Doris выполняются в таблице Unique Key MoW в пять этапов: планирование и чтение, поиск ключей, установка битов удаления для старых строк, запись новых строк в новый rowset и публикация новой версии.

Рассмотрим выполнение UPDATE для таблицы Unique Key MoW:

  1. Планирование и чтение. FE разбирает оператор, обрабатывает предикат WHERE и направляет чтение к репликам BE. При записи с частичным обновлением столбцов узлы BE дополнительно получают недостающие значения столбцов для каждого затронутого ключа.
  2. Поиск ключей. Каждый BE обращается к хранящемуся в памяти индексу первичного ключа для каждого rowset, чтобы определить, в каком rowset и под какими идентификаторами строк сейчас находятся затронутые ключи.
  3. Пометка старых строк. В каждом rowset, содержащем затронутый ключ, в битовой карте удаления устанавливаются биты, соответствующие идентификаторам этих строк. Старые строки остаются на диске, пока их не удалит компактация.
  4. Запись новых строк. Новые значения вместе с неизменёнными столбцами, которые Apache Doris пришлось прочитать для частичного обновления, записываются в новый rowset со следующим номером версии.
  5. Публикация. Транзакция фиксируется, новая версия становится видимой, и с этого момента запросы фильтруют строки с помощью объединённой битовой карты удаления. Место, занятое старыми данными, освобождается при компактации.

DELETE FROM ... WHERE выполняется по той же схеме, но без этапа записи. В таблицах Aggregate или Duplicate Apache Doris вместо этого сохраняет предикат в метаданных tablet, а запросы применяют его при чтении.

Быстрый старт​

CREATE TABLE orders (
order_id BIGINT,
status VARCHAR(20),
amount DECIMAL(10, 2),
updated DATETIME
)
UNIQUE KEY(order_id)
DISTRIBUTED BY HASH(order_id) BUCKETS 4
PROPERTIES ("function_column.sequence_col" = "updated");

INSERT INTO orders VALUES
(1, 'created', 99.50, '2026-05-08 10:00:00'),
(2, 'created', 149.00, '2026-05-08 10:01:00');

UPDATE orders SET status = 'shipped', updated = NOW() WHERE order_id = 1;
DELETE FROM orders WHERE order_id = 2;

Ожидаемый результат

+----------+---------+--------+---------------------+
| order_id | status | amount | updated |
+----------+---------+--------+---------------------+
| 1 | shipped | 99.50 | 2026-05-08 11:42:31 |
+----------+---------+--------+---------------------+

Заказ 1 перезаписан на месте; заказ 2 удалён. Свойство function_column.sequence_col защищает таблицу от записей, поступающих не по порядку: событие CDC с более ранней временной меткой updated уступит уже существующей строке, даже если поступит после более новой записи.

Когда стоит использовать обновление и удаление данных в Apache Doris?​

Обновление и удаление данных в Apache Doris подходят для upsert из CDC в таблицы Unique Key, обновления часто меняющихся столбцов в широких таблицах, удаления отдельных строк по требованиям GDPR, атомарной замены партиций при дозагрузке исторических данных и сборки широких таблиц из нескольких потоков. Эти механизмы не подходят для UPDATE в таблицах Aggregate или Duplicate, обновления отдельных строк в тесном цикле, изменения первичных ключей или массовых операций DELETE по предикату, с которыми можно справиться одной заменой партиции.

Подходящие сценарии

  • Конвейеры CDC на Flink и Spark, выполняющие upsert в таблицу Unique Key, где первичный ключ источника используется как ключ Apache Doris.
  • Обновление часто меняющихся столбцов в широких таблицах (статус заказа, время последнего появления, текущий баланс) через Stream Load с частичным обновлением столбцов.
  • Удаление отдельных строк по идентификатору пользователя в соответствии с GDPR, в том числе в таблицах Duplicate, куда данные только добавляются.
  • Дозагрузка исторических данных с атомарной подстановкой исправленной партиции через ALTER TABLE ... REPLACE PARTITION.
  • Сборка широких таблиц из нескольких потоков, когда каждый источник отвечает за группу столбцов и записывает только свои столбцы.

Неподходящие сценарии

  • UPDATE в таблицах Aggregate или Duplicate. Оператор будет отклонён. Повторно загрузите данные через механизм загрузки (в Aggregate для перезаписи значений используется REPLACE_IF_NOT_NULL) или смените модель таблицы.
  • Частые операции UPDATE для отдельных строк в тесном цикле. Каждый оператор выполняется в собственной транзакции, и накладные расходы на фиксацию становятся определяющими. Вместо этого выполняйте пакетные обновления через Stream Load с partial_columns: true или используйте Group Commit.
  • Изменение первичного ключа. Механизма перезаписи ключа нет; выполните логическое удаление старой строки через __DORIS_DELETE_SIGN__ и вставьте новую, желательно в рамках одной загрузки.
  • DELETE по предикату, которому соответствуют многие миллиарды строк. Каждое удаление сохраняет предикат или битовую карту, которые затем приходится обрабатывать при компактации; замена партиции или INSERT OVERWRITE выполняется быстрее.
  • DELETE в модели Aggregate по неключевым столбцам. Предикат должен фильтровать только по ключевым столбцам: движок не может проверять условия по столбцам значений до агрегации.

Дополнительные материалы​