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

TTL на уровне строк

Экспериментальная функция

TTL на уровне строк — экспериментальная функция, поддерживаемая начиная с Apache Doris 5.0.0. Перед внедрением проверьте её в тестовой среде.

Включите TTL при создании таблицы: впоследствии его нельзя включить для существующей обычной таблицы, отключить или переключить на другой режим TTL. Для частичных обновлений столбцов, Sequence Columns и материализованных представлений действуют ограничения, описанные ниже. Истечение срока не гарантирует немедленное освобождение места на диске.

Обзор​

TTL на уровне строк (Time to Live) делает отдельные строки невидимыми после истечения их срока и позволяет фоновой операции Compaction освободить их. Используйте его, когда для строк одной таблицы или раздела нужны разные сроки истечения. Поддерживаются встроенные таблицы с ключами Duplicate Key и Unique Key, включая Merge-on-Write (MOW) и Merge-on-Read (MOR), но не таблицы Aggregate Key.

Выбор режима TTL​

При создании таблицы выберите один из следующих взаимоисключающих режимов:

Сценарий использованияРежимКонфигурацияВремя истечения
Хранить каждое событие одинаковое время после его временной меткиИсходный столбецВключить TTL и одновременно задать function_column.ttl_col и function_column.ttlВременная метка источника + срок хранения таблицы
Позволить приложению назначать абсолютный срок для каждой строкиПрямое истечениеВключить TTL, не задавая ни одно из этих свойствАбсолютное время истечения строки, записанное в __DORIS_TTL_COL__

Правила истечения​

  • Значение исходного столбца NULL или прямое время истечения NULL означает, что строка не истекает по TTL.
  • Строка считается истёкшей, когда её время истечения меньше или равно текущему времени, используемому запросом.
  • Каждый запрос использует одно значение текущего времени на протяжении всего сканирования. Поэтому последующий запрос может вернуть меньше строк даже без промежуточных записей.

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

Предварительные условия​

  • Используйте Apache Doris 5.0.0 или более поздней версии и проверьте экспериментальную функцию в тестовой среде.
  • Подключитесь к тестовой базе данных под учётной записью с правами на создание, вставку и запросы к таблицам.
  • Используйте поддерживаемую модель таблицы: встроенный Duplicate Key или Unique Key (MOW/MOR).

Создание таблицы и проверка истечения​

В следующем примере каждое событие хранится один день после event_time. Настройка одной реплики предназначена только для этого примера и не является рекомендацией для производственной репликации.

SET time_zone = '+00:00';
DROP TABLE IF EXISTS row_ttl_events;
CREATE TABLE row_ttl_events (
id INT,
event_time DATETIME(6) NULL,
message STRING
)
DUPLICATE KEY(id)
DISTRIBUTED BY HASH(id) BUCKETS 1
PROPERTIES (
"replication_num" = "1",
"function_column.enable_row_ttl" = "true",
"function_column.ttl_col" = "event_time",
"function_column.ttl" = "1 day",
"function_column.ttl_time_zone" = "+00:00"
);

INSERT INTO row_ttl_events VALUES
(1, NOW(6) - INTERVAL 2 DAY, 'expired'),
(2, NULL, 'persistent'),
(3, NOW(6), 'live');

SELECT id, message FROM row_ttl_events ORDER BY id;

Сразу после вставки запрос возвращает:

id  message
2 persistent
3 live

Старое событие уже невидимо без ожидания Compaction. Время события NULL не приводит к истечению. TTL рассчитывается по переданному времени события, а не автоматически по времени загрузки; событие, поступившее с опозданием, может истечь сразу после загрузки.

Параметры​

Все перечисленные ниже свойства function_column.* имеют строковый тип и задаются как свойства таблицы.

