OBKV-HBaseは、HBaseモデルにおけるカラムファミリー(Column Family)レベルおよびセル(Cell)レベルでの期限切れデータ削除(TTL、Time To Live)機能を実装しています。本記事では、コマンドまたは定期タスクを使用して、カラムファミリーレベルまたはセルレベルの期限切れデータを削除する方法について説明します。
注意
期限切れデータ削除(TTL)機能は、OceanBase KVを使用するシナリオに限定されます。SQLを使用するシナリオでは、この機能を使用しないでください。使用すると、予期せずデータを誤って削除するおそれがあります。
分類
現在、OBKV-HBaseはColumn FamilyおよびCellレベルのTTLをサポートしています。
TTLタイプ |
説明 |
有効化 |
対応バージョン |
|---|---|---|---|
| Column Familyレベル | Column FamilyレベルのTTLを設定します。このColumn Familyに書き込まれるすべてのデータは、指定された時間に達すると期限切れになります。 | テーブル作成ステートメントでKV_ATTRIBUTESパラメータを指定することで機能を有効化します。 |
|
| Cellレベル | CellレベルのTTLにより、ユーザーは各セルに独立した有効期限を設定できます。これにより、同一のColumn Family内でも異なるCellが異なる存続時間を持つことが可能です。この方法により、ユーザーはデータのライフサイクルをより柔軟に管理し、最も関連性のあるデータのみが保持されるように保証できます。 | テーブル作成時にTTL列を作成することで機能を有効化します。TTL列のデフォルト値はNULLです。 |
|
注意
Column FamilyレベルとCellレベルのTTLを同時に有効にすることができます。実際のTTL値は、そのうちの最小値になります。
使用方法
TTL機能の基本的な使用手順は以下のとおりです:
- TTL機能を有効にする:
enable_kv_ttl = trueを設定して、テナントのTTLタスクスイッチをオンにします。 - TTLテーブルを定義する:テーブル作成時にTTL属性(Column FamilyレベルまたはCellレベル)を指定します。TTL属性の変更や削除もサポートされています。
- 削除タスクをトリガーする:手動コマンドまたは定期タスクを設定して、期限切れデータの削除をトリガーします。実行中のタスクの一時停止、再開、キャンセルもサポートされています。
- タスクの状態を確認する:システムビューでタスクの実行状況を監視します。
注意
Column FamilyレベルとCellレベルのTTLは、テーブル定義構文が異なる点を除き、その他の機能の使い方は同じです。
以下に詳しく説明します。
ステップ1:TTL機能を有効にする
TTL機能を有効にするには、テナントレベルのパラメータenable_kv_ttlをtrueに設定する必要があります。
ALTER SYSTEM SET enable_kv_ttl= true; -- テナントレベルのパラメータ、デフォルト値はfalse
ステップ2:TTLテーブルを定義する
ここでは、Column FamilyレベルとCellレベルのTTLテーブル定義の構文と例を紹介します。
Column FamilyレベルのTTL機能は、KV_ATTRIBUTESプロパティのTimeToLiveおよびMaxVersionsパラメータで設定します。例えば、OBKV-HBaseテーブルt1$cf1を作成し、各行データの有効期限を3600秒、各行データの最大バージョン数を3に指定します。
CREATE TABLE t1$cf1 (
K VARBINARY(1024),
Q VARBINARY(256),
T BIGINT,
V VARBINARY(1048576) NOT NULL,
PRIMARY KEY(K, Q, T))
-- TimeToLiveの単位は秒です
KV_ATTRIBUTES ='{"Hbase": {"TimeToLive": 3600, "MaxVersions": 3}}'
PARTITION BY KEY(K) PARTITIONS 97;
OBKV-HBaseテーブルt1$cf1を変更し、TimeToLiveプロパティを削除して最大バージョン数を4に変更します。
ALTER TABLE t1$cf1 KV_ATTRIBUTES ='{"Hbase": {"MaxVersions": 4}}';
OBKV-HBaseテーブルt1$cf1の有効期限プロパティを削除します。
ALTER TABLE t1$cf1 KV_ATTRIBUTES ='{"Hbase": {}}';
セルレベルのTTL機能は、テーブルにTTL列を作成することで設定します。例えば、OBKV-HBaseテーブルt1$cf1を作成し、TTL列を含めます。
CREATE TABLE `t1$cf1` (
`K` VARBINARY(1024) NOT NULL,
`Q` VARBINARY(256) NOT NULL,
`T` BIGINT(20) NOT NULL,
`V` VARBINARY(1024) DEFAULT NULL,
-- セルレベルのTTLを作成します。具体的なパラメータはput/increment/append/get/scan/delete DML操作時に指定し、単位はミリ秒です。
-- TTL列は必ず5列目の位置に作成してください。
`TTL` BIGINT(20) DEFAULT NULL,
PRIMARY KEY (`K`, `Q`, `T`)
);
ステップ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タスクの状態と関連情報を確認できます。TTLタスクに関連するビューは4つあります。詳細については、OBKV-HBase関連ビューを参照してください。
タスクタイプ
現在のOBKV-HBaseでは、TTLタスクには2種類あります:Normal TTLタスクとHBase Rowkey TTLタスクです。これに対応するのがタスク状態表のtask_type列です。
- Normal TTLタスク
コマンドまたは定期タスクによってトリガーされ、まずテナントレベルのTTLタスク(table idが-1のレコードに対応)が生成されます。同時に、有効期限ルールが定義されたすべてのテーブルに対して、tabletレベルのTTLタスクが生成され実行されます。各tabletタスクは、そのtablet内の全データをスキャンして、期限切れデータを検出し削除します。すべてのtabletタスクの実行が完了すると、このテナントTTLタスクのすべてのタスクレコードが履歴テーブルに移動されます。
- HBase Rowkey TTLタスク
固定の周期でトリガーされ、毎日古いHBase rowkey TTLタスクのレコードが履歴テーブルに移動され、新しいテナントレベルのHBase rowkey TTLタスク(table idが-2に対応)が生成されます。また、有効期限ルールが定義されたすべてのテーブルに対してtabletレベルのTTLタスクが生成されます。このtabletタスクの実行はユーザーのリクエストに基づいてトリガーされ、Scan/Get操作で扱われた期限切れrow(TTLまたはMaxVersionで期限切れになったrow)を収集し、そのrowのみをスキャンするTTLタスクを生成します。タスクの実行後、結果(scan_cnt/max_version_del_cnt/ttl_del_cnt)が対応するtabletタスクに集計されます。
タスク状態の説明
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構成パラメータを使用して、テナントの履歴TTLタスクレコードの保存期間を設定できます(デフォルトは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;
注意点
変更ログのフィルタリング
注意
この機能はV4.4.2 BP1バージョンからサポートされており、V4.4.2 BP1以降のバージョンのliboblogと併用する必要があります。
TTLタスクは、期限切れデータを削除する際に大量の変更ログ(Change Log、CLOG)を生成します。デフォルトでは、CDC(liboblog)はこれらの変更ログを正常にキャプチャして消費し、下流コンポーネントに同期します。期限切れデータ量が多いシナリオでは、TTLによる削除で発生する大量のログがCDCリンクに追加の処理負荷とリソース消費をもたらします。
CDCリンクのリソース負荷を軽減するため、CDC側のTTL変更ログフィルタリング機能(filter_ttl_delete_log)を有効にできます。有効にすると、TTLタスクが生成する変更ログはCDCによってフィルタリングされ、下流に出力されなくなります。デフォルトではフィルタリングは無効であり、TTL変更ログはCDCによって正常に消費されます。フィルタリングを有効にしても、TTLタスク自体の実行ロジックは変更されません。ただし、TTLタスクの変更ログのみが影響を受けます。
期限切れデータの可視性
OBKV-HBaseインターフェースを使用してレコードに対する操作を実行した場合、そのレコードが既に期限切れである場合、その動作はレコードが存在しない場合と同じになります。例えば、リレーショナルテーブルに主キーが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タスクが完了すると自動的にメジャーコンパクションがトリガーされ、ストレージ容量が解放されます。
一連の操作例
Column Familyレベル
TTL機能を有効にします。
ALTER SYSTEM SET enable_kv_ttl= true;OBKV-HBaseテーブルを作成します。
CREATE TABLE t1$cf1 ( K VARBINARY(1024), Q VARBINARY(256), T BIGINT, V VARBINARY(1048576) NOT NULL, PRIMARY KEY(K, Q, T)) KV_ATTRIBUTES ='{"Hbase": {"TimeToLive": 3600, "MaxVersions": 3}}' PARTITION BY KEY(K) PARTITIONS 3;OBKV-HBaseでのデータ挿入をシミュレートします。
実際のデータ挿入プロセスについては、OBKV-HBaseクライアントの使用方法を参照してください。例:
INSERT INTO t1$cf1 VALUES ("row1", "cq1", -truncate(time_to_usec(date_sub(now(), interval +1 hour))/1000, 0), "del"), ("row1", "cq1", -truncate(time_to_usec(now())/1000, 0), "no del"), ("row2", "cq1", -truncate(time_to_usec(date_sub(now(), interval +1 hour))/1000, 0), "del"), ("row2", "cq1", -truncate(time_to_usec(now())/1000, 0), "no del"), ("row3", "cq1", -truncate(time_to_usec(date_sub(now(), interval +1 hour))/1000, 0), "del"), ("row3", "cq1", -truncate(time_to_usec(now())/1000, 0), "no del"), ("row4", "cq1", -truncate(time_to_usec(date_sub(now(), interval +1 hour))/1000, 0), "del"), ("row4", "cq1", -truncate(time_to_usec(now())/1000, 0), "no del");テナントの日次TTLタスク時間を設定し、タスクを自動的にトリガーします。
-- 0時から、TTLタスクを1回試行します ALTER SYSTEM SET kv_ttl_duty_duration = '[00:00:00, 23:59:59]';タスクの実行状態を確認します。
現在のタスクを確認します(実行結果は実際のタスク実行状態によります)。
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 | +------------+----------+-----------+---------+----------------------------+----------------------------+--------------+---------------+-------------+---------------------+----------+------------+ | NULL | -1 | -1 | 1 | 2023-09-28 11:35:02.695292 | 2023-09-28 11:35:17.720627 | PERIODIC | RS_TRIGGERING | 0 | 0 | 0 | OB_SUCCESS | | t1$cf1 | 500002 | 200001 | 1 | 2023-09-28 11:35:06.612708 | 2023-09-28 11:35:06.612708 | PERIODIC | PREPARED | 0 | 0 | 0 | OB_SUCCESS | | t1$cf1 | 500002 | 200002 | 1 | 2023-09-28 11:35:06.612711 | 2023-09-28 11:35:06.612711 | PERIODIC | PREPARED | 0 | 0 | 0 | OB_SUCCESS | | t1$cf1 | 500002 | 200003 | 1 | 2023-09-28 11:35:06.612712 | 2023-09-28 11:35:06.612712 | PERIODIC | PREPARED | 0 | 0 | 0 | OB_SUCCESS | +------------+----------+-----------+---------+----------------------------+----------------------------+--------------+---------------+-------------+---------------------+----------+------------+ 4 rows in set過去のタスクを確認します(実行結果は実際のタスク実行状態によります)。
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 | +------------+----------+-----------+---------+----------------------------+----------------------------+--------------+----------+-------------+---------------------+----------+------------+ | NULL | -1 | -1 | 1 | 2023-09-28 11:35:02.695292 | 2023-09-28 11:35:17.720627 | PERIODIC | FINISHED | 0 | 0 | 0 | OB_SUCCESS | | t1$cf1 | 500002 | 200001 | 1 | 2023-09-28 11:35:06.612708 | 2023-09-28 11:35:11.634029 | PERIODIC | FINISHED | 1 | 0 | 2 | OB_SUCCESS | | t1$cf1 | 500002 | 200002 | 1 | 2023-09-28 11:35:06.612711 | 2023-09-28 11:35:11.632463 | PERIODIC | FINISHED | 1 | 0 | 2 | OB_SUCCESS | | t1$cf1 | 500002 | 200003 | 1 | 2023-09-28 11:35:06.612712 | 2023-09-28 11:35:11.627921 | PERIODIC | FINISHED | 2 | 0 | 4 | OB_SUCCESS | +------------+----------+-----------+---------+----------------------------+----------------------------+--------------+----------+-------------+---------------------+----------+------------+ 4 rows in set
現在のOBKV-HBaseテーブル内のデータを確認します。
obclient> SELECT * FROM t1$cf1;実行結果は次のとおりです:
+------+-----+----------------+--------+ | K | Q | T | V | +------+-----+----------------+--------+ | row3 | cq1 | -1695872081000 | no del | | row4 | cq1 | -1695872081000 | no del | | row1 | cq1 | -1695872081000 | no del | | row2 | cq1 | -1695872081000 | no del | +------+-----+----------------+--------+ 4 rows in set
セルレベル
OBKV-HBaseテーブルt1$cf1を作成し、TTL列を含めます。
CREATE TABLE `t1$cf1` (
`K` VARBINARY(1024) NOT NULL,
`Q` VARBINARY(256) NOT NULL,
`T` BIGINT(20) NOT NULL,
`V` VARBINARY(1024) DEFAULT NULL,
-- セルレベルのTTLを設定します。具体的なパラメータは、put/increment/append/get/scan/delete DML操作実行時に指定し、単位はミリ秒です。
-- TTL列は必ず5列目に作成してください。
`TTL` BIGINT(20) DEFAULT NULL,
PRIMARY KEY (`K`, `Q`, `T`)
);
データ操作の例:
put操作
Put put1 = new Put(key1.getBytes()); put1.addColumn(family.getBytes(), column1.getBytes(), toBytes(11L)); put1.addColumn(family.getBytes(), column2.getBytes(), toBytes(11L)); # このput操作では、各セルのTTLが300ミリ秒に設定されます。これは、それらが300ミリ秒後に期限切れと見なされることを意味します。 # 期限切れデータの削除は、TTLバックグラウンドタスクの実行に依存します。Rowkey TTLタスクが有効でない場合、期限切れデータがダンプされるまで、SQLクエリでこれらの期限切れセルを取得できます。Rowkey TTLタスクが有効な場合、次回のスキャンまでの間は、SQLクエリでこれらのセルのデータを取得できますが、get操作では取得できません。get操作は期限切れのセルを自動的にフィルタリングするためです。 put1.setTTL(300); hTable.put(put1);increment操作
Increment increment = new Increment(key1.getBytes()); increment.addColumn(family.getBytes(), column1.getBytes(), 1L); increment.addColumn(family.getBytes(), column2.getBytes(), 2L); # incrementでTTLが設定されていない場合、incrementによって生成される新しいセルのTTL値は、クエリで取得したセルの値を使用します。 # incrementでTTLが設定されている場合、incrementによって生成される新しいセルのTTL値は、incrementで設定された値を使用します。 # このincrement操作終了後、500ミリ秒以内にクエリを実行すると、新規挿入されたセルが取得できることが期待されます。500ミリ秒後にそのテーブルをクエリすると、取得できないことが期待されます。 increment.setTTL(500); hTable.increment(increment);append操作
Append append = new Append(key1.getBytes()); append.add(family.getBytes(), column1.getBytes(), toBytes(11L)); append.add(family.getBytes(), column2.getBytes(), toBytes(11L)); # increment操作と同じです。 append.setTTL(500); hTable.append(append);get/scan操作
get/scan操作ではTTLの設定はサポートされていませんが、クエリ時には期限切れのセルが自動的にフィルタリングされます。同時に、スキャンされたセルのRowkeyの期限切れ状態が記録されます。Rowkey内に期限切れのセルがある場合、Rowkey TTLがトリガーされ、期限切れのセルが適時にクリーンアップされます。
delete操作
delete操作には
setTTLインターフェースがあります。TTLが設定されたdelete操作を実行すると、エラーが発生します。TTLを設定しない通常のdelete操作では、期限切れになっていない最新バージョンを削除します。最新版が既に期限切れの場合は、2番目のバージョンのセルを削除します。例えば、最新版のセルにTTLが設定されて期限切れになった後、delete操作を実行すると、次のバージョンのセルが削除されます。一部のサンプルコードは以下のとおりです:hTable.put(put1); hTable.put(put2); Delete del = new Delete(key1.getBytes()); del.addColumn(family.getBytes(), column1.getBytes()); hTable.delete(del);delete操作を実行する前のテーブルデータは以下のとおりです:
+------+-----+----------------+--------+--------+ | K | Q | T | V | TTL | +------+-----+----------------+--------+--------+ | key1 | cf1 | -1741157319257 | value | 5 | | key1 | cf1 | -1741157319182 | value | NULL | +------+-----+----------------+--------+--------+ 2 rows in setdelete操作を実行した後のテーブルデータは以下のとおりです:
+------+-----+----------------+--------+--------+ | K | Q | T | V | TTL | +------+-----+----------------+--------+--------+ | key1 | cf1 | -1741157319257 | value | 5 | +------+-----+----------------+--------+--------+ 1 row in setここでは、2番目のバージョンのデータが削除され、期限切れのデータは削除されていないことが確認できます。