Обзор данных об изменениях и инкрементального потребления
Начиная с версии 5.0, Doris может фиксировать изменения внутренних таблиц на уровне строк в changelog и предоставляет два способа чтения этих изменений:
- Table Stream: именованный объект потребления, который запоминает, до какой позиции прочитаны данные. Каждое чтение возвращает только изменения с момента последнего потребления, а чтение и запись в целевую таблицу выполняются в одной транзакции.
- Инкрементальный запрос (
@incr): создавать объект не требуется. Позволяет читать изменения таблицы за указанный временной интервал.
Асинхронные материализованные представления также могут использовать возможность более высокого уровня — Incremental View Maintenance (IVM). IVM позволяет Doris автоматически управлять внутренними объектами Table Stream и поддерживать материализованное представление на основе изменений на уровне строк. Если вам нужно поддерживать материализованное представление, используйте IVM напрямую вместо самостоятельного создания объектов Stream и потребления их данных.
Эта возможность доступна с версии 5.0.0. Она экспериментальная и по умолчанию отключена. О том, как её включить, см. раздел Предварительные требования.
Какие задачи решает
При инкрементальной обработке внутри Doris обычно возникают следующие проблемы:
| Проблема | Без записей об изменениях | С changelog |
|---|---|---|
| Последующим этапам обработки нужны приращения, но получить их невозможно | Исходная таблица ежедневно получает множество обновлений и удалений, поэтому отчёты, широкие и агрегированные таблицы на последующих этапах приходится полностью пересчитывать либо полагаться на столбец update_time, который поддерживает приложение | Table Stream возвращает только изменения между двумя потреблениями, поэтому на последующих этапах обрабатывается только приращение |
| Обновления и удаления не видны | Обновление в таблице Unique Key перезаписывает старое значение, а удалённая строка просто исчезает, поэтому впоследствии невозможно узнать, что было изменено или удалено | Фиксируется каждая вставка, обновление (со значениями до и после) и удаление каждой строки |
| Приращения нескольких таблиц не согласованы | При соединении инкрементальных данных с таблицей измерений таблица измерений находится в «текущем» состоянии, а приращение охватывает «период в прошлом» | <stream>@snapshot() читает образ таблицы измерений, соответствующий смещению потребления |
Changelog фиксирует каждую вставку, обновление (со значениями до и после обновления) и удаление каждой строки вместе с глобально монотонной временной меткой фиксации транзакции. Table Stream и инкрементальные запросы читают эти записи разными способами.
Два уровня

| Возможность | Требуемый объект | Кто отслеживает позицию | Для каких задач подходит |
|---|---|---|---|
| Table Stream | Требуется CREATE STREAM | Doris хранит смещение потребления для каждой партиции | Непрерывный инкрементальный ETL, синхронизация целевых систем, потребление с гарантией exactly-once |
Инкрементальный запрос @incr | Создавать ничего не нужно | Вы сами выбираете временной интервал | Разовый анализ, внешние планировщики, которые самостоятельно управляют позициями |
IVM работает поверх этих двух уровней. Он использует изменения, зафиксированные в changelog, и внутренние объекты Table Stream, которые Doris создаёт автоматически, но пользователь по-прежнему работает через CREATE MATERIALIZED VIEW и REFRESH MATERIALIZED VIEW.
Типичные сценарии