СвойствоЗначение по умолчанию / условие обязательностиЗначение и правила изменения
function_column.enable_row_ttlfalse; для включения любого режима задайте trueСтроковое булево значение. Можно задать только при создании таблицы.
function_column.ttl_colНе задано; в режиме исходного столбца обязательно вместе с function_column.ttlИмя существующего негенерируемого столбца Value типа DATE/DATEV2, DATETIME/DATETIMEV2 или TIMESTAMPTZ. Столбцы Key и TIMESTAMP_NS не поддерживаются. После создания изменить нельзя.
function_column.ttlНе задано; обязательно вместе с function_column.ttl_colНеотрицательная длительность. После создания разрешается только та же или меньшая длительность. 0 означает истечение в момент времени источника, а не отключение TTL. В режиме прямого истечения недоступно.
function_column.ttl_time_zoneОбязательно для исходных столбцов DATE/DATETIME; для TIMESTAMPTZ по умолчанию +00:00Часовой пояс для интерпретации исходных временных меток. Принимаются UTC, Z или фиксированное смещение от -12:00 до +14:00 в формате +HH:MM / -HH:MM. Для TIMESTAMPTZ допускается только нулевое смещение. После создания изменить нельзя; в режиме прямого истечения задавать нельзя.

Формат длительности​

Длительности без единицы измеряются в секундах. Регистр единиц не учитывается:

ЕдиницаДопустимые формы
Неделяweek, weeks
Деньday, days, d
Часhour, hours, h
Минутаminute, minutes, m
Секундаsecond, seconds, s

Например, 86400, 1 day и 24h обозначают одну и ту же длительность. День всегда равен 24 часам.

  • Дробные и отрицательные значения, составные длительности вроде 1 day 2 hours, месяцы и годы отклоняются.
  • Длительность в микросекундах должна помещаться в знаковое 64-битное целое число.
  • Сумма исходной временной метки и длительности также должна помещаться в знаковое 64-битное число микросекунд эпохи; при переполнении вычисление времени истечения завершается ошибкой.

Часовые пояса​

В режиме исходного столбца региональные часовые пояса, такие как Asia/Shanghai, и правила летнего времени не поддерживаются. Значения DATE интерпретируются как полночь при настроенном смещении; значения TIMESTAMPTZ обозначают абсолютные моменты времени. Изменение часового пояса сеанса запроса не меняет политику TTL уже сохранённой строки.

Скрытый столбец TTL​

Doris автоматически создаёт допускающий NULL скрытый столбец __DORIS_TTL_COL__. Не объявляйте его в схеме таблицы.

В режиме исходного столбца Doris копирует значение источника в этот скрытый столбец. Записывайте или обновляйте исходный столбец; не задавайте независимое время истечения через скрытый столбец.

В режиме прямого истечения скрытый столбец имеет тип BIGINT и хранит микросекунды с начала эпохи Unix, а не секунды или миллисекунды. Входные данные обрабатываются следующим образом:

Входные данныеПоведение в режиме прямого истечения
NULL, DEFAULT или пропуск при полной вставкеДаёт NULL-время истечения, поэтому строка не истекает по TTL.
BIGINTИспользуется непосредственно как микросекунды эпохи. Значения 0 и отрицательные значения уже истекли относительно текущего времени запросов.
Выражение DATE/DATETIMEПреобразуется в микросекунды эпохи с использованием time_zone сеанса SQL или timezone задания загрузки.
Выражение TIMESTAMPTZПреобразуется в микросекунды эпохи; значение уже представляет абсолютный момент времени.
Текстовая датаЯвно приведите к поддерживаемому временному типу.
TIMESTAMP_NSНе поддерживается.

Для просмотра включите show_hidden_columns и явно выберите скрытый столбец. Это не отключает фильтрацию TTL и не делает истёкшие строки видимыми.

Примеры​

Назначение времени истечения каждой строке​

Используйте режим прямого истечения, если приложение передаёт отдельное время истечения для каждой строки:

SET time_zone = '+00:00';
DROP TABLE IF EXISTS row_ttl_expirations;
CREATE TABLE row_ttl_expirations (id INT, message STRING)
DUPLICATE KEY(id)
DISTRIBUTED BY HASH(id) BUCKETS 1
PROPERTIES (
"replication_num" = "1",
"function_column.enable_row_ttl" = "true"
);

