Full モード¶
ビューで Full キャッシュモードを使用している場合、そのビューのデータは常に、ソースからではなく、キャッシュデータベースから取得されます。
Partial キャッシュと比較した場合、このモードには、複数の (さらには複数のデータソースからの) ビューを使用する複雑な操作 (結合、和結合、グループ化など) をキャッシュデータベースに委任できるため、これらの操作のパフォーマンスが大幅に向上するという大きな利点があります。
このキャッシュモードでは、特別なクエリ (「キャッシュプリロードクエリ」) を実行して、ビューのキャッシュを充てんする必要があります。このクエリの結果がキャッシュに挿入され、このビューに対するクエリはそのデータに基づいて実行されます。
キャッシュプリロードクエリは、 CONTEXT
句でパラメータ 'cache_preload' = 'true'
を指定している通常のクエリです。次に例を示します。
SELECT *
FROM internet_inc
CONTEXT (
'cache_preload' = 'true'
, 'cache_invalidate' = 'all_rows'
, 'cache_wait_for_load' = 'true'
, 'cache_return_query_results' = 'false')
キャッシュプリロードクエリは、以下の条件を満たす必要があります。
ビューのすべてのフィールドを投影する必要があります (つまり
SELECT * FROM ...
)。集計句または集計関数は使用できません。つまり、
GROUP BY
またはHAVING
は禁止されています。選択条件 (WHERE
句) は使用できます。WHERE
句ではサブクエリを使用できません。Full キャッシュモードが有効なビューに対して実行する必要があります。その基盤となるビューまたはその派生ビューに対してではありません。
キャッシュプリロードクエリは、定期的に実行する必要があります。それには、 Denodo Scheduler Module を使用することが推奨されます。なぜなら、Denodo Scheduler には、キャッシュをプリロードするビューと頻度を選択し、クエリで使用するパラメータを選択できるウィザードが用意されているからです。ロードプロセスの構成方法については、「 VDPCache 抽出セクション 」のセクションを参照してください。
以降のセクションでは、「Full」キャッシュのビューのキャッシュをプリロードする 2 つの方法について説明します。
既存のデータを無効化してキャッシュをロードする。これは、キャッシュをプリロードする最も一般的な方法です。 以下 を参照してください。
キャッシュを増分ロードする。「 キャッシュを増分ロードする 」を参照してください。
既存のデータを無効化してキャッシュをロードする¶
クエリの CONTEXT
句でパラメータ ('cache_preload' = 'true', 'cache_invalidate' = 'all_rows')
を指定している場合、キャッシュエンジンはクエリ対象のビューのキャッシュデータをすべて無効とマークしてから、クエリの結果をキャッシュデータベースに保存します。
たとえば、次のクエリは、キャッシュされている customer
ビューの行をすべて無効化してから、クエリの結果をキャッシュします。
SELECT *
FROM customer
CONTEXT (
'cache_preload' = 'true'
, 'cache_invalidate' = 'all_rows'
, 'cache_wait_for_load' = 'true'
, 'cache_return_query_results' = 'false')
キャッシュを増分ロードする¶
キャッシュ増分更新プロセスにより、データソースからキャッシュに移動する必要のあるデータ量が最小限に抑えられます。ただし、これらは一定の要件を満たした場合のみ適用できます。このセクションでは、利用可能な各種オプションと、それぞれに適用される制限について説明します。
キャッシュを増分更新するには、更新するコンテンツの特定が必要です。以下の 2 つの基準に従ってキャッシュを更新することができます。
時間に基づく増分更新: Denodo Scheduler を使用して、キャッシュが前回更新されてからデータソース内で追加または変更された新しいデータで定期的にキャッシュを更新するジョブを構成できます。これが最も一般的なシナリオです。新しい行や変更された行を特定するには、キャッシュされたビューに、各行の作成日や最終更新日を示す列などの、何らかの日時情報が含まれている必要があります。このオプションは、行が削除されることのないビューでのみ使用できることに注意してください。そうでないと、更新プロセスにより、変更された行が追加または更新されますが、キャッシュには、データソースで削除された行がそのまま含まれます。
コンテンツに基づく増分更新: 変更を時間に基づいて特定することはできなくても、更新するエレメントを他のコンテンツに基づいて特定することができる場合に使用します。たとえば、ある部署が別の住所に移転したとします。その場合、更新対象の部署 ID を指定する WHERE 条件に一致する行を無効にして、クエリの結果をキャッシュデータベースに追加できます。こうした更新は、JMS メッセージを使用して自動的にトリガーできます。
時間に基づく増分キャッシュロード¶
最後のキャッシュロードのタイムスタンプには、変数 '@LAST_REFRESH_DATE'
を使用してアクセスできるため、この変数を WHERE
条件で使用して、挿入する新しいデータを特定できます。たとえば、キャッシュモード「full」のテーブル user
があり、前回のキャッシュプリロード以降に追加された新しいレコードを追加するために、このビューにキャッシュされたデータを更新する必要があるとします。以下のクエリは、前回のキャッシュ更新以降に追加されたユーザーのみを元のデータソースから読み取り、キャッシュにあるユーザーのみを挿入します。
SELECT * FROM user WHERE start_date >= '@LAST_REFRESH_DATE' CONTEXT ( 'cache_preload' = 'true' , 'cache_wait_for_load' = 'true' , 'cache_return_query_results' = 'false')
このオプションは、新しいデータを挿入するだけです。既存のキャッシュされたデータの更新や削除は行いません。
コンテンツに基づく増分キャッシュロード¶
時間に基づく増分ロードは不可能でも、複数のクエリを実行してキャッシュを読み込む必要がある場合があります。たとえば、初回のキャッシュの読み込みは、1 回のクエリで実行するとソースに負荷がかかりすぎます。クエリの CONTEXT
句にパラメータ ('cache_preload' = 'true')
を追加することで ('cache_invalidate'
は追加しない)、現在のキャッシュデータを無効化せずに、クエリの結果がキャッシュデータベースに保存されます。このパラメータを使用して複数のクエリを実行すれば、キャッシュを増分ロードできます。
このパラメータを追加することは、ビューの [Execute] ダイアログからビューを実行して、[Store results in cache] チェックボックスをチェックし、[Invalidate existing results] チェックボックスのチェックを外すのと同じことです。このパラメータを追加するときには、キャッシュの増分ロードに使用するクエリの結果が重複しないことを確認します。たとえば、次のクエリを実行したとします。
SELECT *
FROM phone_inc
WHERE pinc_id > 0
CONTEXT (
'cache_preload' = 'true'
, 'cache_wait_for_load' = 'true'
, 'cache_return_query_results' = 'false')
さらに次のクエリを実行します。
SELECT *
FROM phone_inc
WHERE pinc_id > -1
CONTEXT (
'cache_preload' = 'true'
, 'cache_wait_for_load' = 'true'
, 'cache_return_query_results' = 'false')
キャッシュには、両方のクエリから返されたデータが保存されます。ここで SELECT * FROM phone_inc
というクエリを実行した場合、結果は両方のクエリの和結合になり、その中には同じ行が 2 回含まれることになります。
既存のキャッシュデータを更新する増分キャッシュロード¶
元のデータが挿入とは別に更新される可能性があり、ビューにプライマリキーが定義されている場合は、 CONTEXT
句でパラメータ ('cache_preload' = 'true', 'cache_invalidate' = 'matching_pk')
を使用できます。この場合、キャッシュエンジンはすでにキャッシュされた行を更新し、まだキャッシュに存在しない新しい行をキャッシュします。キャッシュエンジンは、ビューのプライマリキーを使用して、行がすでにキャッシュされているかどうかを判断します。キャッシュの行とソースの行は、プライマリキーの値が同じであれば同一と見なされます。これらのパラメータをクエリに追加するのは、ビューの [Execute] ダイアログからビューを実行して、[Store results in cache] と [Replace rows with same PK value] チェックボックスを選択するのと同じことです。
たとえば、前述の例のテーブル user
が、追加とは別に更新される可能性があり、その中に、最後の更新日を特定するための modification_date 列が含まれているとします。その場合、以下のクエリで、キャッシュされたデータを更新できます。
SELECT * FROM user WHERE modification_date >= '@LAST_REFRESH_DATE' CONTEXT ( 'cache_preload' = 'true' , 'cache_invalidate' = 'matching_pk' , 'cache_wait_for_load' = 'true' , 'cache_return_query_results' = 'false')
このクエリは、変更日が最後のキャッシュプリロードよりも遅いユーザーのみを読み取り、パラメータ 'cache_invalidate' = 'matching_pk'
があるため、キャッシュエンジンはプライマリキーがすでにキャッシュテーブルに存在する行を更新し、ソースから取得した新しいユーザーをキャッシュします。
このキャッシュロード方法をサポートするには、ビューは以下の要件を満たす必要があります。
キャッシュビューに定義されたプライマリキー。
この機能をサポートするキャッシュデータソース。パラメータ
'cache_invalidate' = 'matching_pk'
をサポートするデータソースのリストを取得するには、「 マージデータをサポートするデータソース 」のセクションを参照してください。ソースでデータから行を削除することはできません。実行できるのは、行の追加または更新だけです。ソースで行が削除された場合、このビューのキャッシュを無効化して再度キャッシュしない限り、ビューは削除された行を返します。多くの場合はこの要件が満たされています。なぜなら、行は、実際に削除されるのではなく、削除済みまたは無効とマークされるからです。
上記の例のように条件を含める場合、Virtual DataPort は、各行が追加または更新された日時を示すフィールドに対する条件をソースにプッシュダウンできる 必要があります 。
ビューにプライマリキーが含まれていない場合、あるいはキャッシュデータソースが前述の機能をサポートしていない場合、オプション 'cache_invalidate' = 'matching_rows' を使用できます。パラメータ ('cache_preload' = 'true', 'cache_invalidate' = 'matching_rows')
を追加すると、キャッシュエンジンは、キャッシュされた行の中でクエリの WHERE
句に一致するものを無効化してから、クエリの結果をキャッシュします。これらのパラメータをクエリに追加することは、ビューの [Execute] ダイアログからビューを実行して、[Store results in cache] と [Invalidate existing results] の各チェックボックスをチェックすることに相当します。
たとえば、 order
というテーブルがあり、そのキャッシュモードが Full である場合に、このビューのキャッシュデータを更新して今年の最新レコードをキャッシュする必要があるとします。ただし、昨年以前のキャッシュデータは無効化したくありません。なぜなら、それらは変更されていない上に、すべてのデータを再取得するのは時間がかかりすぎるからです。これを実現するには、次のクエリを使用します。このクエリは日付が今年である注文のみを返します。また、パラメータ 'cache_invalidate' = 'matching_rows'
を指定しているので、キャッシュエンジンはクエリの条件に一致する行のみを無効化して、ソースから取得したデータをキャッシュします。
SELECT *
FROM order
WHERE order_date >= TRUNC( CURRENT_DATE(), 'Y')
CONTEXT (
'cache_preload' = 'true'
, 'cache_invalidate' = 'matching_rows'
, 'cache_wait_for_load' = 'true'
, 'cache_return_query_results' = 'false')
このオプションは、キャッシュデータソースが UPDATE ステートメントをサポートする場合のみ指定可能であることに注意してください。一般に、Hive、Impala、Spark、Athena、Presto などの Parquet ファイルに基づくストレージシステムを使用したキャッシュデータベースは、UPDATE ステートメントをサポートしません。ただし、Kudu や Spark Databricks を使用する Impala など、いくつかの例外があります。元のデータに更新が含まれていても、データソースが UPDATE ステートメントをサポートしない場合、オプション 'cache_invalidate' = 'all_rows' を使用して、すべてのデータを更新する必要があります。
実行時の Full キャッシュモード¶
Full キャッシュが有効なビューに対してクエリを実行すると、キャッシュプリロードクエリが実行されていなくても、データは常にキャッシュから取得されます。ビューのキャッシュがプリロードされていない場合、このビューに対するクエリでは 0 行が返されます。
パフォーマンスの観点から見ると、Full キャッシュモードを使用する主な利点は、Full キャッシュが有効な 2 つのビューを結合する場合にクエリがキャッシュに委任されることです。これにより実行時間が短縮される場合があります。Partial キャッシュモードを使用する場合、このような最適化は利用できません。
たとえば、異なるデータソースからデータを取得する 2 つのビューで Full キャッシュモードを有効にして、それらの間で結合を実行した場合、結合はサーバーで実行されるのではなく、キャッシュデータベースに委任されます。
重要
このキャッシュモードが有効な場合、キャッシュエンジンはキャッシュプリロードクエリを確認 しません 。たとえば、次のクエリでビューがロードされたとします。
SELECT *
FROM employee WHERE id = 1
CONTEXT ('cache_preload' = 'true', 'cache_invalidate' = 'all_rows')
その後、次のクエリを実行します。
SELECT *
FROM employee
この場合、データはキャッシュから取得されます。つまり、 id = 1
という条件に一致する行のみが取得されます。
クエリでパラメータ 'cache_preload' = 'true'
が指定されている場合、キャッシュエンジンは以下の処理を実行します。
このビューのキャッシュデータを保存する予定のテーブルが存在することを確認します。さらに、そのテーブルに適切なスキーマが存在することも確認します。このテーブルは、Full キャッシュモードまたは Partial キャッシュモードを有効にしたときに作成されます。
クエリに
@LAST_REFRESH_DATE
変数が含まれる場合、Denodo ではその変数を置換し、最後のキャッシュロードに対応するタイムスタンプを使用します。キャッシュエンジンは、Denodo に行を転送せずにキャッシュデータソースで操作を実行できるかどうかを確認します。「キャッシュプリロードクエリ」は、以下の条件を満たす必要があります。
データが単一の JDBC データソースから取得される。
キャッシュエンジンが、このデータソースを使用するように構成されている。
クエリ全体が同じデータベースに委任されている。
このデータベースが
INSERT INTO SELECT
ステートメントをサポートしている。
上記のすべての条件が満たされている場合、キャッシュエンジンは、
INSERT INTO ... SELECT ...
ステートメントを実行し、クエリの結果を直接、データベース内でキャッシュエンジンが使用するスキーマの適切なテーブルに保存します。この場合、このデータはデータベースから Denodo に送信されたり、同じデータベースに返されたりすることはありません。また、Denodo がデータを処理する必要もありません。クエリの読み込みにパラメータ
'cache_invalidate' = 'matching_pk'
が含まれていた場合、キャッシュエンジンは、代わりに MERGE コマンドをデータソースに送信します。この状態では、クライアントアプリケーション (Administration Tool、Design Studio など) は、キャッシュテーブルに挿入された行を受け取りません。Virtual DataPort もこれらの行を受け取らないからです。Virtual DataPort は、
MERGE INTO <cache table> SELECT...
ステートメントを実行し、Denodo を介することなくキャッシュテーブルに直接データを保存します。挿入された行をクライアントアプリケーションで受け取る必要がある場合、クエリの CONTEXT 句にパラメータ'cache_return_query_results' = 'true'
を追加します。このパラメータを使用すると、この最適化が無効になるため、クエリの実行速度が低下します。手順 3 の条件を 満たさず 、クエリの読み込みに
'cache_invalidate' = 'matching_pk'
オプションが含まれている場合、キャッシュエンジンは以下の手順を実行します。クエリで指定された WHERE 条件を使用して、ソースをクエリします。
キャッシュデータソースに一時テーブルを作成し、前のクエリの結果を挿入します。
ソースに対して MERGE コマンドを実行し、この一時テーブル内のデータをキャッシュにマージします (UPSERT とも呼ばれます)。
一時テーブルを削除します。
キャッシュに直接ではなく一時テーブルに行を挿入しているため、挿入中に何らかの不具合が生じた場合は、MERGE コマンドの前に操作が中断され、整合性のないデータがキャッシュに残ることはありません。VDP が @LAST_REFRESH_DATE
の値を更新するのは、操作が成功した後だけです。つまり、 @LAST_REFRESH_DATE
パラメータの値が、最後にキャッシュロードに成功した日になります。データの読み取りや書き込みでキャッシュロードに失敗した場合、VDP は @LAST_REFRESH_DATE
パラメータの値を更新しません。
手順 3 の条件が 満たされず 、クエリの読み込みに
'cache_invalidate' = 'matching_pk'
パラメータが含まれない場合は、以下のようになります。クエリが行を返し始めると同時に、キャッシュエンジンはビューのキャッシュテーブルに行を挿入し始め、状態を「処理中」にします。
キャッシュテーブルにすべての行を挿入し終わると、キャッシュデータベースに対するトランザクションを開始します。このトランザクションで、キャッシュエンジンは、1 つまたは 2 つのクエリを次の順序で実行します。
クエリでパラメータ
'cache_invalidate'
が指定されている場合、UPDATE ステートメントを実行して行のステータスを「有効」から「無効」に変更します。クエリで
'cache_invalidate' = 'all_rows'
が指定されている場合、すべての「有効」な行のステータスは「無効」に切り替わります。クエリで
'cache_invalidate' = 'matching_rows'
が指定されている場合、クエリの WHERE 条件に一致する「有効」な行のステータスは「無効」に切り替わります。クエリに WHERE 句が存在しない場合、matching_rows
はall_rows
と等価です。「処理中」の行を「有効」に変更する UPDATE ステートメントを実行します。
トランザクションをコミットします。この後にこのビューをヒットするクエリは、この新しいデータを取得します。
このプロセスにより、Full キャッシュモードを使用するビューをヒットしたクエリは、ビューのキャッシュのロード中に別のクエリがビューをヒットした場合でも、確実に有効なデータを返すようになります。
データをキャッシュテーブルに挿入している間にクエリがビューをヒットした場合、返されるデータは有効です。なぜなら、キャッシュエンジンは常にステータスが「有効」な行を返すからです。それまでに挿入された行のステータスは「処理中」であり、「有効」ではありません。
行のステータスが「処理中」から「有効」に切り替わる間にクエリがビューをヒットした場合、返されるデータは有効です。なぜなら、この UPDATE はトランザクション内で実行されるからです。したがって、このクエリは依然として「古い」行を返しますが、部分的に変更された行を返すことはありません。
cache_wait_for_load
が false
である場合、結果のすべての行がクライアントに返されると、たとえデータが完全にはキャッシュデータベースに挿入されていなくても、すぐにクライアントはクエリ完了通知を受け取ります。 cache_wait_for_load
が true
であるか、存在しない場合は、上記のすべての手順が完了した後にクエリ完了通知を受け取ります。