OBKV-Tableでは、データの有効期限を設定し、期限切れデータを削除することで、ストレージ使用量を削減できます。また、期限切れデータを読み取り結果から除外します。本記事では、コマンドまたは定期タスクで期限切れデータを削除する方法を説明します。
注意
期限切れデータの削除(TTL)機能は、OceanBase KVでの使用に限定されます。SQLで使用してはいけません。使用すると、意図しないデータが誤って削除されるおそれがあります。
使用方法
TTL機能の基本的な使用手順は以下のとおりです:
- TTL機能を有効にする:
enable_kv_ttl = trueを設定して、テナントのTTLタスクスイッチをオンにします。 - TTLテーブルを定義する:テーブル作成時にTTL属性を指定するか、既存のテーブルにTTL属性を追加します。TTL属性の変更/削除をサポートします。
- 削除タスクをトリガーする:手動コマンドまたは定期タスクを設定して、期限切れデータの削除をトリガーします。実行中のタスクの一時停止/再開/キャンセルをサポートします。
- タスクの状態を確認する:システムビューでタスクの実行状況を監視します。
以下で詳しく説明します。
ステップ1:TTL機能を有効にする
TTL機能を有効にするには、テナントレベルの構成パラメータenable_kv_ttlをtrueに設定する必要があります。
ALTER SYSTEM SET enable_kv_ttl= true; -- テナントレベルの構成パラメータ。デフォルト値はfalseです。
ステップ2:TTLテーブルを定義する
テーブルのTTL属性はCOLUMN_NAME + INTERVAL NUM TTL_UNITの形式で定義します。ここで、各項目の説明は以下の通りです:
COLUMN_NAME:TIMESTAMPまたはDATETIME型の、テーブル内で定義済みの列名。+ INTERVAL:固定部分です。NUM:有効期間を表す整数値。TTL_UNIT:SECOND,MINUTE,HOUR,DAY,MONTH,YEARのいずれかです。
新しいTTL関係テーブルt1を作成し、各行データを12時間後に期限切れにする場合は、以下のステートメントで作成できます:
CREATE TABLE t1 (
a INT PRIMARY KEY,
b TIMESTAMP DEFAULT current_timestamp ON UPDATE current_timestamp)
TTL (b + INTERVAL 12 HOUR);
既存のテーブルt1のTTL属性を変更し、有効期限を1日に変更する場合は、以下のステートメントで変更できます:
ALTER TABLE t1 TTL (b + INTERVAL 1 DAY);
テーブルt1のTTL属性を削除する場合は、以下のステートメントで削除できます:
ALTER TABLE t1 REMOVE TTL;
ステップ3:タスクのトリガー
TTL削除タスクをトリガーする方法は2つあります:
- システムテナントからのコマンドによるトリガー:システムテナントにログインして、すべてのテナントのTTLタスクをトリガーします。タスクのトリガーに加え、システムテナントでは実行中のTTLタスクの一時停止、再開、キャンセルもサポートしています。
- 定期的なタスクトリガー:TTLタスクを実行したいユーザーテナントにログインし、そのユーザーテナントの毎日のTTLタスクのトリガー時間を設定します。
TTLコマンドは、ユーザーテナントまたはシステムテナントでの実行時にのみ有効です。ユーザーテナントで実行する場合は、そのテナント自身のTTLタスクのみを管理できます。システムテナントで実行する場合は、すべてのユーザーテナントのTTLタスクを管理できます。
システムテナントにログインし、以下のコマンドを実行して、すべてのテナントのTTLタスクをトリガーします。
ALTER SYSTEM TRIGGER TTL;
実行中のTTLタスクを一時停止するコマンドは以下のとおりです。
ALTER SYSTEM SUSPEND TTL;
一時停止されたTTLタスクを再開するコマンドは以下のとおりです。
ALTER SYSTEM RESUME TTL;
実行中のTTLタスクをキャンセルするコマンドは以下のとおりです。
ALTER SYSTEM CANCEL TTL;
TTLタスクを実行するテナントにログインし、以下のコマンドを実行して、テナントの1日のTTLタスクのトリガー時間を設定します。
-- デフォルト値は""で、定期TTLタスクがトリガーされないことを意味します。
ALTER SYSTEM SET kv_ttl_duty_duration = '[22:00:00, 24:00:00]';
ステップ4:タスクの状態を確認する
以下のビューで、現在および過去のTTLタスクの状態と関連情報を確認できます:
ビュー名 |
ビューの役割 |
|---|---|
| DBA_OB_KV_TTL_TASKS | 現在のテナントで実行中のTTLタスクを確認する |
| DBA_OB_KV_TTL_TASK_HISTORY | 現在のテナントの履歴TTLタスクを確認する |
| CDB_OB_KV_TTL_TASKS | システムテナントで、すべてのテナントが実行中のTTLタスクを確認する。DBAビューに比べて TENANT_ID 列が追加されている |
| CDB_OB_KV_TTL_TASK_HISTORY | システムテナントで、すべてのテナントの履歴TTLタスクを確認する。DBAビューに比べて TENANT_ID 列が追加されている |
タスクの状態の説明
TTLタスクは、テナントレベルタスクとTabletレベルタスクの2種類に分類され、それぞれ異なる状態が対応します。いずれの状態も、タスクビューのDBA_OB_KV_TTL_TASKSおよびCDB_OB_KV_TTL_TASKS、および履歴タスクビューのDBA_OB_KV_TTL_TASK_HISTORYおよびCDB_OB_KV_TTL_TASK_HISTORYで確認できます。
注意
テナントレベルタスクのTABLE_NAMEはNULL、TABLET_IDおよびTABLE_IDはいずれも-1です。
Tabletレベルタスクの状態:
タスクの状態 |
説明 |
|---|---|
| PREPARED | 準備中。期限切れデータの削除はまだ開始されていない |
| RUNNING | 実行中。このパーティションの期限切れデータを削除しています |
| PENDING | 一時停止中。コマンドで実行を再開できます |
| CANCELED | 取り消し状態。実行を再開することはできません |
| FINISHED | 完了状態。履歴テーブルに移動する予定です |
| INVALID | 無効状態 |
テナントレベルタスクの状態:
タスクの状態 |
説明 |
|---|---|
| RS_TRIGGERING | テナントTTLタスクが実行中であることを示します。 |
| RS_SUSPENDING | テナントTTLタスクが一時停止されていることを示します。 |
| RS_CANCELING | テナントTTLタスクがキャンセルされたことを示します。 |
| RS_MOVING | すべてのTTLタスクレコードを履歴テーブルに移動していることを示します。 |
| INVALID | 無効な状態 |
履歴タスクのクリーンアップサイクルを設定する(オプション)
TTLタスクの履歴が蓄積してストレージを圧迫しないように、構成パラメータkv_ttl_history_recycle_intervalで履歴の保持期間を設定できます。デフォルトは7日間です。
例えば、30日を超える履歴TTLタスクレコードを自動的にクリーンアップするよう設定するコマンドは以下のとおりです:
ALTER SYSTEM SET kv_ttl_history_recycle_interval= '30d';
パフォーマンス最適化
パラレル度の設定
テナントレベル構成パラメータ ttl_thread_score を使用して、TTLタスクのワーカースレッド数を設定できます。デフォルト値は2です。
例えば、TTLタスクのワーカースレッド数を10に変更します:
ALTER SYSTEM SET ttl_thread_score = 10;
インデックススキャン
TTL(Time To Live)タスクでは、インデックススキャンを利用して期限切れデータを効率よく削除できます。デフォルトではテーブル全体を主キー順にスキャンし、各行の有効期限を確認するため、I/O負荷が大きくなります。有効期限の判定に使う列にローカルインデックスを作成し、TTLタスクでそのインデックスを指定すると、インデックスだけで期限切れを判定できます。これにより不要なデータ読み取りを減らし、削除処理を高速化できます。
テーブル作成時に、プロパティパラメータKV_ATTRIBUTESのTTLScanIndexサブパラメータでインデックス名を指定することで、インデックススキャンを有効にします。構文は以下のとおりです:
-- 実際の使用では、$index_nameをインデックス名に置き換える必要があります
CREATE TABLE table_name (
...
) TTL (ttl_column + INTERVAL ...)
KV_ATTRIBUTES = '{"TTLScanIndex": "$index_name"}';
以下に、異なるシナリオの例をいくつか示します:
例1では、TTLタスクが有効期限の判定に使う列を含むローカルインデックスを使用して、期限切れデータのクリーンアップ効率を向上させる方法を示しています。
CREATE TABLE test_ttl_with_index (
a INT PRIMARY KEY,
b TIMESTAMP DEFAULT current_timestamp ON UPDATE current_timestamp,
c VARCHAR(128),
INDEX idx(b) LOCAL
) TTL (b + INTERVAL 12 HOUR)
KV_ATTRIBUTES = '{"TTLScanIndex": "idx"}';
説明:
- テーブルは
b列をTTL列として使用し、期限は12時間です。 TTLScanIndexを使用して、idxインデックスでスキャンすることを指定します。idxインデックスはTTL列b上に構築されており、期限切れデータを効率的に特定できます。
OBKV-Tableのヒープテーブルモデルを使用する場合、通常は一意のキーとして一意インデックスを作成し、有効期限の判定に使う列をその一意インデックス上に冗長的に格納します。TTLタスクはこのインデックスを指定して期限切れデータのスキャンを実行します。例2では、ヒープテーブルを作成し、有効期限の判定に使う列を一意インデックス上に冗長的に格納し、一意インデックスを使用して期限切れデータをスキャンする方法を示しています。
CREATE TABLE test_ttl_storing_index (
pagerowkey VARCHAR(1024) NOT NULL,
request LONGTEXT DEFAULT NULL,
rawpage LONGBLOB NOT NULL,
pagecode VARCHAR(1024) NOT NULL,
timestamp BIGINT(20) NOT NULL,
_expire_ts TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
-- _expire_tsを一意インデックスu_idx_pagerowkey上に冗長的に格納する
UNIQUE INDEX u_idx_pagerowkey (pagerowkey) STORING (_expire_ts)
) ORGANIZATION = HEAP DEFAULT CHARSET = utf8mb4
TTL (_expire_ts + INTERVAL 1 DAY)
-- 一意インデックスu_idx_pagerowkeyを使用して期限切れデータをスキャンする
KV_ATTRIBUTES = '{"TTLScanIndex": "u_idx_pagerowkey"}';
説明:
STORING (_expire_ts)を使用して、TTL列_expire_tsを一意インデックスu_idx_pagerowkey上に冗長的に格納することで、TTLタスク中のベーステーブルへの追加アクセスを回避します。
例3では、まずテーブルを作成し、その後 ALTER TABLE を使用してインデックス idx3 を追加し、インデックススキャンを有効にする方法を示しています。
-- テーブルの作成(初期段階ではインデックススキャンは使用しない)
CREATE TABLE test_ttl_with_index_6 (
a INT PRIMARY KEY,
b TIMESTAMP DEFAULT current_timestamp ON UPDATE current_timestamp,
c VARCHAR(128),
INDEX idx(b) LOCAL,
INDEX idx2(c) LOCAL
) TTL (b + INTERVAL 12 HOUR);
-- インデックスの追加とインデックススキャンの有効化
ALTER TABLE test_ttl_with_index_6 ADD INDEX idx3(b, c);
ALTER TABLE test_ttl_with_index_6 SET KV_ATTRIBUTES = '{"TTLScanIndex": "idx3"}';
説明:
ALTER TABLEを使用してインデックスidx3を追加し、インデックススキャンを有効にします。KV_ATTRIBUTESを使用して、インデックスidx3を使用した期限切れデータのスキャンを指定します。
注意点
変更ログのフィルタリング
注意
この機能はV4.4.2 BP1バージョンからサポートされており、V4.4.2 BP1以降のバージョンのliboblogと併用する必要があります。
TTLタスクは、期限切れデータを削除する際に大量の変更ログ(Change Log、CLOG)を生成します。デフォルトでは、CDC(liboblog)はこれらの変更ログを正常にキャプチャし、消費した上で下流コンポーネントに同期します。ただし、期限切れデータ量が多いシナリオでは、TTLによるデータ削除で生成される大量のログがCDCパイプラインに過剰な処理負荷とリソース消費をもたらします。
CDCの処理負荷を軽減するには、TTL変更ログのフィルタリング機能(filter_ttl_delete_log)を有効にします。有効にすると、TTLタスクが生成した変更ログはCDCで除外され、下流に出力されなくなります。デフォルトではこの機能は無効で、TTL変更ログも通常どおり処理されます。フィルタリングの対象はTTLタスクの変更ログだけであり、TTLタスク自体の実行処理は変わりません。
期限切れデータの可視性
OBKV-Tableインターフェースで期限切れのレコードを操作すると、そのレコードが存在しない場合と同じ動作になります。例えば、主キーがk1の期限切れレコードが存在していても、同じ主キーk1のレコードを挿入できます。この場合、主キーの重複エラーは発生しません。
操作 |
期限切れ |
戻りコード |
affected rows |
その他 |
|---|---|---|---|---|
| insert | N | -5024 OB_ERR_PRIMARY_KEY_DUPLICATE |
0 | |
| insert | Y | 0 OB_SUCCESS |
1 | |
| delete | N | 0 OB_SUCCESS |
1 | |
| delete | Y | 0 OB_SUCCESS |
0 | |
| update | N | 0 OB_SUCCESS |
1 | |
| update | Y | 0 OB_SUCCESS |
0 | |
| replace | N | 0 OB_SUCCESS |
2 | |
| replace | Y | 0 OB_SUCCESS |
1 | |
| insert_or_update | N | 0 OB_SUCCESS |
1 | |
| insert_or_update | Y | 0 OB_SUCCESS |
1 | |
| increment | N | 0 OB_SUCCESS |
1 | |
| increment | Y | 0 OB_SUCCESS |
1 | increment列以外の列はデフォルト値に設定されます |
| append | N | 0 OB_SUCCESS |
1 | |
| append | Y | 0 OB_SUCCESS |
1 | append列以外の列はデフォルト値に設定されます |
| query/get | N | 0 OB_SUCCESS |
/ | データの読み取りに成功しました |
| query/get | Y | 0 OB_SUCCESS |
/ | データを読み取ることができませんでした |
説明
SQLインターフェースでは、期限切れデータを読み取り結果から除外しません。削除タスクで削除されるまでは、期限切れデータも参照できます。
タスクの実行メカニズム
TTLによる期限切れデータ削除タスクは、バックグラウンドで低優先順位で実行されるタスクであり、期限切れデータが即座に削除される保証はありません。システム性能への影響を抑えるため、以下の状況ではタスクは自動的に一時停止されます:
- メモリ負荷が高い場合:MemStoreのメモリ使用量
MEMSTORE_USEDがしきい値FREEZE_TRIGGERを超えた場合、タスクの実行は一時停止され、メモリ使用量がしきい値を下回るまで続行されません。メモリ使用状況はGV$OB_MEMSTOREビューで確認できます。 - 物理復元中:物理復元中のテナントについては、TTLタスクの実行は一時停止され、テナントの復元完了まで続行されません。
ストレージ容量の解放
OceanBaseデータベースはLSM-Treeアーキテクチャを採用しているため、削除操作は本質的には追記書き込み(削除フラグの書き込み)です。そのため、TTLタスクが期限切れデータを削除した後も、実際のストレージ容量は即座に解放されず、一時的に増加する可能性さえあります。ストレージ容量の最終的な解放は、メジャーコンパクションプロセスに依存します。
ストレージ容量が適時に解放されるようにするために、TTLタスクとMajor Freezeを組み合わせて使用することを推奨します:
- TTLタスクの実行時間枠(
kv_ttl_duty_duration)を設定します。 - Major Freezeの実行時間(
major_freeze_duty_time)をTTLタスクの時間枠の後に設定します。
これにより、TTLタスク終了後に自動的にメジャーコンパクションがトリガーされ、ストレージ容量が解放されます。
全体の例
TTL機能を有効にします。
ALTER SYSTEM SET enable_kv_ttl= true;TTL関係テーブルを作成し、各レコードがc + 10秒後に期限切れになるように定義します。
CREATE TABLE ttl_table(a VARCHAR(1024) PRIMARY KEY, b VARCHAR(1024), c TIMESTAMP) TTL(c + INTERVAL 10 SECOND) PARTITION BY KEY(a) PARTITIONS 3;データを挿入します(OBKV-Table/SQLを使用できます。OBKV-Tableインターフェースを使用してデータを挿入するには、詳細な操作手順については、クライアントの概要と使用方法を参照してください)。
INSERT INTO ttl_table VALUES("k1", "hello obkv", now()); INSERT INTO ttl_table VALUES("k2", "hello obkv", now()); INSERT INTO ttl_table VALUES("k3", "hello obkv", now());10秒待った後、コマンドを実行してTTLタスクの実行をトリガーします。
ALTER SYSTEM TRIGGER TTL; -- 0時から、TTLタスクを1回トリガーしようと試みますタスクの実行状態を確認します。
obclient> SELECT * FROM OCEANBASE.DBA_OB_KV_TTL_TASKS;実行結果は次のとおりです:
+------------+----------+-----------+---------+----------------------------+----------------------------+--------------+---------------+-------------+---------------------+----------+------------+ | TABLE_NAME | TABLE_ID | TABLET_ID | TASK_ID | START_TIME | END_TIME | TRIGGER_TYPE | STATUS | TTL_DEL_CNT | MAX_VERSION_DEL_CNT | SCAN_CNT | RET_CODE | +------------+----------+-----------+---------+----------------------------+----------------------------+--------------+---------------+-------------+---------------------+----------+------------+ | ttl_table | 500002 | 200003 | 1 | 2023-09-27 23:31:30.300276 | 2023-09-27 23:31:35.315848 | USER | FINISHED | 2 | 0 | 2 | OB_SUCCESS | | ttl_table | 500002 | 200002 | 1 | 2023-09-27 23:31:30.300276 | 2023-09-27 23:31:35.320258 | USER | FINISHED | 1 | 0 | 1 | OB_SUCCESS | | ttl_table | 500002 | 200001 | 1 | 2023-09-27 23:31:30.300271 | 2023-09-27 23:31:35.321879 | USER | FINISHED | 0 | 0 | 0 | OB_SUCCESS | | NULL | -1 | -1 | 1 | 2023-09-27 23:31:28.675583 | 2023-09-27 23:31:28.675583 | USER | RS_TRIGGERING | 0 | 0 | 0 | OB_SUCCESS | +------------+----------+-----------+---------+----------------------------+----------------------------+--------------+---------------+-------------+---------------------+----------+------------+ 4 rows in set (0.043 sec)タスクの完了後、その実行記録は履歴テーブルに移動されます。
OCEANBASE.DBA_OB_KV_TTL_TASK_HISTORYで確認できます。obclient> SELECT * FROM OCEANBASE.DBA_OB_KV_TTL_TASK_HISTORY;実行結果は次のとおりです:
+------------+----------+-----------+---------+----------------------------+----------------------------+--------------+----------+-------------+---------------------+----------+------------+ | TABLE_NAME | TABLE_ID | TABLET_ID | TASK_ID | START_TIME | END_TIME | TRIGGER_TYPE | STATUS | TTL_DEL_CNT | MAX_VERSION_DEL_CNT | SCAN_CNT | RET_CODE | +------------+----------+-----------+---------+----------------------------+----------------------------+--------------+----------+-------------+---------------------+----------+------------+ | ttl_table | 500002 | 200003 | 1 | 2023-09-27 23:31:30.300276 | 2023-09-27 23:31:35.315848 | USER | FINISHED | 2 | 0 | 2 | OB_SUCCESS | | ttl_table | 500002 | 200002 | 1 | 2023-09-27 23:31:30.300276 | 2023-09-27 23:31:35.320258 | USER | FINISHED | 1 | 0 | 1 | OB_SUCCESS | | ttl_table | 500002 | 200001 | 1 | 2023-09-27 23:31:30.300271 | 2023-09-27 23:31:35.321879 | USER | FINISHED | 0 | 0 | 0 | OB_SUCCESS | | NULL | -1 | -1 | 1 | 2023-09-27 23:31:28.675583 | 2023-09-27 23:31:42.526853 | USER | FINISHED | 0 | 0 | 0 | OB_SUCCESS | +------------+----------+-----------+---------+----------------------------+----------------------------+--------------+----------+-------------+---------------------+----------+------------+ 4 rows in set (0.058 sec)タスクの実行完了後、すべての期限切れデータが削除されたことが確認できます。
obclient> SELECT * FROM ttl_table; Empty set (0.060 sec)