INSERT INTO row_ttl_expirations(id, message, __DORIS_TTL_COL__) VALUES
(1, 'expired', 0),
(2, 'persistent', NULL),
(3, 'live', NOW(6) + INTERVAL 1 DAY);
INSERT INTO row_ttl_expirations VALUES (4, 'omitted');

SELECT id, message FROM row_ttl_expirations ORDER BY id;

Немедленный запрос возвращает:

id  message
2 persistent
3 live
4 omitted

INSERT ... SELECT также принимает выражения временных типов для скрытого столбца и преобразует их по тем же правилам.

Загрузка временных меток истечения через Stream Load​

Используйте таблицу row_ttl_expirations из предыдущего примера. Замените заполнители подключения и используйте учётную запись с правом загрузки. Входные данные содержат временную метку истечения, поэтому явно приведите её в сопоставлении столбцов и укажите часовой пояс загрузки:

curl --location-trusted -u '<user>:<password>' \
-H 'label:row_ttl_expirations_example_1' \
-H 'column_separator:,' \
-H 'timezone:+00:00' \
-H 'columns:id,message,expiration,__DORIS_TTL_COL__=cast(expiration as datetime(6))' \
-T - 'http://<fe_host>:<http_port>/api/<database>/row_ttl_expirations/_stream_load' <<'DATA'
10,stream-live,2099-01-01 00:00:00.000000
11,stream-expired,2000-01-01 00:00:00.000000
DATA

При повторной загрузке используйте новую метку. В успешном ответе Status равно Success; само истечение не превращает иным образом корректную входную строку в ошибку загрузки. До 2099 года следующий запрос возвращает только строку 10:

SELECT id, message FROM row_ttl_expirations WHERE id >= 10 ORDER BY id;
id  message
10 stream-live

Если входные данные уже содержат микросекунды эпохи, сопоставьте их напрямую через columns:id,message,__DORIS_TTL_COL__, не преобразуя в DATETIME.

Обновление строки Unique Key​

Обычный SQL UPDATE поддерживается. Для видимых строк изменение несвязанных столбцов сохраняет значение TTL; изменение исходной временной метки или прямого времени истечения меняет момент истечения строки. Это отличается от неподдерживаемых режимов загрузки с частичным обновлением столбцов.

DROP TABLE IF EXISTS row_ttl_accounts;
CREATE TABLE row_ttl_accounts (id INT, message STRING)
UNIQUE KEY(id)
DISTRIBUTED BY HASH(id) BUCKETS 1
PROPERTIES (
"replication_num" = "1",
"enable_unique_key_merge_on_write" = "true",
"function_column.enable_row_ttl" = "true"
);
INSERT INTO row_ttl_accounts(id, message, __DORIS_TTL_COL__) VALUES
(1, 'original', 9223372036854775807);
UPDATE row_ttl_accounts SET message = 'updated' WHERE id = 1;

SET show_hidden_columns = true;
SELECT id, message, __DORIS_TTL_COL__ FROM row_ttl_accounts ORDER BY id;
SET show_hidden_columns = false;
id  message  __DORIS_TTL_COL__
1 updated 9223372036854775807

Полный UPSERT строки заменяет строку целиком. Поэтому в режиме прямого истечения пропуск времени истечения очищает старое время:

INSERT INTO row_ttl_accounts(id, message) VALUES (1, 'replaced');
SET show_hidden_columns = true;
SELECT id, message, __DORIS_TTL_COL__ FROM row_ttl_accounts ORDER BY id;
SET show_hidden_columns = false;
id  message   __DORIS_TTL_COL__
1 replaced NULL