| Сценарий | Рекомендуемый подход | Как это работает | См. |
|---|---|---|---|
| Инкрементальная синхронизация с целевой таблицей | Table Stream типа min_delta | Таблица заказов ежедневно получает множество обновлений статуса. Создайте Table Stream типа min_delta и периодически выполняйте INSERT INTO downstream SELECT ... FROM the orders stream. Каждый запуск обрабатывает только итоговые изменения между двумя выполнениями: новые заказы, заказы с изменённым статусом (со значениями до и после) и удалённые заказы. Чтение изменений и запись в целевую таблицу выполняются в одной транзакции; при сбое она автоматически откатывается, поэтому ничего не пропускается и не потребляется дважды | Основы Table Stream |
| Журналы и таблицы событий только с добавлением данных | Table Stream типа append_only | Для таблиц детализации, в которые поступают только вставки, позволяет получать только вновь записанные строки с минимальными затратами | Типы потребления |
| Аудит и воспроизведение изменений | Table Stream типа detail или режим DETAIL в @incr | Если нужна полная история всех изменений, выгружайте изменения построчно по смещению потребления или за временной интервал и сохраняйте их в таблице аудита | Инкрементальные запросы |
| Согласованные соединения инкрементальных данных с таблицами измерений | <stream>@snapshot() | При потреблении изменений заказов требуется соединение с таблицей пользователей. users_stream@snapshot() читает образ таблицы пользователей, соответствующий смещению потребления, поэтому новый заказ никогда не соединяется с устаревшей информацией о пользователе и наоборот | Чтение снимков |
Матрица возможностей
Модели таблиц
| Модель таблицы | Changelog | Образ до изменения | Доступные типы изменений |
|---|---|---|---|
| Duplicate Key | Поддерживается | Не поддерживается | Только APPEND |
| Unique Key (Merge-on-Write, без ключа кластеризации) | Поддерживается | Поддерживается (changelog.need_historical_value = true) | APPEND / UPDATE_BEFORE / UPDATE_AFTER / DELETE |
| Unique Key (Merge-on-Read) | Не поддерживается | - | - |
| Aggregate Key | Не поддерживается | - | - |
Другие ограничения (столбцы с автоинкрементом, столбцы VARIANT, допустимые изменения схемы и т. д.) перечислены в разделе Changelog.
Выбор типа потребления
| Что вам нужно | Что выбрать | Примечания |
|---|---|---|
| Только вновь вставленные строки | append_only | Обновления и удаления не выдаются; минимальные накладные расходы |
| Итоговое изменение каждого ключа между двумя потреблениями | min_delta (по умолчанию) | Несколько изменений одного ключа сворачиваются в одну пару UPDATE_BEFORE + UPDATE_AFTER; ключ, который был вставлен, а затем удалён, не выдаётся |
| Полная история всех изменений | detail | Изменения выдаются построчно и никогда не сворачиваются |
Строки UPDATE_BEFORE и DELETE в min_delta и detail требуют образов до изменения, поэтому базовая таблица должна быть таблицей MoW с включённым свойством changelog.need_historical_value.
Предварительные требования
-
Версия: Doris 5.0.0 или более поздняя.
-
Конфигурация FE: включите следующие два параметра в
fe.confи перезапустите FE (оба параметра не поддерживают динамическое изменение):enable_feature_changelog = true
enable_table_stream = trueenable_feature_changelogуправляет changelog и выделением временных меток фиксации транзакций (TSO);enable_feature_binlogуправляет только binlog для CCR и здесь не требуется.enable_table_streamуправляет DDL для Table Stream. Если он отключён, создание Stream завершается ошибкойTable Stream is experimental. Please set enable_table_stream=true to enable it.. -
Включение changelog при создании таблицы: Changelog можно включить только при создании таблицы. Для существующей таблицы включить его через
ALTER TABLEнельзя; создайте таблицу заново и повторно загрузите данные. -
Режим развёртывания: Changelog и Table Stream работают как в режиме с совмещением хранения и вычислений, так и в режиме с разделением вычислений и хранения. Пока используйте инкрементальные запросы
@incrв совмещённом режиме; поддержка в разделённом режиме ещё дорабатывается.
При включённом changelog каждая запись дополнительно создаёт и сохраняет записи об изменениях, а таблицам MoW также требуется читать старые значения. Пропускная способность загрузки заметно снижается. Включайте эту возможность только для таблиц, которым действительно нужно инкрементальное потребление, и перед использованием в производственной среде оценивайте её на реалистичной нагрузке.
Частые вопросы
| Вопрос | Ответ |
|---|---|
| Можно ли включить changelog для существующей таблицы? | Нет. Changelog можно включить только при создании таблицы; создайте новую таблицу с включённым changelog и повторно загрузите данные, см. Changelog |
Table Stream или @incr? | Непрерывный инкрементальный ETL с гарантией exactly-once: Table Stream. Разовый анализ, просмотр изменений за прошедший период или внешняя система, которая уже самостоятельно управляет позициями: @incr, см. Отличия от Table Stream |
Создание Stream завершается ошибкой Table Stream is experimental. Please set enable_table_stream=true to enable it. | На FE не включён enable_table_stream; обновите fe.conf и перезапустите FE |
| Работает ли это в режиме с разделением вычислений и хранения? | Changelog и Table Stream работают; @incr пока используйте в режиме с совмещением хранения и вычислений |
| Как changelog влияет на запись? | Каждая запись дополнительно создаёт и сохраняет записи об изменениях, а таблицы MoW также читают старые значения, поэтому пропускная способность загрузки заметно снижается. Включайте эту возможность только для таблиц, которым нужно инкрементальное потребление, и оценивайте её на реалистичной нагрузке |
| Удаляются ли записи об изменениях автоматически? | Да. changelog.ttl_seconds задаёт срок хранения (по умолчанию — сутки); при инкрементальном чтении записи с истёкшим сроком отфильтровываются, а фоновая компактация освобождает занимаемое ими место. Потребляйте изменения в пределах срока хранения; см. Хранение и очистка |
Путеводитель по документации
| Страница | Содержание |
|---|---|
| Быстрый старт | Пошаговое руководство на 10 минут: создание таблицы, создание Stream, запись данных, просмотр изменений, потребление |
| Changelog | Включение, свойства, область поддержки, модель записей об изменениях, ограничения DDL, накладные расходы и устранение неполадок |
| Инкрементальные запросы | Запросы @incr за временной интервал и три инкрементальных режима |
| Основы Table Stream | Создание объектов Stream и управление ими, три типа потребления, начальные строки, различия между чтением и потреблением, виртуальные столбцы |
| Расширенные возможности Table Stream | Смещения на уровне партиций, снимки и сброс, согласованные соединения, параллельное потребление, влияние изменений базовой таблицы, мониторинг и восстановление |
| Incremental View Maintenance (IVM) | Поддержание асинхронных материализованных представлений на уровне строк с помощью changelog и внутренних объектов Table Stream |