TDVの増分更新キャッシュ(INSERTのみ)の利用方法について説明します。
本手順で利用する外部キャッシュデータベースのDBエンジンは Oracle 19c です。
キャッシュターゲット
TDVではキャッシュターゲットとして大きく分けて以下の3通りを選択できます。
キャッシュターゲット | 説明 |
---|---|
デフォルトキャッシュデータベース | TDVインストール時に自動で構築されるデフォルトのキャッシュデータベースにキャッシュデータを保存する方式です。 DBエンジンはPostgreSQLです。 ただし、パフォーマンスチューニングの余地がほとんどなく、TDV ServerをActive Cluster構成にしても各TDV Serverのデフォルトキャッシュデータベースはクラスタ構成とはならず大規模ユースケースに不向きであることから、商用環境での利用は推奨されていません。 |
外部キャッシュデータベース | 利用者が用意した任意のデータベースにキャッシュデータを保存する方式です。 |
ファイル | データベースではなくファイルにキャッシュデータを保存する方式です。 主に設計・開発時の利用を想定しており、商用環境での利用は推奨されていません。 |
本記事では、「外部キャッシュデータベース」を利用する方式について説明します。
更新モード
TDVではキャッシュの更新モードとしては以下が提供されています。
キャッシュターゲット | 説明 |
---|---|
完全更新モード | 「完全更新モード」でキャッシュを利用します。 キャッシュリフレッシュのたびにキャッシュテーブル内のデータはすべて置換されます。 最も簡単なアプローチです。 |
増分更新モード | キャッシュ更新アクションが開始されると、変更されたデータのみが取得され、キャッシュで更新されます。 |
本記事では、「増分更新モード」を利用する方式について説明します。
増分更新キャッシュの制約
増分更新モードはTDVの仕様により単一テーブルモードでしか利用できません。
したがって、以下の場合には利用できないことにご注意ください。
- デフォルトキャッシュデータベースを利用する場合
- 複数テーブルモードのみがサポートされているため
- 外部キャッシュデータベースを複数テーブルモードで利用する場合
検証環境
PostgreSQLをデータソースするビューorderDetails
にキャッシュ設定を行います。
データソース
データソースとして外部のPostgreSQLデータベースに存在する以下3種類のテーブルをdemo_postgres
としてTDVに追加します。
- orders
- products
- stores
orders
products
stores
orderDetailsビュー
キャッシュターゲットデータソース追加
キャッシュターゲットとして利用する外部データベースをデータソースとして追加します。
実際にデータがロードされるテーブルは、後続の操作の過程でTDVにより作成されるため、この「キャッシュターゲットデータソース追加」の目的は、データロード先となるテーブルを所有するスキーマをTDVとして認識することです。
したがって、キャッシュデータを外部データベースのどのスキーマに格納していきたいかは事前に決めておく必要があります。また、そのスキーマも事前に作成しておく必要があります。
以下の例では、EXTERNAL_DB_TARGET_SINGLE_TABLE_INSERTONLY
というスキーマのメタデータを取り込んでいます。
イントロスペクト時の注意点として、取り込みたいスキーマにテーブルを1件も存在しない場合は、イントロスペクトの対象とならないため、イントロスペクト時には最低1件以上のテーブルがそのスキーマに存在している必要があります。
キャッシュのステータステーブルおよび追跡テーブルの作成
先ほど追加した、キャッシュターゲットとして利用する外部データベースをデータソースに、キャッシュのステータステーブルと追跡テーブルを以下の手順で作成します。
ステータステーブル
1. キャッシュターゲットデータソースを開き、ステータステーブル欄右の 参照… ボタンをクリックします。
2. 次のキャッシュテーブルを選択 ステータステーブルウィンドウが表示されるので、ステータステーブル作成先のスキーマを選択します。
スキーマを選択すると、テーブル名cache_status
が自動で入力されていることを確認し、作成ボタンをクリックします。
3. 作成ボタンをクリックすると、次のDDL: ステータステーブルというウィンドウにSQLコマンドが表示されるので、実行をクリックします。
4. ステータステーブルが正常に作成され、「DDLは正常に実行されました」と表示されることを確認します。
追跡テーブル
次に、追跡テーブルもステータステーブルと同様の手順で作成します。
1. 追跡テーブル欄右の参照…ボタンをクリックします。
2. 次のキャッシュテーブルを選択 追跡ステーブルウィンドウが表示されるので、追跡ステーブル作成先のスキーマを選択します。
スキーマを選択すると、テーブル名cache_tracking
が自動で入力されていることを確認し、作成ボタンをクリックします。
3. 作成ボタンをクリックすると、次のDDL: 追跡ステーブルというウィンドウにSQLコマンドが表示されるので、実行をクリックします。
4. 追跡テーブルが正常に作成され、「DDLは正常に実行されました」と表示されることを確認します。
この時点で、TDVのリソースツリー上でも、ステータステーブルと追跡テーブルが作成されたことを確認できます。
キャッシュの有効化
以下の手順でキャッシュを有効化します。
1. orderDetails
ビューを開き、キャッシュタブにてキャッシュの作成ボタンをクリックします。
2. 以下のとおり設定し、キャッシュのテーブルの結果フィールド右端の参照ボタンをクリックします。
- ステータスの有効に✓を入れる
- ストレージのデフォルトのキャッシュデータベースを使用の✓を外し、単一テーブルを選択する
- ストレージのデータソースにキャッシュターゲットとして利用するデータソースを指定する
- 詳細の完全更新モードを選択したままとする(注:下図には表示されていません)
- 後ほど増分更新モードに変更します
本記事では、単一テーブルを利用します。
3. 次のキャッシュテーブルを選択 resultウィンドウが表示されるので、キャッシュテーブル作成先スキーマを選択した状態で任意のキャッシュテーブル名を入力し、作成ボタンをクリックします。
4. 作成ボタンをクリックすると、DDL: resultというウィンドウにSQLコマンドが表示されますので実行をクリックします。
5. テーブルが正常に作成され、「DDLは正常に実行されました」と表示されることを確認します。
6. ビューを保存すると、ステータスが NOT LOADED となることを確認します。
これは、まだ外部キャッシュデータベースにデータがロードされていないことを意味しています。
この時点で、リソースツリー上のビューにキャッシュが有効化されたことを示すアイコンがつきます。
自動生成されたキャッシュテーブルも確認することができます。
キャッシュ初期化スクリプト作成
キャッシュを初期化するためのスクリプトを以下の手順で作成します。
1. 任意の場所(フォルダ)を右クリックし、新規 > 新しいSQLスクリプトをクリックします。
2. 任意の名前を付けます。
3. 以下のようなスクリプトを記述します。
PROCEDURE InitialCache(OUT IncrementalMaintenanceLevel VARCHAR)
BEGIN
DECLARE cacheKey BIGINT;
DECLARE maxOrderID BIGINT;
-- Log beginning of script execution
CALL /lib/debug/Log('Starting script InitialCache');
-- Retrieve cache key from request environment
CALL /lib/util/GetEnvironment('System.CACHED_RESOURCE_CACHE_KEY', cacheKey);
CALL /lib/debug/Log('cachedResourceCacheKey = ' || cacheKey);
-- Determine initial incremental maintenance level (which we have defined as highest order ID)
-- Get the highest row on the view, based on the field used for incremental caching
SELECT { option no_data_cache }
MAX(id)
INTO maxOrderID
FROM /shared/cache_demo/external_db_target_single_table_insertonly/"view"/L2_Business/orderDetails;
-- If the highest order ID is null (view is empty) use 0 instead
SET maxOrderID = COALESCE(maxOrderID, 0);
-- Load cache target table
INSERT INTO /shared/cache_demo/external_db_target_single_table_insertonly/cache_target/"oracle-19c"/EXTERNAL_DB_TARGET_SINGLE_TABLE_INSERTONLY/orderDetails
SELECT { option disable_data_cache }
cacheKey,
S.*
FROM /shared/cache_demo/external_db_target_single_table_insertonly/"view"/L2_Business/orderDetails S
WHERE id <= maxOrderID;
-- Return incremental maintenance level
SET IncrementalMaintenanceLevel = CAST(maxOrderID AS VARCHAR);
-- Log completion of script execution
CALL /lib/debug/Log('Completion of script InitialCache');
END
4. 保存し、スクリプトにエラーが発生していないことを確認します。
キャッシュ更新スクリプト作成
キャッシュを更新するためのスクリプトを以下の手順で作成します。
1. キャッシュ初期化スクリプトと同様に任意のフォルダに新しいスクリプトを作成し、以下のようなスクリプトを記述します。
PROCEDURE DeltaLoader(OUT IncrementalMaintenanceLevel VARCHAR)
BEGIN
DECLARE cacheKey BIGINT;
DECLARE maxOrderID BIGINT;
-- Log beginning of script execution
CALL /lib/debug/Log('Starting script InitialCache');
-- Retrieve cache key from request environment
CALL /lib/util/GetEnvironment('System.CACHED_RESOURCE_CACHE_KEY', cacheKey);
CALL /lib/debug/Log('cachedResourceCacheKey = ' || cacheKey);
-- Retrieve incremental maintenance level from request environment
CALL /lib/util/GetEnvironment('System.CACHED_RESOURCE_INCREMENTAL_MAINTENANCE_LEVEL', IncrementalMaintenanceLevel);
CALL /lib/debug/Log('cached ResourceIncrementalMaintenanceLevel after execution in DeltaLoader script = ' || IncrementalMaintenanceLevel);
-- Determine next level
SELECT { option no_data_cache }
MAX(id)
INTO maxOrderID
FROM /shared/cache_demo/external_db_target_single_table_insertonly/"view"/L2_Business/orderDetails;
-- Refresh cache target table
INSERT INTO /shared/cache_demo/external_db_target_single_table_insertonly/cache_target/"oracle-19c"/EXTERNAL_DB_TARGET_SINGLE_TABLE_INSERTONLY/orderDetails
SELECT { option disable_data_cache }
cacheKey,
S.*
FROM /shared/cache_demo/external_db_target_single_table_insertonly/"view"/L2_Business/orderDetails S
WHERE id > CAST(IncrementalMaintenanceLevel AS BIGINT) AND id <= maxOrderID;
-- Update incremental maintenance level
SET IncrementalMaintenanceLevel = CAST(maxOrderID AS VARCHAR);
CALL /lib/debug/Log('IncrementalMaintenanceLevel for successful run of DeltaLoader script = ' || IncrementalMaintenanceLevel);
--Catch and handle all exception
EXCEPTION
ELSE
-- Log the exception
CALL /lib/debug/Log('Exception raised in DeltaLoader script');
CALL /lib/debug/Log('Exception is : ' || CURRENT_EXCEPTION.NAME || ' : ' || CURRENT_EXCEPTION.MESSAGE);
-- Don't advance the incremental meintenance level on a failure, just return previous value
CALL /lib/util/GetEnvironment('System.CACHED_RESOURCE_INCREMENTAL_MAINTENANCE_LEVEL', IncrementalMaintenanceLevel);
CALL /lib/debug/Log('IncrementalMaintenanceLevel after exception in DeltaLoader script = ' || IncrementalMaintenanceLevel);
END
2. 保存し、スクリプトにエラーが発生していないことを確認します。
増分更新モード設定・キャッシュの初回ロード
orderDetails
ビューに対して増分更新モードの設定およびキャッシュの初回ロードを以下の手順で実施します。
1. ビューのキャッシュ設定を開いて以下の通り設定し一度ビューを保存します。
- 詳細にて増分更新モードを選択
- 次を使用してキャッシュを初期化で作成した「キャッシュ初期化スクリプト」を指定
- 次を使用してキャッシュを更新で作成した「キャッシュ更新スクリプト」を指定
2. 保存後のビューにエラーが発生していないことを確認し、更新モードの今すぐ更新ボタンをクリックしてキャッシュを初期化します。
3. ダイアログが表示されるのでOKボタンをクリックします。
4. 正常にキャッシュがリフレッシュされ、ステータスが UP となっていることを確認します。
キャッシュ初期化スクリプトのログは [TDVインストールフォルダ]\logs\cs_server.log
にて以下のように確認できます。
INFO [Cache Refresh for /shared/cache_demo/external_db_target_single_table_insertonly/view/L2_Business/orderDetails] 2022-01-01 01:01:24.544 +0900 LogProcedure - Starting script InitialCache
INFO [Cache Refresh for /shared/cache_demo/external_db_target_single_table_insertonly/view/L2_Business/orderDetails] 2022-01-01 01:01:24.544 +0900 LogProcedure - cachedResourceCacheKey = 1002
INFO [Cache Refresh for /shared/cache_demo/external_db_target_single_table_insertonly/view/L2_Business/orderDetails] 2022-01-01 01:01:24.589 +0900 LogProcedure - Completion of script InitialCache
5. ビューを実行し、これまでと同じようにデータが取得できることを確認します。
以降はorderDetails
ビューに対してクエリを実行すると、以下の実行計画が示す通り、デフォルトキャッシュデータベースからデータが取得されるようになり、実際のデータソースであるdemo_postgres
データソースに対してクエリが実行されることはありません。
demo_postgres
データソースに対してクエリが実行されるのは、キャッシュをリフレッシュするときのみとなります。
また、リネージュは以下のようになります。
キャッシュのリフレッシュ - INSERT
データソース(PostgreSQL)に新規レコードが追加された後に、キャッシュをリフレッシュし、デフォルトキャッシュテーブル内のデータにもレコード追加が反映されることを確認します。
データソースに新規レコードを追加する前の状態が、データソース にて示した状態であることを前提とします。
データソースのorders
テーブルには新規レコードを以下のように追加します。
しかし、この時点でorderDetails
ビューを実行しても以下のとおりレコード追加は反映されていません。
キャッシュを最新化するために、以下の手順でキャッシュテーブルに対してキャッシュをリフレッシュします。
1. 「更新モード」の「今すぐ更新」ボタンをクリックし、キャッシュをリフレッシュします。
2. ダイアログが表示されるので「OK」ボタンをクリックします。
3. 正常にキャッシュがリフレッシュされ、ステータスが UP となっていることを確認します。
キャッシュ初期化スクリプトのログは [TDVインストールフォルダ]\logs\cs_server.log
にて以下のように確認できます。
INFO [Cache Refresh for /shared/cache_demo/external_db_target_single_table_insertonly/view/L2_Business/orderDetails] 2022-01-01 01:03:28.420 +0900 LogProcedure - Starting script DeltaLoader
INFO [Cache Refresh for /shared/cache_demo/external_db_target_single_table_insertonly/view/L2_Business/orderDetails] 2022-01-01 01:03:28.421 +0900 LogProcedure - cachedResourceCacheKey = 1002
INFO [Cache Refresh for /shared/cache_demo/external_db_target_single_table_insertonly/view/L2_Business/orderDetails] 2022-01-01 01:03:28.422 +0900 LogProcedure - cached ResourceIncrementalMaintenanceLevel after execution in DeltaLoader script = 10
INFO [Cache Refresh for /shared/cache_demo/external_db_target_single_table_insertonly/view/L2_Business/orderDetails] 2022-01-01 01:03:28.663 +0900 LogProcedure - IncrementalMaintenanceLevel for successful run of DeltaLoader script = 12
4. 再度、orderDetails ビューを実行し、レコード追加が反映されていることを確認します。
キャッシュ更新用スクリプト実行が失敗した場合の挙動について
更新用プロシージャにエラーが発生しているなどといった理由により、キャッシュ更新用スクリプトの実行が失敗した場合、以下のような動きとなります。
- (キャッシュ初期化が成功した結果)キャッシュが「UP」の状態から、キャッシュ更新を行った結果、キャッシュ更新用スクリプト実行がエラーのためキャッシュのステータスが「STALE」となる(status = F となる)
- 次にキャッシュ更新を行うと、キャッシュが「STALE」であるため(前回のキャッシュ更新の結果が status = F であるため)、キャッシュ初期化用スクリプトがコールされる
- 初期化用スクリプトが成功した場合:
- cachekeyをキーに、前世代の有効データ、及び更新用スクリプトのデータがDELETEされる
- ステータス「UP」となるが、次回更新時までにキャッシュ更新スクリプトのエラーを解消しない限り、また2の動きを繰り返す
- (何らかの理由で)初期化用スクリプトが(も)失敗した場合:
- cachekeyをキーに、更新用スクリプトのデータがDELETEされる
- 上図の cache_statusテーブル内の status= F のレコードのみが削除される
- ステータスは引き続き「STALE」のままで、次回更新時はまた2の動きを繰り返す
- cachekeyをキーに、更新用スクリプトのデータがDELETEされる
- 初期化用スクリプトが成功した場合:
上記の動きからもわかるように、キャッシュのステータスが「STALE」となった場合に、次の更新タイミングにおいて、キャッシュ更新処理ではなく、キャッシュ初期化処理が実行されることに注意する必要があります。