Учитывайте следующие правила обновления:

  • В режиме исходного столбца полная вставка без исходного столбца использует обычные правила DEFAULT/NULL этого столбца, а не временную метку предыдущей версии строки.
  • UPDATE не может найти уже истёкшую строку обычным запросом; чтобы записать новую версию, используйте полную вставку с нужными значениями.
  • В таблицах Unique Key истечение новейшей версии не открывает снова старую версию того же ключа.

Сокращение срока хранения​

Используйте таблицу с исходным столбцом из раздела «Быстрый старт» и учётную запись с правом ALTER:

ALTER TABLE row_ttl_events SET ("function_column.ttl" = "12 hours");
SHOW CREATE TABLE row_ttl_events;

Новый срок хранения применяется как к существующим значениям исходного столбца, так и к будущим записям. SHOW CREATE TABLE показывает обновлённое свойство function_column.ttl; длительности, отображаемые как целые числа без единицы, указаны в секундах.

Строки, которые по новой политике вышли за срок хранения, становятся невидимыми для запросов с этой политикой и пригодными для освобождения. Повторно задать ту же длительность разрешено; увеличение отклоняется, поскольку ранее истёкшие данные уже могли быть освобождены.

Ошибка ALTER не означает откат

Более короткая политика запросов сохраняется до распространения настроек освобождения. Поэтому ALTER может сообщить о тайм-ауте, отсутствии подтверждения версии конфигурации или одновременном изменении таблицы уже после применения сокращённого срока хранения.

Проверьте SHOW CREATE TABLE, устраните указанную проблему и повторите операцию с той же длительностью, чтобы синхронизировать политику. Не пытайтесь восстановить прежнюю, более длинную длительность.

Ограничения​

Перед включением TTL проверьте совместимость с существующими функциями таблицы и рабочими нагрузками:

ОбластьТекущее поведение / ограничение
Модель таблицыПоддерживаются только встроенные таблицы Duplicate Key и Unique Key (MOW/MOR); Aggregate Key отклоняется.
Включение и изменение режимаВключить можно только во время CREATE TABLE. ALTER не может включить или отключить TTL, изменить его исходный столбец или часовой пояс либо переключить режим. ENABLE FEATURE "ROW_TTL" не поддерживается. Сократить можно только срок хранения в режиме исходного столбца.
Sequence ColumnНе может использоваться вместе с TTL на уровне строк, включая последующее включение SEQUENCE_LOAD.
Изменения схемыНельзя удалить или изменить исходный либо скрытый столбец TTL и переименовать исходный столбец. Изменения несвязанных столбцов по-прежнему подчиняются обычным правилам изменения схемы.
Частичные обновления столбцовНе поддерживаются ни в одном режиме TTL. Сюда входят INSERT с enable_unique_key_partial_update = true, Stream Load с partial_columns = true, UPDATE_FIXED_COLUMNS и UPDATE_FLEXIBLE_COLUMNS, даже если запрос содержит значение TTL. Полный UPSERT, обычный SQL UPDATE и DELETE остаются доступными по обычным правилам модели таблицы.
Материализованные представленияCREATE MATERIALIZED VIEW для синхронных материализованных представлений отклоняется на таблицах с TTL; асинхронные материализованные представления не могут использовать таблицы TTL как базовые. Это отличается от обычного ALTER TABLE ... ADD ROLLUP, который поддерживается, а скрытый столбец TTL обслуживается Doris.
Исторический и инкрементальный доступВ таблицах TTL не поддерживаются FOR VERSION AS OF, FOR TIME AS OF, @incr(...) и CREATE STREAM ... ON TABLE.
Подсказки запросовPREAGGOPEN отклоняется. При сканировании MOR отключается предварительная агрегация на уровне хранилища, чтобы сохранить корректную семантику слияния версий и истечения.
Производительность запросовПри сканировании TTL отключаются SQL Cache, Query Cache, короткие точечные запросы и некоторые оптимизации проталкивания TopN. Точечные выборки, агрегаты, соединения и ORDER BY/LIMIT по-прежнему работают, но нельзя предполагать тот же план выполнения или производительность, что у таблицы без TTL.
Проверки согласованностиАвтоматические проверки согласованности контрольных сумм пропускают таблицы TTL; явные проверки согласованности контрольных сумм для TTL-tablet отклоняются. Обычная репликация при этом не отключается.

Границы физического освобождения​

Видимость TTL проверяется во время запросов; освобождение места на диске зависит от подходящей фоновой Compaction и последующей очистки устаревших файлов. Простаивающая таблица, задержка Compaction или сохранение старых файлов могут оставить истёкшие данные на диске. Фиксированного срока удаления нет.

Освобождение зависит от модели таблицы и пути Compaction:

Модель таблицы / путь данныхПоведение освобождения
Duplicate KeyПоддерживаемые пути segment, cumulative, base и full Compaction могут освобождать истёкшие строки.
Unique Key MOWCumulative, base и full Compaction могут освобождать истёкшие строки из опубликованных rowset. Segment Compaction до публикации сохраняет истёкшие ключи для разрешения конфликтов записи.
Unique Key MORИстёкшие строки освобождаются только при full Compaction или base Compaction, охватывающей версии начиная с 0; удаление не открывает старые версии того же ключа.
Compaction холодных данныхОсвобождение по TTL строк не выполняется.
Changelog tabletsTTL строк не удаляет записи журнала. Необработанный Changelog может сохранять записи, строки которых в базовой таблице уже истекли; его хранение регулируется отдельно.

TTL на уровне строк не гарантирует, что в момент истечения будут удалены все копии или записи изменений.

Устранение неполадок​

Используйте следующие проверки при ошибках конфигурации или задержке освобождения хранилища:

Ошибка / симптомДействие
function_column.ttl_col and function_column.ttl must be set togetherДля режима исходного столбца задайте оба свойства, а для режима прямого истечения не задавайте ни одного.
function_column.ttl_time_zone is requiredЯвно задайте фиксированное смещение для исходного столбца DATE/DATETIME.
row ttl column must be a value columnВыберите поддерживаемый временной столбец Value, а не столбец Key.
Partial update is not supported on tables with row TTLИспользуйте полный UPSERT с намеренно заданными значениями по умолчанию для пропущенных столбцов или обычный SQL UPDATE; не удаляйте настройку частичного обновления, не проверив значения пропущенных столбцов.
Increasing function_column.ttl is not supportedСохраните или сократите длительность. Если требуется более длительное хранение, создайте новую таблицу и повторно загрузите данные из сохранённого источника; TTL не может восстановить уже освобождённые данные.
TTL properties can only be specified when creating a tableНе изменяйте через ALTER флаг включения, исходный столбец или часовой пояс. В таблице TTL с исходным столбцом можно менять только function_column.ttl.
Строки исчезают, но размер хранилища не уменьшаетсяПроверьте ход Compaction и описанные выше границы освобождения. Истечение и физическое удаление — отдельные этапы.

Лучшие практики​

  • Выбирайте режим исходного столбца, когда после каждого события нужно хранить данные одинаковое время, и режим прямого истечения, когда приложение назначает абсолютный срок для каждой строки. Перед загрузкой проверяйте запаздывающие временные метки и значения NULL.
  • Если хранение естественным образом следует целым временным разделам, отдавайте предпочтение динамическому секционированию. TTL на уровне строк подходит для более детального управления, но добавляет фильтрацию каждой строки и ограничивает оптимизации запросов.
  • Перед внедрением протестируйте реальные рабочие нагрузки загрузки, обновления, запросов и Compaction. Особенно проверьте зависимости от частичных обновлений, Sequence Columns, материализованных представлений, исторических запросов и кэширования.
  • Перед сокращением срока хранения подтвердите нужную границу истечения и сохраните вне этой политики TTL все данные, которые должны оставаться восстанавливаемыми. Проверяйте видимость обычными запросами; размер на диске или просмотр скрытого столбца не доказывают ни истечение, ни полное удаление данных.