この章では、データ・ウェアハウス内で表とマテリアライズド・ビューへの変更を同期させる方法について説明します。この方法は、表とマテリアライズド・ビューに対する更新の同期に基づいており、同期リフレッシュと呼ばれます。
この章の内容は次のとおりです。
同期リフレッシュは、Oracle Database 12cリリース1で導入されたリフレッシュ方法で、表一式とそこで定義されたマテリアライズド・ビューが常に同期した状態を維持できるようにします。ここでは、増分データのロードが厳密に制御され、定期的に発生するデータ・ウェアハウスには非常に適しています。
ほとんどのデータ・ウェアハウスでは、ファクト表は時間ディメンションに沿ってパーティション化され、通常増分データ・ロードは主に最近の期間に対する変更で構成されます。同期リフレッシュはこのような特性を利用し、リフレッシュのパフォーマンスおよびスループットを大幅に向上させます。これにより、計画済問合せと非定型問合せの両方において、問合せパフォーマンスが高速になります。これはデータ・ウェアハウスを成功させるために重要なことです。
この項では、同期リフレッシュの主要な要件と基本的な概念について説明します。内容は次のとおりです。
同期リフレッシュはデータ・ウェアハウスにおける表とマテリアライズド・ビューの新しい管理方法で、これによって表とマテリアライズド・ビューが同時にリフレッシュされます。従来のリフレッシュ方法の場合、変更は実表に適用され、マテリアライズド・ビューは次のいずれかのリフレッシュ方法で別個にリフレッシュされます。
マテリアライズド・ビューのログが使用できる場合、これを使用したログベースの増分(高速)リフレッシュ
PCTリフレッシュ(使用可能な場合)
完全リフレッシュ
同期リフレッシュは、ログベースの増分(高速)リフレッシュとPCTリフレッシュの手法のいくつかの要素を組み合せたものですが、これら2つの方法とは異なり、ON DEMANDマテリアライズド・ビューに対してのみ適用可能です。同期リフレッシュと他のリフレッシュ方法には、主に次の3つの相違点があります。
同期リフレッシュでは、表とマテリアライズド・ビューの登録が必要です。
同期リフレッシュでは、以前指定したルールに従ってデータへの変更を指定する必要があります。
同期リフレッシュは、リフレッシュ操作を準備と実行の2つのステップに分割して機能します。このアプローチにより、他の方法に比べ、パフォーマンスが優れている、詳細に制御できるなどの重要な利点が得られます。
同期リフレッシュAPIは、DBMS_SYNC_REFRESHという新しいパッケージで定義されています。このパッケージの詳細は、『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照してください。
同期リフレッシュでは、データ・ウェアハウスでマテリアライズド・ビューをリフレッシュするために使用される従来のタイプのリフレッシュ方法に対し、次のような利点があります。
実表への変更のロードと、それ自体独立したマテリアライズド・ビューの非常に効果的なリフレッシュを連携させます。
オプティマイザがクエリーをリライトするためにマテリアライズド・ビューを使用できない時間を減らします。
これは、データ・ウェアハウスで一般的に使用されるマテリアライズド・ビューの幅広いクラス(マテリアライズド集計ビューおよびマテリアライズド結合ビュー)に適しています。ファクト表と同様にマテリアライズド・ビューをパーティション化する必要があります。マテリアライズド・ビューが現在パーティション化されていない場合は、同期リフレッシュを利用できるように効果的にパーティション化できます。
パーティション化およびデータ・ウェアハウスのロード・サイクルの性質を十分に活用して、リフレッシュ・プロシージャを通してマテリアライズド・ビューと実表間の同期を保証します。
一般的なデータ・ウェアハウスでは、データの準備として、1つ以上のソースからのデータの抽出、クレンジング、整合性のためのフォーマットおよびデータ・ウェアハウス・スキーマへの変換があります。データの準備領域はステージング領域と呼ばれ、データ・ウェアハウスの実表がステージング領域の表からロードされます。同期リフレッシュ方法では、変更データをステージング・ログにロードできるため、この方法はこのモデルに適しています。
ステージング・ログは、従来の高速リフレッシュ方法のマテリアライズド・ビュー・ログと同じ役割を果たします。ただし、重要な相違点が1つあります。従来の高速リフレッシュ方法では、まず実表が更新され、その後変更がマテリアライズド・ビュー・ログからマテリアライズド・ビューに適用されます。ところが同期リフレッシュ方法では、ステージング・ログからの変更がマテリアライズド・ビューのリフレッシュに適用される一方、実表にもこれが適用されます。
データ・ウェアハウス内のほとんどのマテリアライズド・ビューは通常、ファクト表およびディメンション表が外部キーと主キーの関係で結合されているスター・スキーマまたはスノーフレーク・スキーマを採用します。同期リフレッシュ方法では、ファクト表にのみ行が追加されるものから、ファクト表とディメンション表への無作為な変更まで、考えられるすべての変更データ・ロード・シナリオにおいて、両方のスキーマを処理できます。
ステージング・ログに変更ロード・データを指定するかわりに、影響を受けるパーティションと交換するデータを含む外部表の形式で変更データを直接実表に指定することもできます。この機能は、DBMS_SYNC_REFRESHパッケージのREGISTER_PARTITION_OPERATIONプロシージャによって提供されます。
同期リフレッシュを実際に実行する前に、該当する表とマテリアライズド・ビューを登録する必要があります。同期リフレッシュでは、表とマテリアライズド・ビューを登録するため、次の方法を提供しています。
表は、そこにステージング・ログを作成することによって、同期リフレッシュに登録されます。ステージング・ログは、CREATE MATERIALIZED VIEW LOG文を使用して作成されます。この構文は、従来の増分リフレッシュに使用されるなじみのあるマテリアライズド・ビュー・ログに加え、ステージング・ログも作成するよう、このリリースで拡張されました。表にステージング・ログを作成すると、同期リフレッシュに登録されたと見なされ、同期リフレッシュ・プロシージャによってのみ変更可能となります。言い換えると、ステージング・ログが定義されている表は同期リフレッシュに登録され、ユーザーが直接変更することはできません。
CREATE MATERIALIZED VIEW LOG文の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。
マテリアライズド・ビューは、DBMS_SYNC_REFRESHパッケージのREGISTER_MVIEWSプロシージャを使用して同期リフレッシュに登録されます。REGISTER_MVIEWSプロシージャは、暗黙的に同期リフレッシュ・グループと呼ばれる関連オブジェクトのグループを作成します。同期リフレッシュ・グループは、互いに依存しているため単一のエンティティとして一緒にリフレッシュする必要のあるすべての関連マテリアライズド・ビューおよび表で構成されます。
DBMS_SYNC_REFRESHパッケージの詳細は、『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照してください。
他のリフレッシュ方法の場合、マテリアライズド・ビューの実表を直接変更でき、変更データの指定の問題は生じません。しかし同期リフレッシュでは、以前指定した特定のルールに従い、DBMS_SYNC_REFRESHパッケージにより提供されるAPIを使用して、変更データを指定および準備する必要があります。
変更データを指定するには、次の2つの方法があります。
外部表に変更データを指定し、これをREGISTER_PARTITION_OPERATIONプロシージャに登録します。
詳細は、同期リフレッシュの変更データの取得時におけるパーティション操作の使用を参照してください。
ステージング・ログに変更データを指定し、これらをPREPARE_STAGING_LOGプロシージャで処理します。ステージング・ログのフォーマットおよび移入に関するルールは、同期リフレッシュの変更データの取得時におけるステージング・ログの使用で説明されています。表ごとに、リフレッシュ操作を実行する前に、PREPARE_STAGING_LOGプロシージャを実行する必要があります。
変更データの準備ができたら、実際のリフレッシュ操作を実行できます。同期リフレッシュでは、新しいリフレッシュ実行方法を取ります。これは、リフレッシュ操作を準備と実行の2つのステップに分割して機能します。これは、同期リフレッシュと他のリフレッシュ方法の主な相違点の1つで、重要ないくつかの利点があります。
準備ステップでは、ファクト表のパーティションとマテリアライズド・ビューのパーティション間のマッピングを決定します。このステップでは、増分変更データのロードによって変更されたファクト表のパーティションのみに対応する新しい表を計算します。外部表と呼ばれるこれらの表が計算されると、実行ステップで実際にリフレッシュ操作が行われます。この操作は、外部表と、ファクト表またはマテリアライズド・ビュー内の該当するパーティションの交換です。
リフレッシュ実行ステップを2つのフェーズに分割し、それぞれに別のプロシージャを与えることにより、同期リフレッシュでは、リフレッシュ実行プロセスを制御できるだけでなく、システム全体のパフォーマンスを向上させることができます。これは、リフレッシュ・プロセスによって変更されるためダイレクト・アクセスまたはオプティマイザがマテリアライズド・ビューを使用できない時間を最小限に抑えることよって実現しています。準備フェーズでは、マテリアライズド・ビューとその表は変更されません。これは、この時点ではすべてのリフレッシュ変更が外部表に記録されるためです。したがって、マテリアライズド・ビューは、これを読み取る必要のあるすべての問合せで使用可能です。表とマテリアライズド・ビューが変更されるのは実行の間のみです。実行パフォーマンスは、主にディメンション表への変更の数の影響を受けます。この数が少ない場合、パーティション交換操作自体は非常に高速であるため、パフォーマンスは非常に良好になります。
DBMS_SYNC_REFRESHパッケージでは、これら2つのステップを実行するPREPARE_REFRESHプロシージャとEXECUTE_REFRESHプロシージャを提供しています。
関連項目:
『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』
マテリアライズド・ビューを同期リフレッシュで使用できるようにするための主な要件として、マテリアライズド・ビューは、そのファクト表のパーティション・キーから導出できるキーでパーティション化される必要があります。以降の項では、同期リフレッシュを使用するためのその他の要件について説明します。
この項には次のトピックが含まれます:
同期リフレッシュを使用するためには、主に2つの要件があります。
マテリアライズド・ビューは、ファクト表と同じディメンションでパーティション化される必要があります。
ファクト表のパーティション・キーが機能的にマテリアライズド・ビューのパーティション・キーを決定する必要があります。
機能的に決定するとは、外部キー制約関係に基づき、マテリアライズド・ビューのパーティション・キーはファクト表のパーティション・キーから導出できることを意味します。この条件が満たされるのは、マテリアライズド・ビューのパーティション・キーが、ファクト表のパーティション・キーと同じであるか、スター・スキーマやスノーフレーク・スキーマのようにファクト表とディメンション表の結合により関連付けられている場合です。たとえば、ファクト表がTIME_KEYなどの日付列でパーティション化されている場合、マテリアライズド・ビューは、TIME_KEY、MONTH、YEARなどでパーティション化できます。
同期リフレッシュは、ファクト表とマテリアライズド・ビューにおいて2種類のパーティション化(最上位のパーティション化タイプがレンジの場合、レンジ・パーティション化とコンポジット・パーティション化)をサポートしています。
マテリアライズド・ビューを定義する際は、リフレッシュ方法、トラステッド制約を使用可能にするかどうか、実行するリフレッシュのタイプの3つのリフレッシュ・オプションを指定できます。オプションを指定しない場合は、デフォルトとして、それぞれON DEMAND、ENFORCED制約、FORCEが使用されます。同期リフレッシュの場合、これらのオプションの最初の2つの値は、それぞれON DEMANDとTRUSTED制約である必要があります。同期リフレッシュでは、リフレッシュのタイプには特定の値を必要としません。したがって、FAST、FORCE、COMPLETEのいずれでもかまいません。
ファクト表とディメンション表の関係は、表の外部キーおよび主キー制約によって宣言されます。同期リフレッシュは、リフレッシュの実行の際にこれらの制約を信頼し、マテリアライズド・ビューの定義でUSING TRUSTED CONSTRAINTSが指定されている必要があります。これによって、リフレッシュの際、UNKNOWNまたはFRESHの状態で、妥当性チェックが行われていないRELY制約の使用およびマテリアライズド・ビューに対するリライトが許可されます。
表が同期リフレッシュ用に登録されている場合、その制約はVALIDATEまたはNOVALIDATEの状態です。表がディメンション表の場合、同期リフレッシュでは、リフレッシュ実行プロセスの間、この状態が維持されます。
ただし、表がファクト表の場合は、リフレッシュ実行の間、同期リフレッシュにより制約がNOVALIDATEの状態にマークされます。これにより、同期リフレッシュ方法の基本であるパーティション交換の間、既存のデータで制約を検証する必要がなくなり、リフレッシュ実行のパフォーマンスが向上します。
同期リフレッシュではファクト表での制約は強制されないため、ユーザー自身が提供されたデータの整合性を検証する必要があります。
同期リフレッシュで使用できるようにするには、表は次の条件を満たす必要があります。
表にはVPDやトリガーを定義できません。
表にRAW型を含めることはできません。
表はリモートにできません。
同期リフレッシュ用に登録された各表のステージング・ログ・キーは、ステージング・ログ・キーについてで説明する要件を満たす必要があります。
他にも、同期リフレッシュ用に登録されたマテリアライズド・ビューに固有の制約がいくつかあります。
問合せの定義にROWID列を使用することはできません。これは、元のパーティションを外部表と置き換えるパーティション交換を使用するため、関係ありません。したがって、問合せの定義にROWID列は含めません。
同期リフレッシュでは、ネステッド・マテリアライズド・ビュー、UNION ALLマテリアライズド・ビュー、副問合せ、マテリアライズド・ビュー定義での複雑な問合せはサポートしていません。問合せの定義は、スター・スキーマまたはスノーフレーク・スキーマに準拠している必要があります。
SQLコンストラクトの分析ウィンドウ関数(RANKなど)、MODEL句およびCONNECT BY句もサポートされていません。
ビュー、リモート表または外部結合を参照するマテリアライズド・ビューでは、同期リフレッシュはサポートされません。
マテリアライズド・ビューには、SYSDATEやROWNUMなど、結果の再現が不可能な式への参照を含めることはできません。
一般に、PCTリフレッシュ、高速リフレッシュおよび一般的なクエリー・リライトに適用される制限のほとんどが、同期リフレッシュにも適用されます。これらの制限は次の項を参照してください。
集計を含むマテリアライズド・ビューの場合、同期リフレッシュでは、高速リフレッシュと同様に次の制限があります。
サポートされているのは、SUM、COUNT、AVG、STDDEV、VARIANCE、MINおよびMAXのみです。
COUNT(*)を指定する必要があります。
集計関数は、式の最も外側でのみ使用する必要があります。つまり、AVG(AVG(x))やAVG(x)+ AVG(x)などの集計は実行できません。
AVG(expr)などの集計ごとに、対応するCOUNT(expr)が存在している必要があります。さらにSUM(expr)を指定することをお薦めします。
VARIANCE(expr)またはSTDDEV(expr)が指定された場合は、COUNT(expr)およびSUM(expr)を指定する必要があります。さらにSUM(expr *expr)を指定することをお薦めします。
同期リフレッシュは、様々な点で他のリフレッシュ方法とは異なります。1つは、他のリフレッシュ方法はDBMS_MVIEWパッケージで宣言されるのに対し、同期リフレッシュのAPIはDBMS_SYNC_REFRESHと呼ばれる新しいパッケージに含まれる点です。もう1つは、オブジェクトが一度同期リフレッシュに登録されると、これらに他のリフレッシュ方法を使用できなくなる点です。
同期リフレッシュに関連する操作は、大まかに次の3つのフェーズに分割できます。
このフェーズでは(図8-1)、使用するオブジェクトを同期リフレッシュに登録します。このフェーズの2つのステップでは、まず表を登録し、次にマテリアライズド・ビューを登録します。表はステージング・ログを作成することで登録し、マテリアライズド・ビューはREGISTER_MVIEWSプロシージャによって登録します。ステージング・ログは、CREATE MATERIALIZED LOG … FOR SYNCHRONOUS REFRESH文を使用して作成されます。表にすでに通常のマテリアライズド・ビュー・ログがある場合は、ALTER MATERIALIZED LOG … FOR SYNCHRONOUS REFRESH文を使用して、これをステージング・ログに変換できます。
例8-1に示すような文を使用してステージング・ログを作成できます。
例8-1 表の登録
CREATE MATERIALIZED VIEW LOG ON fact FOR SYNCHRONOUS REFRESH USING st_fact;
表にマテリアライズド・ビューがある場合、次のような文を使用して、これをステージング・ログに変更できます。
ALTER MATERIALIZED VIEW LOG ON fact FOR SYNCHRONOUS REFRESH USING st_fact;
例8-2に示すような文を使用してマテリアライズド・ビューを登録できます。
例8-2 マテリアライズド・ビューの登録
EXECUTE DBMS_SYNC_REFRESH.REGISTER_MVIEWS('MV1');
複数のマテリアライズド・ビューを一度に登録できます。
EXECUTE DBMS_SYNC_REFRESH.REGISTER_MVIEWS('mv2, mv2_year, mv1_halfmonth');
同期リフレッシュの使用を停止することにした場合、図8-3に示すとおり、マテリアライズド・ビューを登録解除する必要があります。まず、UNREGISTER_MVIEWSプロシージャを使用してマテリアライズド・ビューを登録解除します。次に、ステージング・ログを削除するか、通常のログに変更することによって、表を登録解除します。ALTER MATERIALIZED LOG … FOR FAST REFRESH文を使用してステージング・ログを通常のマテリアライズド・ビュー・ログに変換する場合、マテリアライズド・ビューは標準の高速リフレッシュ方法で管理できます。
例8-3は、単一のマテリアライズド・ビューMV1を登録解除する方法を示しています。
例8-3 マテリアライズド・ビューの登録解除
EXECUTE DBMS_SYNC_REFRESH.UNREGISTER_MVIEWS('MV1');
次の方法では複数のマテリアライズド・ビューを一度に登録解除できます。
EXECUTE DBMS_SYNC_REFRESH.UNREGISTER_MVIEWS('mv2, mv2_year, mv1_halfmonth');
DBA_SR_OBJ_ALLビューを問い合せることで、マテリアライズド・ビューが登録解除されたかどうかを確認できます。
例8-4は、ステージング・ログの削除方法を示しています。
例8-4 表の登録解除
DROP MATERIALIZED VIEW LOG ON fact;
次のようにして表をマテリアライズド・ビュー・ログに変更することもできます。
ALTER MATERIALIZED VIEW LOG ON fact FOR FAST REFRESH;
DBA_SR_OBJ_ALLビューを問い合せることで、表が登録解除されたかどうかを確認できます。
同期リフレッシュの際立った特徴として、表およびそのマテリアライズド・ビューへの変更が一緒にロードされリフレッシュされることがあげられます。このため同期リフレッシュという名前になっています。同期リフレッシュで管理される表およびマテリアライズド・ビューでは、オブジェクトを登録する必要があります。表は、ステージング・ログが作成されると同期リフレッシュに対して登録され、マテリアライズド・ビューはREGISTER_MVIEWSプロシージャにより登録されます。
同期リフレッシュでは、複数の表に構築されたマテリアライズド・ビュー(これらのうち1つ以上に変更がある)のリフレッシュをサポートしています。制約によって関連付けられている表は、データの整合性を保証するにはすべて一緒にリフレッシュする必要があります。さらに、同期リフレッシュに対して登録されている表の最上位にいくつかのマテリアライズド・ビューを構築することが可能ですが、その場合、これらのマテリアライズド・ビューは一緒にリフレッシュする必要があります。
ユーザーがこれらの依存性を追跡し、適切な表のセットでリフレッシュ・コマンドを発行するかわりに、Oracle Databaseでは一緒にリフレッシュする必要のある最低限の表とマテリアライズド・ビューのセットを自動生成します。これらのセットは同期リフレッシュ・グループと呼ばれます。各同期リフレッシュ・グループは、GROUP_ID値で識別されます。
同期リフレッシュの実行に関連する3つのプロシージャ(PREPARE_REFRESH、EXECUTE_REFRESHおよびABORT_REFRESH)は、入力として、同期リフレッシュ・グループを識別する単一のグループIDまたはグループIDのリストを取ります。
同期リフレッシュに対して登録された各表またはマテリアライズド・ビューにはGROUP_ID値が割り当てられます。これは依存関係が変わると変更される可能性があります。これは、REGISTER_MVIEWSプロシージャおよびUNREGISTER_MVIEWSプロシージャを発行すると発生します。後続の例は、様々なシナリオにおける同期リフレッシュ・グループを示しています。
GROUP_ID値は時とともに変化する可能性があるため、同期リフレッシュ・プロシージャの起動の際には、実際のGROUP_ID値は使用せず、かわりにDBMS_SYNC_REFRESH.GET_GROUP_ID関数を使用することをお薦めします。この関数は入力としてマテリアライズド・ビュー名を取り、マテリアライズド・ビューのGROUP_ID値を戻します。
関連項目:
DBMS_SYNC_REFRESH.REGISTER_MVIEWSプロシージャの使用方法については、『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照してください。
この項には次のトピックが含まれます:
rdbms/demoディレクトリの同期リフレッシュ・デモ・スクリプトでは、実行されることの多い一般的な操作を見ることができます。メイン・スクリプトはsyncref_run.sqlで、そのログはsyncref_run.logです。次の例8-5、例8-6および例8-7は、GET_GROUP_ID関数を使用できる、異なるコンテキストを示しています。
例8-5 グループに登録されたオブジェクトの表示
この例は、グループに登録されたオブジェクトを表示する方法を示しています。
EXECUTE DBMS_SYNC_REFRESH.REGISTER_MVIEWS('MV1');
SELECT NAME, TYPE, STAGING_LOG_NAME FROM USER_SR_OBJ
WHERE GROUP_ID = DBMS_SYNC_REFRESH.GET_GROUP_ID('MV1')
ORDER BY TYPE, NAME;
NAME TYPE STAGING_LOG_NAME
---------- ---------- ----------------
MV1 MVIEW
FACT TABLE ST_FACT
STORE TABLE ST_STORE
TIME TABLE ST_TIME
例8-6 リフレッシュ操作の起動
この例は、リフレッシュ操作の起動方法を示しています。
EXECUTE DBMS_SYNC_REFRESH.PREPARE_REFRESH( -
DBMS_SYNC_REFRESH.GET_GROUP_ID('MV1'));
EXECUTE DBMS_SYNC_REFRESH.EXECUTE_REFRESH( -
DBMS_SYNC_REFRESH.GET_GROUP_ID('MV1'));
SELECT NAME, TYPE, STATUS FROM USER_SR_OBJ_STATUS
WHERE GROUP_ID = DBMS_SYNC_REFRESH.GET_GROUP_ID('MV1')
ORDER BY TYPE, NAME;
例8-7 グループに登録されたオブジェクトのステータスの確認
この例は、EXECUTE_REFRESH操作の後に、グループに登録されたオブジェクトのステータスを確認する方法を示しています。
SELECT NAME, TYPE, STATUS FROM USER_SR_OBJ_STATUS
WHERE GROUP_ID = DBMS_SYNC_REFRESH.GET_GROUP_ID('MV1')
ORDER BY TYPE, NAME;
NAME TYPE STATUS
---------------- ---------- ----------------
MV1 MVIEW COMPLETE
FACT TABLE COMPLETE
STORE TABLE COMPLETE
TIME TABLE COMPLETE
次のAPIを使用して一度に複数のリフレッシュ・グループを使用できます。
GET_GROUP_ID_LIST
入力にマテリアライズド・ビューのリストを取り、それらのグループIDをリストで戻します。
GET_ALL_GROUP_IDS
システム内のすべてのグループのグループIDをリストで戻します。
リフレッシュ準備プロシージャ(PREPARE_REFRESH、EXECUTE_REFRESHおよびABORT_REFRESH)は複数のグループで機能します。これらのオーバーロードされたバージョンでは、一度にグループIDのリストを受け入れます。
例8-8 同期リフレッシュ・グループの準備
この例は、MV1、MV2およびMV3の同期リフレッシュ・グループを準備する方法を示しています。
EXECUTE DBMS_SYNC_REFRESH.PREPARE_REFRESH(
DBMS_SYNC_REFRESH.GET_GROUP_ID_LIST('MV1, MV2, MV3'));
これら3つのマテリアライズド・ビューがすべて異なるグループである必要はないことに注意してください。マテリアライズド・ビューのうち2つが同じグループでもう1つが別のグループでも、あるいは3つすべてが同じグループでもかまいません。グループIDまたはグループIDのリストを受け入れるため、PREPARE_REFRESHはオーバーロードされるので、前述のコールはどのような場合でも機能します。
例8-9 同期リフレッシュ・グループの実行
この例は、システム内のすべての同期リフレッシュ・グループのリフレッシュを準備および実行する方法を示しています。
EXECUTE DBMS_SYNC_REFRESH.PREPARE_REFRESH(
DBMS_SYNC_REFRESH.GET_ALL_GROUP_IDS);
EXECUTE DBMS_SYNC_REFRESH.EXECUTE_REFRESH(
DBMS_SYNC_REFRESH.GET_ALL_GROUP_IDS);
同期リフレッシュでは、PREPARE_REFRESHプロシージャおよびEXECUTE_REFRESHプロシージャへの入力として機能する変更データを指定および準備する必要があります。変更データを指定するには、次の2つの方法があります。
同期リフレッシュの変更データの取得時におけるパーティション操作の使用の説明に従って、外部表に変更データを指定し、これをREGISTER_PARTITION_OPERATIONプロシージャに登録します。
同期リフレッシュの変更データの取得時におけるステージング・ログの使用の説明に従って、ステージング・ログに変更データを指定し、これらをPREPARE_STAGING_LOGプロシージャで処理します。
変更データに関する注意点を次に示します。
2つの方法は互いに排他的ではなく、同じ表であっても同時に使用することが可能です。ただし、指定した変更で競合が存在することはできません。たとえば、変更の数が少ないパーティションではステージング・ログを使用して変更を指定できますが、別のパーティションに大規模な変更がある場合は、そのパーティションの変更を外部表に指定することができます。
ディメンション表の場合、変更の指定にはステージング・ログのみを使用できます。
同期リフレッシュでは、ファクト表およびディメンション表内の任意の組合せの変更を処理できますが、大量の変更がファクト表の少数のパーティションのみに行われるという、データ・ウェアハウスの最も一般的な使用シナリオ向けに最適化されます。
同期リフレッシュでは、一般的にデータ・ウェアハウスで使用される、パーティションの追加などの非破壊的パーティション・メンテナンス操作(PMOPS)の使用について、制限を設けていません。このようなPMOPSの使用は、変更データの指定に使用される方法に直接関係しません。
同期リフレッシュでは、グループ内のすべてのステージング・ログが準備されている必要があります。これはステージング・ログに登録されている変更がない場合でも同様です。
REGISTER_PARTITION_OPERATIONプロシージャを使用して、直接変更データを提供できます。この方法はファクト表にのみ適用可能です。変更されるファクト表パーティションごとに、そのパーティションのデータを含む外部表を提供する必要があります。同期リフレッシュのデモ(syncref_run.sqlおよびsyncref_run.log)に例が含まれています。手順は次のとおりです。
外部表を登録し、リフレッシュを実行すると、Oracle DatabaseはEXECUTE_REFRESH時に次の操作を実行します。
ALTER TABLE FACT EXCHANGE PARTITION fp3 WITH TABLE fact_ot_fp3 INCLUDING INDEXES WITHOUT VALIDATION;
ただし、この文を自分自身で直接発行することはできません。発行すると、Oracle Databaseでは次のエラーが表示されます。
ORA-31908: Cannot modify the contents of a table with a staging log.
EXCHANGE操作の他に、REGISTER_PARTITION_OPERATIONプロシージャで登録できる2つのパーティション操作として、DROPとTRUNCATEがあります。
例8-10 DROP操作の登録
この例は、次の文を使用して最初のパーティション(FP1)の削除を指定する方法を示しています。
begin
DBMS_SYNC_REFRESH.REGISTER_PARTITION_OPERATION(
partition_op => 'DROP',
schema_name => 'SYNCREF_USER',
base_table_name => 'FACT',
partition_name => 'FP1');
end;
/
かわりにパーティションを切り捨てる場合は、partition_opパラメータにDROPではなくTRUNCATEを指定できます。
3つのパーティション操作(EXCHANGE、DROPおよびTRUNCATE)は、表の内容を変更するため破壊的PMOPSと呼ばれます。次のパーティション操作は破壊的ではなく、同期リフレッシュに登録される表で直接実行できます。
ADD PARTITION
SPLIT PARTITION
MERGE PARTITIONS
MOVE PARTITION
RENAME PARTITION
データ・ウェアハウスでは、これらのパーティション操作は一般に大量のデータを管理するために使用され、同期リフレッシュはその使用方法に制約を設けません。Oracle Databaseでの要件は、PREPARE_REFRESHコマンドが発行される前にこれらの操作を実行することのみです。これは、PREPARE_REFRESHプロシージャは、ファクト表パーティションとマテリアライズド・ビュー・パーティション間のマッピングを計算しており、PREPARE_REFRESHプロシージャとEXECUTE_REFRESHプロシージャの間にパーティション・メンテナンスが行われると、Oracle DatabaseはEXECUTE_REFRESHでこれを検出し、エラーを表示するためです。
USER_SR_PARTN_OPSカタログ・ビューを使用して、登録されたパーティション操作を表示できます。
SELECT TABLE_NAME, PARTITION_OP, PARTITION_NAME,
OUTSIDE_TABLE_SCHEMA ot_schema, OUTSIDE_TABLE_NAME ot_name
FROM USER_SR_PARTN_OPS
ORDER BY TABLE_NAME;
TABLE_NAME PARTITION_ PARTITION_NAME OT_SCHEMA OT_NAME
---------- ---------- --------------- --------------- --------------------
FACT EXCHANGE FP3 SYNCREF_USER FACT_OT_FP3
1 row selected.
これらのパーティション操作は、同期リフレッシュ操作で使用され、EXECUTE_REFRESHプロシージャにより自動的に登録解除されます。したがって、EXECUTE_REFRESHの後にUSER_SR_PARTN_OPSを問い合せても行は表示されません。
パーティションの登録後に誤りを見つけたり、方針が変わった場合には、UNREGISTER_PARTITION_OPERATIONコマンドを使用して元に戻すことができます。
begin
DBMS_SYNC_REFRESH.UNREGISTER_PARTITION_OPERATION(
partition_op => 'EXCHANGE',
schema_name => 'SYNCREF_USER',
base_table_name => 'FACT',
partition_name => 'FP3');
end;
/
同期リフレッシュにおいて、ステージング・ログは、増分リフレッシュでのマテリアライズド・ビュー・ログに類似した役割を果たします。これらはDDL文で作成され、マテリアライズド・ビュー・ログに変更できます。ただし、マテリアライズド・ビュー・ログとは異なり、変更は指定した形式でユーザーがステージング・ログにロードする必要があります。ステージング・ログの各行は、一意に識別するためのキーを持つ必要があります。これはステージング・ログ・キーと呼ばれ、ステージング・ログ・キーについてで定義されています。
ユーザーはステージング・ログにデータを移入する必要があります。ステージング・ログは、実表内のすべての列とCHAR(2)型の追加制御列DMLTYPE$$で構成されます。これには、行が挿入されていることを示す'I'、削除を示す'D'、および更新される行の新しい値と古い値をそれぞれ示す'UN'と'UO'の値が必要です。最後の2つはペアで表す必要があります。
ステージング・ログはPREPARE_STAGING_LOGプロシージャにより検証され、同期リフレッシュ操作(PREPARE_REFRESHおよびEXECUTE_REFRESH)により使用されます。PREPARE_STAGING_LOGによる検証でエラーが検出された場合、これらは例外表で取得されます。ビューUSER_SR_STLOG_EXCEPTIONSを問い合せることで、例外の詳細を取得できます。
同期リフレッシュでは、同期リフレッシュ・グループのPREPARE_REFRESHをコールする前に、グループ内のすべての表のステージング・ログをPREPARE_STAGING_LOGで処理する必要があります。これは、表に変更データがなく、ステージング・ログが空の場合でも必要です。
この項には次のトピックが含まれます:
実表でステージング・ログを作成するには、実表にキーが必要です。表に主キーがある場合、その主キーは表のステージング・ログでステージング・ログ・キーと見なされます。すべてのディメンション表に主キーがあることに注意してください。
ファクト表の場合、主キーがあるのはあまり一般的ではありません。表に主キーがない場合、そのディメンション表の外部キーである列がそのステージング・ログ・キーを構成します。
ステージング・ログ・キーは次のように説明できます。
実表の主キー。ファクト表に主キーがある場合は、サロゲート・キーと呼ばれることもあります。
ファクト表の外部キーのセット。これはファクト表に主キーがない場合に当てはまります。このような場合というのはデータ・ウェアハウスでは一般的ですが、必ずしもそうとはかぎりません。
ステージング・ログのロード・ルールについては、ステージング・ログ・ルールについてを参照してください。
PREPARE_STAGING_LOGプロシージャは、各キー値が一度だけ指定されていることを確認します。ステージング・ログにデータを移入する際、同じキー値の行が複数回変更される場合には、ユーザーがその変更を統合する必要があります。このプロセスは変更の統合と呼ばれます。変更の統合を行う際には、次のようにする必要があります。
同じ行の削除/挿入は、行'UO'および'UN'による更新操作に統合する。
複数の更新を1つの更新に統合する。
同じ行での挿入/更新/削除など、NULL変更がステージング・ログに表示されないようにする。
複数の更新が後に続く挿入を、1つの挿入に統合する。
各行には、主キーを含むすべての列に対して非NULL値が含まれる必要があります。ステージング・ログ内の各キーを1種類の操作に対してのみ指定できるように、変更はすべて統合する必要があります。
挿入される行(DMLTYPE$$が'I')の場合、ステージング・ログ内のすべての列に、実表内の対応する列での制約に準拠した有効な値を提供する必要があります。挿入される行のキーが実表に存在することはできません。
削除される行(DMLTYPE$$が'D')の場合、キー以外の列値はオプションです。同様に、更新される列の古い値を指定する行(DMLTYPE$$が'UO')の場合、キー以外の列値はオプションですが、重要な例外として、値がNULLに更新される列があります。これについてはこの後で説明します。
更新される列の新しい値を指定する行(DMLTYPE$$が'UN')の場合、キー以外の列値は変更された列の値を除いてオプションです。
列がNULLに更新される場合、その古い値は指定する必要があります。指定しないと、Oracle Databaseは、これを更新で値が変更されないままの列と区別できない場合があります。
たとえば、表T1に3つの列c1、c2およびc3があるとします。(c1, c2, c3) = (1, 5, 10)の行があり、ステージング・ログに次の情報を指定するとします。
| DMLTYPE$$ | C1 | C2 | C3 |
|---|---|---|---|
UO |
1 |
NULL |
NULL |
UN |
1 |
NULL |
11 |
古い値を指定しない場合、新しい行は(1, 5, 11)または(1, NULL, 11)となります。しかし、このように指定した場合、明らかに新しい行は(1, 5, 11)となります。c2にNULLを指定する場合は、UO列に次のように古い値を指定する必要があります。
| DMLTYPE$$ | C1 | C2 | C3 |
|---|---|---|---|
UO |
1 |
5 |
NULL |
UN |
1 |
NULL |
11 |
c2の古い値は5(この列に対して以前更新された正しい値)であるため、その新しい値はNULLで、新しい行は(1, NULL, 11)となります。
この項では、ステージング・ログの使用例について説明します。
PREPARE_STAGING_LOGプロシージャには、オプションでPSL_MODEという3番目のパラメータを指定できます。これによって、例8-11に示すように、ステージング・ログで指定される3種類のDML文のいずれかまたはすべてを信頼できるものとして扱えるかどうかを指定でき、PREPARE_STAGING_LOGプロシージャによる検証に依存しないようにできます。
例8-11 信頼できるDML文の指定
EXECUTE DBMS_SYNC_REFRESH.PREPARE_STAGING_LOG('syncref_user', 'store',
DBMS_SYNC_REFRESH.INSERT_TRUSTED +
DBMS_SYNC_REFRESH.DELETE_TRUSTED);
このコールでは、STOREのステージング・ログのINSERTおよびDELETEのDML文の検証はスキップしますが、UPDATE DML文の検証は行います。
例8-12 ステージング・ログの準備
この例は、デモsyncref_run.sqlから取り出したものです。これは、ユーザーが削除および更新操作用にすべての列の値を指定していることを示しています。これらの値が使用可能な場合は、これをお薦めします。
INSERT INTO st_store (dmltype$$, STORE_KEY, STORE_NUMBER, STORE_NAME, ZIPCODE)
VALUES ('I', 5, 5, 'Store 5', '03060');
INSERT INTO st_store (dmltype$$, STORE_KEY, STORE_NUMBER, STORE_NAME, ZIPCODE)
VALUES ('I', 6, 6, 'Store 6', '03062');
INSERT INTO st_store (dmltype$$, STORE_KEY, STORE_NUMBER, STORE_NAME, ZIPCODE)
VALUES ('UO', 4, 4, 'Store 4', '03062');
INSERT INTO st_store (dmltype$$, STORE_KEY, STORE_NUMBER, STORE_NAME, ZIPCODE)
VALUES ('UN', 4, 4, 'Stor4NewNam', '03062');
INSERT INTO st_store (dmltype$$, STORE_KEY, STORE_NUMBER, STORE_NAME, ZIPCODE)
VALUES ('D', 3, 3, 'Store 3', '03060');
EXECUTE DBMS_SYNC_REFRESH.PREPARE_STAGING_LOG('syncref_user', 'store');
-- display initial contents of st_store
SELECT dmltype$$, STORE_KEY, STORE_NUMBER, STORE_NAME, ZIPCODE
FROM st_store
ORDER BY STORE_KEY ASC, dmltype$$ DESC;
DM STORE_KEY STORE_NUMBER STORE_NAME ZIPCODE
-- --------- ------------ ---------- -------
D 3 3 Store 3 03060
UO 4 4 Store 4 03062
UN 4 4 Stor4NewNam 03062
I 5 5 Store 5 03060
I 5 5 Store 6 03062
5 rows selected.
例8-13 削除および更新レコードの不足している値の充填
この例は、ユーザーが削除および更新操作用にすべての値を指定しない場合、PREPARE_STAGING_LOGプロシージャの実行時にOracle Databaseが不足している値を埋めることを示しています。
INSERT INTO st_store (dmltype$$, STORE_KEY, STORE_NUMBER, STORE_NAME, ZIPCODE)
VALUES ('D', 3, NULL, NULL, NULL);
INSERT INTO st_store (dmltype$$, STORE_KEY, STORE_NUMBER, STORE_NAME, ZIPCODE)
VALUES ('UO', 4, NULL, NULL, NULL);
INSERT INTO st_store (dmltype$$, STORE_KEY, STORE_NUMBER, STORE_NAME, ZIPCODE)
VALUES ('UN', 4, NULL, NULL, '03063');
EXECUTE DBMS_SYNC_REFRESH.PREPARE_STAGING_LOG('syncref_user', 'store');
SELECT dmltype$$, STORE_KEY, STORE_NUMBER, STORE_NAME, ZIPCODE
FROM ST_STORE ORDER BY STORE_KEY ASC, dmltype$$ DESC;
DM STORE_KEY STORE_NUMBER STORE_NAME ZIPCODE
-- --------- ------------ ----------- ---------
D 3 3 Store 3 03060
UO 4 4 Store 4 03062
UN 4 4 Store 4 03063
例8-14 列のNULLへの更新
この例は、列をNULLに更新する方法を示しています。列値をNULLに更新する場合、UOレコードに古い値を指定する必要があります。
この例の目的は、店舗の郵便番号を4から03063に変更し、その名前をNULLにすることです。古い郵便番号の値を指定することはできますが、'UO'行にはstore_nameの古い値を指定する必要があります。指定しない場合、store_nameは変更されません。
INSERT INTO st_store (dmltype$$, STORE_KEY, STORE_NUMBER, STORE_NAME, ZIPCODE)
VALUES ('UO', 4, NULL, 'Store 4', NULL);
INSERT INTO st_store (dmltype$$, STORE_KEY, STORE_NUMBER, STORE_NAME, ZIPCODE)
VALUES ('UN', 4, NULL, NULL, '03063');
EXECUTE DBMS_SYNC_REFRESH.PREPARE_STAGING_LOG('syncref_user', 'store');
SELECT dmltype$$, STORE_KEY, STORE_NUMBER, STORE_NAME, ZIPCODE
FROM st_store ORDER BY STORE_KEY ASC, dmltype$$ DESC;
DM STORE_KEY STORE_NUMBER STORE_NAME ZIPCODE
-- --------- ------------ ----------- --------
UO 4 4 Store 4 03062
UN 4 4 03063
例8-15 ステージング・ログ統計の表示
この例は、USER_SR_STLOG_STATSカタログ・ビューを使用してステージング・ログ統計を表示する方法を示しています。
SELECT TABLE_NAME, STAGING_LOG_NAME, NUM_INSERTS, NUM_DELETE, NUM_UPDATES FROM USER_SR_STLOG_STATS ORDER BY TABLE_NAME; TABLE_NAME STAGING_LOG_NAME NUM_INSERTS NUM_DELETES NUM_UPDATES ---------- ---------------- ----------- ----------- ----------- FACT ST_FACT 4 1 1 STORE ST_STORE 2 1 1 TIME ST_TIME 1 0 0 3 rows selected.
EXECUTE_REFRESHプロシージャの最後に同じ問合せを使用すると、取得する行はありません。これは、同期リフレッシュによりすべての変更データが使用されたことを示します。
表がPREPARE_STAGING_LOGプロシージャで処理される際、これはその表のみに関係する変更データの仕様でエラーを検出および報告します。たとえば、挿入される行のキーがまだ実表に存在していないことや、削除または更新する行のキーが存在することを確認します。ただし、PREPARE_STAGING_LOGプロシージャは、表での参照整合性制約に関連するエラーを検出できません。つまり、複数の表が関与する変更データの仕様に不整合があった場合、このプロシージャでエラーを検出することはできません。このようなエラーは、EXECUTE_REFRESHプロシージャで検出されます。
この項では、2つの同期リフレッシュ・プロシージャ、PREPARE_REFRESHおよびEXECUTE_REFRESHのステータスの監視方法および、発生する可能性のあるエラーのトラブルシューティング方法について説明します。同期リフレッシュを使いこなすには、発生する可能性のある様々なエラーのタイプとその対処方法を知っておく必要があります。
エラーの原因として最も可能性の高いものの1つは、変更データの準備での誤りです。これらのエラーは、EXECUTE_REFRESHプロシージャが実行されると、参照制約違反として表示されます。そのような場合、グループのステータスはABORTに設定されます。これらのエラーを認識して対処する方法を理解することが重要です。
この項では、次のトピックについて説明します。
DBMS_SYNC_REFRESHパッケージは、リフレッシュ実行プロセスを制御する3つのプロシージャを提供しています。同期リフレッシュはPREPARE_REFRESHプロシージャで開始します。これは、リフレッシュ操作全体を計画し、リフレッシュのための計算作業の大部分を行います。その後、リフレッシュを実行するEXECUTE_REFRESHプロシージャが続きます。提供されている3番目のプロシージャはABORT_REFRESHで、これは、いずれかのプロシージャが失敗した場合にエラーからのリカバリに使用されます。
USER_SR_GRP_STATUSカタログ・ビューおよびUSER_SR_OBJ_STATUSカタログ・ビューには、現在のグループのリフレッシュ操作のステータスに関するすべての情報が含まれます。
USER_SR_GRP_STATUSビューは、グループ全体としてのステータスを示します。
OPERATIONフィールド(PREPAREまたはEXECUTE)は、そのグループでの現在のリフレッシュ・プロシージャの実行状況を示します。
STATUSフィールド(RUNNING、COMPLETE、ERROR-SOFT、ERROR-HARD、ABORT、PARTIAL)は、操作のステータスを示します。これらについては、後で詳しく説明します。
グループは、そのグループIDで識別されます。
USER_SR_OBJ_STATUSビューは、各個別オブジェクトのステータスを示します。
オブジェクトは、その所有者、名前、タイプ(TABLEまたはMVIEW)およびグループIDによって識別されます。
STATUSフィールド(NOT PROCESSED、ABORTまたはCOMPLETE)。これらについては、後で詳しく説明します。
新しいPREPARE_REFRESHジョブを起動すると、グループのSTATUSはRUNNINGに設定され、グループ内のオブジェクトのSTATUSはNOT PROCESSEDに設定されます。PREPARE_REFRESHジョブが終了してもオブジェクトのステータスには変化がありませんが、グループのステータスは次の3つの値のいずれかに変わります。
COMPLETE: ジョブが正常に完了した場合。
ERROR_SOFT: ジョブでORA-01536「表領域%sに対する領域割当て制限を使い果たしました。」エラーが発生した場合。
ERROR_HARD: その他(つまり、ジョブでORA-01536以外のなんらかのエラーが発生した場合)。
PREPARE_REFRESHプロシージャの使用時の注意点
グループ内のオブジェクトのNOT PROCESSEDステータスは、PREPARE_REFRESHジョブによってそのオブジェクトのデータが変更されていないことを示しています。データの変更はEXECUTE_REFRESHステップでのみ発生します。この際、ステータスは適宜変更されます。これについては後で説明します。
STATUSがERROR_SOFTの場合、表領域の領域割当を増やすことでORA-01536エラーを修正し、PREPARE_REFRESHを再開できます。かわりに、ABORT_REFRESHを使用してリフレッシュを中断させることもできます。
STATUS値がERROR_HARDの場合は、ABORT_REFRESHによるリフレッシュの中断が唯一の選択肢となります。
PREPARE_REFRESHプロシージャの終了後のSTATUS値がRUNNINGである場合は、エラーが発生しています。Oracleサポート・サービスに連絡してください。
PREPARE_REFRESHプロシージャではリソースを大量に使用する場合があるため、ERROR_HARDのSTATUS値は、リソースの枯渇と関連している可能性があります。問題を特定できない場合は、Oracleサポート・サービスに連絡してください。ただし、問題を特定してそれを修正できる場合には、まずABORT_REFRESHを実行し、次にPREPARE_REFRESHプロシージャを実行することによって、同期リフレッシュの使用を続行できる可能性があります。
新しいPREPARE_REFRESHジョブを起動できるのは、そのグループの前のリフレッシュ操作(存在する場合)が正常終了しているか、中断された場合のみであることに留意してください。
PREPARE_REFRESHプロシージャの最終的なSTATUS値がCOMPLETEではない場合、EXECUTE_REFRESHステップには進めません。PREPARE_REFRESHが正常に機能しない場合は、登録解除フェーズに進み、グループ内のオブジェクトを他のリフレッシュ方法で管理できます。
この項では、リフレッシュの準備の際の一般的な例を示します。
例8-16 ステータスがCOMPLETEで正常終了するPREPARE_REFRESH
この例は、正常に完了するPREPARE_REFRESHプロシージャを示しています。
EXECUTE DBMS_SYNC_REFRESH.PREPARE_REFRESH( DBMS_SYNC_REFRESH.GET_GROUP_ID('MV1'));
PL/SQL procedure successfully completed.
SELECT OPERATION, STATUS
FROM USER_SR_GRP_STATUS
WHERE GROUP_ID = DBMS_SYNC_REFRESH.GET_GROUP_ID('MV1');
OPERATION STATUS
--------- ------
PREPARE COMPLETE
例8-17 ステータスがERROR_SOFTで失敗するPREPARE_REFRESH
この例は、ORA-01536が発生するPREPARE_REFRESHプロシージャを示しています。
EXECUTE DBMS_SYNC_REFRESH.PREPARE_REFRESH( DBMS_SYNC_REFRESH.GET_GROUP_ID('MV1'));
BEGIN DBMS_SYNC_REFRESH.PREPARE_REFRESH(DBMS_SYNC_REFRESH.GET_GROUP_ID('MV1')); END;
*
ERROR at line 1:
ORA-01536: space quota exceeded for tablespace 'DUMMY_TS'
ORA-06512: at "SYS.DBMS_SYNC_REFRESH", line 63
ORA-06512: at "SYS.DBMS_SYNC_REFRESH", line 411
ORA-06512: at "SYS.DBMS_SYNC_REFRESH", line 429
ORA-06512: at line 1PL/SQL procedure successfully completed.
SELECT OPERATION, STATUS
FROM USER_SR_GRP_STATUS
WHERE GROUP_ID = DBMS_SYNC_REFRESH.GET_GROUP_ID('MV1');
OPERATION STATUS
--------- ------
PREPARE ERROR_SOFT
例8-18 PREPARE_REFRESHの再開の成功
この例は、例8-17の続きです。ORA-01536エラーが発生したら、DUMMY_TSの表領域を増やし、PREPARE_REFRESHプロシージャを再実行します。今回は正常に終了します。PREPARE_REFRESHプロシージャは停止した場所から処理を再開することに注意してください。PREPARE_REFRESHプロシージャの使用方法は通常と変わりなく、プロシージャが再開されていることを示すパラメータや設定は必要ありません。
EXECUTE DBMS_SYNC_REFRESH.PREPARE_REFRESH(DBMS_SYNC_REFRESH.GET_GROUP_ID('MV1'));
PL/SQL procedure successfully completed.
SELECT OPERATION, STATUS
FROM USER_SR_GRP_STATUS
WHERE GROUP_ID = DBMS_SYNC_REFRESH.GET_GROUP_ID('MV1');
OPERATION STATUS
--------- ------
PREPARE COMPLETE
例8-19 PREPARE_REFRESHの中断
この例は、PREPARE_REFRESHプロシージャが失敗し、STATUS値がERROR_HARDであることを前提としています。ABORT_REFRESHプロシージャを実行して準備ジョブを中断します。STATUS値が最終的にERROR_HARDからABORTに変わることに注意してください。
SELECT OPERATION, STATUS
FROM USER_SR_GRP_STATUS
WHERE GROUP_ID = DBMS_SYNC_REFRESH.GET_GROUP_ID('MV1');
OPERATION STATUS
--------- ------
PREPARE ERROR_HARD
EXECUTE DBMS_SYNC_REFRESH.ABORT_REFRESH( DBMS_SYNC_REFRESH.GET_GROUP_ID('MV1'));
PL/SQL procedure successfully completed.
SELECT OPERATION, STATUS
FROM USER_SR_GRP_STATUS
WHERE GROUP_ID = DBMS_SYNC_REFRESH.GET_GROUP_ID('MV1');
OPERATION STATUS
--------- ------
PREPARE ABORT
EXECUTE_REFRESHプロシージャでは、同期リフレッシュ・グループ内のオブジェクトのグループをサブグループに分割し、各サブグループがアトミックにリフレッシュされます。最初のサブグループは実表で構成されます。同期リフレッシュ・グループ内の各マテリアライズド・ビューは別個のサブグループに配置され、アトミックにリフレッシュされます。
EXECUTE_REFRESHプロシージャの場合、STATUSフィールドの考えられる最終状態は、COMPLETE、PARTIALおよびABORTです。
STATUS = COMPLETE
実表とすべてのマテリアライズド・ビューが正常にリフレッシュされると、この状態になります。
STATUS = ABORT
この状態は、実表のサブグループのリフレッシュが失敗したことを示しています。表とマテリアライズド・ビュー内のデータは整合していますが、変更されていません。この状態が生じた場合は、失敗に関連するエラーがあると考えられます。これが制約違反などのユーザー・エラーである場合は、問題を修正して同期リフレッシュ操作を最初(つまり、グループPREPARE_REFRESHおよびEXECUTE_REFRESH内の各表のPREPARE_STAGING_LOG)から行うことができます。これがユーザー・エラーではない場合は、Oracleサポート・サービスに連絡してください。
STATUS = PARTIAL
実表はすべて正常にリフレッシュされ、マテリアライズド・ビューはすべてではなく一部のみが正常にリフレッシュされると、この状態になります。正常にリフレッシュされた表とマテリアライズド・ビュー内のデータは互いに整合しています。その他のマテリアライズド・ビューは失効しており、リフレッシュを完了させる必要があります。この状態が生じた場合は、失敗に関連するエラーがあると考えられます。最も可能性が高いのは、ユーザー・エラーではなく、Oracleサポート・サービスに報告する必要のあるOracleエラーです。この状態では、次の2つの選択肢があります。
EXECUTE_REFRESHプロシージャの実行を再度試みます。この場合、EXECUTE_REFRESHは、失敗したマテリアライズド・ビューのリフレッシュを、PCTリフレッシュやCOMPLETEリフレッシュなどの別のリフレッシュ方法で再試行します。すべてのマテリアライズド・ビューが成功すると、ステータスはCOMPLETEに設定されます。そうでない場合、ステータスはPARTIALのままとなります。
ABORT_REFRESHプロシージャを起動して、マテリアライズド・ビューを中断します。これにより、すべてのマテリアライズド・ビューおよび実表への変更がロールバックされます。これらはすべて、ステージング・ログ内の変更または登録されたパーティション操作が適用される前の元の状態と同じデータを持つことになります。
EXECUTE_REFRESHプロシージャでのエラーの場合、USER_SR_GRP_STATUSビュー内の次のフィールドも役立ちます。
NUM_MVS_COMPLETED: 正常にリフレッシュ操作を完了したマテリアライズド・ビューの数が含まれています。
NUM_MVS_ABORTED: 中断されたマテリアライズド・ビューの数が含まれています。
ERRORおよびERROR_MESSAGE: 操作で発生したエラーが記録されます。
EXECUTE_REFRESHプロシージャの最後には、グループ内のオブジェクトのステータスがUSER_SR_OBJ_STATUSビューで次のようにマークされます。
変更が正常に適用された場合、オブジェクトのステータスはCOMPLETEに設定されます。
変更が正常に適用されなかった場合、オブジェクトのステータスはABORTに設定されます。この場合、オブジェクトはリフレッシュ操作の前と同じ状態です。ERRORおよびERROR_MESSAGEフィールドには、操作で発生したエラーが記録されます。
変更が適用されなかった場合、オブジェクトのステータスはNOT PROCESSEDのままとなります。
この項では、リフレッシュの実行の際の一般的な例を示します。
例8-20 正常に完了するEXECUTE_REFRESH
例8-20は、正常に完了するEXECUTE_REFRESHプロシージャを示しています。
EXECUTE DBMS_SYNC_REFRESH.EXECUTE_REFRESH( DBMS_SYNC_REFRESH.GET_GROUP_ID('MV1'));
PL/SQL procedure successfully completed.
SELECT OPERATION, STATUS
FROM USER_SR_GRP_STATUS
WHERE GROUP_ID = DBMS_SYNC_REFRESH.GET_GROUP_ID('MV1');
OPERATION STATUS
--------- ------
EXECUTE COMPLETE
例8-21 部分的に成功するEXECUTE_REFRESH
例8-21は、部分的に成功するEXECUTE_REFRESHプロシージャを示しています。この例で、EXECUTE_REFRESHプロシージャは、実表のリフレッシュ後、すべてのマテリアライズド・ビューのリフレッシュが完了する前に失敗します。結果として生じるグループのステータスはPARTIALで、QSM-03280エラー・メッセージがスローされます。
EXECUTE DBMS_SYNC_REFRESH.EXECUTE_REFRESH(DBMS_SYNC_REFRESH.GET_GROUP_ID('MV1'));
BEGIN DBMS_SYNC_REFRESH.EXECUTE_REFRESH(DBMS_SYNC_REFRESH.GET_GROUP_ID('MV1')); END;
*
ERROR at line 1:
ORA-31928: Synchronous refresh error
QSM-03280: One or more materialized views failed to refresh successfully.
ORA-06512: at "SYS.DBMS_SYNC_REFRESH", line 63
ORA-06512: at "SYS.DBMS_SYNC_REFRESH", line 411
ORA-06512: at "SYS.DBMS_SYNC_REFRESH", line 446
ORA-06512: at line 1
EXECUTE_REFRESHプロシージャの後で、グループ自体のステータスをチェックします。操作フィールドがEXECUTEに設定され、ステータスがPARTIALであることに注意してください。
SELECT OPERATION, STATUS FROM USER_SR_GRP_STATUS
WHERE GROUP_ID = DBMS_SYNC_REFRESH.GET_GROUP_ID('MV1');
OPERATION STATUS
--------- -------------
EXECUTE PARTIAL
USER_SR_GRP_STATUSビューを問い合せることによって、中断したマテリアライズド・ビューの数が1で、失敗したマテリアライズド・ビューがMV1であることがわかります。
グループ内のオブジェクトのステータスを調べると、STOREおよびTIMEは変更されていないため、それらのステータスはNOT PROCESSEDです。
SELECT NAME, TYPE, STATUS FROM USER_SR_OBJ_STATUS
WHERE GROUP_ID = DBMS_SYNC_REFRESH.GET_GROUP_ID('MV1')
ORDER BY TYPE, NAME;
NAME TYPE STATUS
---------------- ---------- ----------------
MV1 MVIEW ABORT
MV1_HALFMONTH MVIEW COMPLETE
MV2 MVIEW COMPLETE
MV2_YEAR MVIEW COMPLETE
FACT TABLE COMPLETE
STORE TABLE NOT PROCESSED
TIME TABLE NOT PROCESSED
7 rows selected.
SELECT NUM_TBLS, NUM_MVS, NUM_MVS_COMPLETED, NUM_MVS_ABORTED
FROM USER_SR_GRP_STATUS
WHERE GROUP_ID = DBMS_SYNC_REFRESH.GET_GROUP_ID('MV1');
NUM_TBLS NUM_MVS NUM_MVS_COMPLETED NUM_MVS_ABORTED
-------- ------- ----------------- ---------------
3 4 3 1
この時点で、もう一度EXECUTE_REFRESHプロシージャの実行を試みることができます。再試行に成功し、失敗したマテリアライズド・ビューが成功すると、グループのステータスはCOMPLETEに設定されます。そうでない場合、ステータスはPARTIALのままとなります。例8-22を参照してください。リフレッシュ・プロシージャを中断して元の状態に戻すこともできます。例8-23を参照してください。
例8-22 PARTIALステータス後のリフレッシュの再試行
例8-22は例8-21の続きを示しています。EXECUTE_REFRESHプロシージャを再試行し、成功します。
EXECUTE DBMS_SYNC_REFRESH.EXECUTE_REFRESH(DBMS_SYNC_REFRESH.GET_GROUP_ID('MV1'));
PL/SQL procedure successfully completed.
--Check the status of the group itself after the EXECUTE_REFRESH operation;
--note that the operation field is set to EXECUTE and status is COMPLETE.
SELECT OPERATION, STATUS
FROM USER_SR_GRP_STATUS
WHERE GROUP_ID = DBMS_SYNC_REFRESH.GET_GROUP_ID('MV1');
OPERATION STATUS
--------- ---------
EXECUTE COMPLETE
USER_SR_GRP_STATUSビューを問い合せることによって、中断したマテリアライズド・ビューの数が0で、MV1のステータスがCOMPLETEであることがわかります。グループ内のオブジェクトのステータスを調べると、STOREおよびTIMEは変更されていないため、それらのステータスはNOT PROCESSEDです。
SELECT NAME, TYPE, STATUS FROM USER_SR_GRP_STATUS
WHERE GROUP_ID = DBMS_SYNC_REFRESH.GET_GROUP_ID('MV1')
ORDER BY TYPE, NAME;
NAME TYPE STATUS
---------------- ---------- ----------------
MV1 MVIEW COMPLETE
MV1_HALFMONTH MVIEW COMPLETE
MV2 MVIEW COMPLETE
MV2_YEAR MVIEW COMPLETE
FACT TABLE COMPLETE
STORE TABLE NOT PROCESSED
TIME TABLE NOT PROCESSED
7 rows selected.
SELECT NUM_TBLS, NUM_MVS, NUM_MVS_COMPLETED, NUM_MVS_ABORTED
FROM USER_SR_GRP_STATUS
WHERE GROUP_ID = DBMS_SYNC_REFRESH.GET_GROUP_ID('MV1');
NUM_TBLS NUM_MVS NUM_MVS_COMPLETED NUM_MVS_ABORTED
-------- ------- ----------------- ---------------
3 4 4 0
表とマテリアライズド・ビューを調べ、変更データ内の変更がそれらに正しく適用されていること、およびマテリアライズド・ビューと表が互いに整合していることを確認できます。
例8-23 PARTIALステータスのリフレッシュの中断
例8-23は、PARTIAL状態のリフレッシュ・プロシージャの中断を示しています。
EXECUTE DBMS_SYNC_REFRESH.ABORT_REFRESH(DBMS_SYNC_REFRESH.GET_GROUP_ID('MV1'));
PL/SQL procedure successfully completed.
ABORT_REFRESHプロシージャの後で、グループ自体のステータスをチェックします。操作フィールドがEXECUTEに設定され、ステータスがABORTであることに注意してください。
SELECT OPERATION, STATUS FROM USER_SR_GRP_STATUS
WHERE GROUP_ID = DBMS_SYNC_REFRESH.GET_GROUP_ID('MV1');
OPERATION STATUS
---------- -------
EXECUTE ABORT
USER_SR_GRP_STATUSビューを問い合せることによって、すべてのマテリアライズド・ビューとファクト表が中断されたことがわかります。グループ内のオブジェクトのステータスを調べます。STOREおよびTIMEは変更されていないため、それらのステータスはNOT PROCESSEDです。
SELECT NAME, TYPE, STATUS FROM USER_SR_GRP_STATUS
WHERE GROUP_ID = DBMS_SYNC_REFRESH.GET_GROUP_ID('MV1')
ORDER BY TYPE, NAME;
NAME TYPE STATUS
---------------- ---------- ----------------
MV1 MVIEW ABORT
MV1_HALFMONTH MVIEW ABORT
MV2 MVIEW ABORT
MV2_YEAR MVIEW ABORT
FACT TABLE ABORT
STORE TABLE NOT PROCESSED
TIME TABLE NOT PROCESSED
7 rows selected.
SELECT NUM_TBLS, NUM_MVS, NUM_MVS_COMPLETED, NUM_MVS_ABORTED
FROM USER_SR_GRP_STATUS
WHERE GROUP_ID = DBMS_SYNC_REFRESH.GET_GROUP_ID('MV1');
NUM_TBLS NUM_MVS NUM_MVS_COMPLETED NUM_MVS_ABORTED
-------- ------- ----------------- ---------------
3 4 0 4
表とマテリアライズド・ビューを調べ、これらがすべて元の状態で、変更データの変更が適用されていないことを確認できます。
同期リフレッシュ方法では、変更データは表とマテリアライズド・ビューに同時にロードされ、同期した状態を保ちます。その他のリフレッシュ方法では、変更データはまず表にロードされ、その際に有効なすべての制約がチェックされます。同期リフレッシュ方法では、外部表はユーザーが信頼するデータを使用して準備され、制約違反は実行時間を省くため無効にされます。次の例は、EXECUTE_REFRESHプロシージャによって検出される制約違反を示しています。このような場合、EXECUTE_REFRESHプロシージャの最終的なステータスはABORTとなります。変更データの問題を特定して修正し、もう一度同期リフレッシュ・フェーズを開始する必要があります。
例8-24 子キーの制約違反
例8-24では、rdbms/demoディレクトリのファイルsyncref_run.sqlと同じ表が使用され、同じデータが移入されるものとします。特に、表STOREには、主キーSTORE_KEYの値が1から4の4つの行があり、FACT表には、store 3を含む4つすべての店舗を参照する行があります。
親キーの制約違反を示すため、STOREのステージング・ログにSTORE_KEYが3の行の削除を移入します。他の表へのその他の変更はありません。EXECUTE_REFRESHプロシージャを実行すると、次のようにORA-02292エラーで失敗します。
INSERT INTO st_store (dmltype$$, STORE_KEY, STORE_NUMBER, STORE_NAME, ZIPCODE)
VALUES ('D', 3, 3, 'Store 3', '03060');
-- Prepare the staging logs
EXECUTE DBMS_SYNC_REFRESH.PREPARE_STAGING_LOG('syncref_user', 'fact');
EXECUTE DBMS_SYNC_REFRESH.PREPARE_STAGING_LOG('syncref_user', 'time');
EXECUTE DBMS_SYNC_REFRESH.PREPARE_STAGING_LOG('syncref_user', 'store');
-- Prepare the refresh
EXECUTE DBMS_SYNC_REFRESH.PREPARE_REFRESH(DBMS_SYNC_REFRESH.GET_GROUP_ID('MV1'));
-- Execute the refresh
EXECUTE DBMS_SYNC_REFRESH.EXECUTE_REFRESH( -
DBMS_SYNC_REFRESH.GET_GROUP_ID('MV1'));
BEGIN DBMS_SYNC_REFRESH.EXECUTE_REFRESH(DBMS_SYNC_REFRESH.GET_GROUP_ID('MV1')); END;
*
ERROR at line 1:
ORA-02292: integrity constraint (SYNCREF_USER.SYS_C0031765) violated - child record found
ORA-06512: at line 1
ORA-06512: at "SYS.DBMS_SYNC_REFRESH", line 63
ORA-06512: at "SYS.DBMS_SYNC_REFRESH", line 411
ORA-06512: at "SYS.DBMS_SYNC_REFRESH", line 446
ORA-06512: at line 1
EXECUTE_REFRESHプロシージャの後で、グループ自体のステータスを確認します。操作フィールドがEXECUTEに設定され、ステータスがABORTであることに注意してください。
SELECT OPERATION, STATUS
FROM USER_SR_GRP_STATUS
WHERE GROUP_ID = DBMS_SYNC_REFRESH.GET_GROUP_ID('MV1');
OPERATION STATUS
---------- --------------
EXECUTE ABORT
実表とMV1の内容をチェックすると、変更がなく、これらすべてに元の値が含まれていることがわかります。
CAN_SYNCREF_TABLE関数は、表とその依存マテリアライズド・ビューが同期リフレッシュで使用可能かどうかを示します。その分析についての説明も行います。表とビューが使用できない場合、その原因を調査し、可能であれば適切な処置を行うことができます。同期リフレッシュで使用できるようにするには、表が前述の様々な条件を満たす必要があります。
CAN_SYNCREF_TABLE関数は、次の2つの方法で起動できます。
CAN_SYNCREF_TABLE関数の出力を格納する表を使用します
出力表を使用するための基本構文は、次のとおりです。
can_syncref_table(schema_name IN VARCHAR2,
table_name IN VARCHAR2,
statement_id IN VARCHAR2)
CAN_SYNCREF_TABLE関数の出力を格納するVARRAYを使用します
CAN_SYNCREF_TABLE関数の出力を表ではなくVARRAYに送るには、次のようにプロシージャをコールします。
can_syncref_table(schema_name IN VARCHAR2,
table_name IN VARCHAR2,
output_array IN OUT Sys.CanSyncRefTypeArray)
スクリプトutlcsrt.sqlを実行すると、出力表SYNCREF_TABLEを作成できます。
表8-1 CAN_SYNCREF_TABLE
| パラメータ | 説明 |
|---|---|
|
実表のスキーマの名前。 |
|
実表の名前。 |
|
出力がユーザーのスキーマ内の |
|
|
注意:
CAN_SYNCREF_TABLE関数には、1つのstatement_idまたはoutput_arrayパラメータのみを指定する必要があります。
CAN_SYNCREF_TABLE関数の出力は、表SYNCREF_TABLEに送ることができます。ユーザーはSYNCREF_TABLEの作成を担います。これは必要がなくなったら削除できます。SYNCREF_TABLEの形式は次のとおりです。
CREATE TABLE SYNCREF_TABLE(
statement_id VARCHAR2(30),
schema_name VARCHAR2(30),
table_name VARCHAR2(30),
mv_schema_name VARCHAR2(30),
mv_name VARCHAR2(30),
eligible VARCHAR2(1), -- 'Y' , 'N'
seq_num NUMBER,
msg_number NUMBER,
message VARCHAR2(4000)
);
同じ表でこのプロシージャを起動するたびに、異なるstatement_idパラメータを指定する必要があります。そうしないとエラーがスローされます。statement_id、schema_nameおよびtable_nameフィールドは、特定の表およびstatement_idの結果を識別します。
各行には、表またはその依存マテリアライズド・ビューの適格性に関する情報が含まれます。CAN_SYNCREF_TABLE関数は、NULLまたは非NULLの、mv_schema_nameとmv_nameの両方の値が各行にあることを保証します。これらの行には、次のような意味があります。
mv_schema_name値がNULLでmv_nameがNULLの場合、ELIGIBLEフィールドは表が同期リフレッシュで使用できるかどうかを表します。表が使用できない場合、MSG_NUMBERおよびMESSAGEフィールドにその理由が示されます。
mv_schema_name値がNOT NULLでmv_nameがNOT NULLの場合、ELIGIBLEフィールドはマテリアライズド・ビューが同期リフレッシュで使用できるかどうかを表します。マテリアライズド・ビューが使用できない場合、MSG_NUMBERおよびMESSAGEフィールドにその理由が示されます。
同じ表でこのプロシージャを起動するたびに、異なるstatement_idパラメータを指定する必要があります。そうしないと、エラーがスローされます。statement_id、schema_nameおよびtable_nameフィールドは、特定の表およびstatement_idの結果を識別します。
CAN_SYNCREF_TABLE関数の出力は、PL/SQLのVARRAYに保存できます。この配列の要素はCanSyncRefMessage型で、SYSスキーマで次の例のように事前定義されています。
TYPE CanSyncRefMessage IS OBJECT (
schema_name VARCHAR2(30),
table_name VARCHAR2(30),
mv_schema_name VARCHAR2(30),
mv_name VARCHAR2(30),
eligible VARCHAR2(1), -- 'Y' , 'N'
seq_num NUMBER,
msg_number NUMBER,
message VARCHAR2(4000)
);
配列型CanSyncRefArrayTypeは、CanSyncRefMessageオブジェクトのVARRAYで、SYSスキーマで次のように事前定義されています。
TYPE CanSyncRefArrayType AS VARRAY(256) OF CanSyncRefMessage;
各CanSyncRefMessageレコードは、同期リフレッシュに対する実表または依存マテリアライズド・ビューの適格性に関するメッセージを提供します。フィールドの意味は、SYNCREF_TABLE内の対応するフィールドの意味と同じです。ただし、CAN_SYNCREF_TABLEプロシージャがVARRAYパラメータとともにコールされた場合、statement_idは提供されない(要求されないため)ので、SYNCREF_TABLEにはCanSyncRefMessageにないstatement_idフィールドがあります。
CanSyncRefArrayTypeのデフォルトのサイズ制限は、256要素です。256以上の要素を必要とする場合、CanSyncRefArrayをSYSとして接続し、再定義します。次のコマンドは、SYSユーザーとして接続した場合、CanSyncRefArrayを再定義し、制限を2048要素に設定します。
CREATE OR REPLACE TYPE CanSyncRefArrayType AS VARRAY(2048) OF SYS.CanSyncRefMessage; / GRANT EXECUTE ON SYS.CanSyncRefMessage TO PUBLIC; CREATE OR REPLACE PUBLIC SYNONYM CanSyncRefMessage FOR SYS.CanSyncRefMessage; / GRANT EXECUTE ON SYS.CanSyncRefArrayType TO PUBLIC; CREATE OR REPLACE PUBLIC SYNONYM CanSyncRefArrayType FOR SYS.CanSyncRefArrayType; /
DBMS_SYNC_REFRESHパッケージの実行権限は、PUBLICに対して付与されており、すべてのユーザーがこのパッケージのプロシージャを実行して、自身が所有するオブジェクトで同期リフレッシュを実行できます。データベース管理者は、データベース内のすべての表およびマテリアライズド・ビューで同期リフレッシュ操作を実行できます。
一般に、DBA権限のないユーザーが別のユーザーの表で同期リフレッシュを使用する場合、その表における完全な読取りおよび書込み権限が必要です。つまり、その表またはマテリアライズド・ビューのSELECT、INSERT、UPDATEおよびDELETE権限を持つ必要があります。ユーザーは、SELECT権限でなくREAD権限を持つことができます。次のように、例外が2つあります。
PURGE_REFRESH_STATS関数およびALTER_REFRESH_STATS_RETENTION関数
これら2つの関数はパージ・ポリシーを実装し、デフォルトの保存期間の変更に使用できます。これらの関数を実行できるのはデータベース管理者のみです。
CAN_SYNCREF_TABLE関数
これは、指定された表に関連付けられたすべてのマテリアライズド・ビューの同期リフレッシュの適格性を調査するアドバイザ関数です。したがって、このファンクションでは、指定した表に関連付けられたすべてのマテリアライズド・ビューに対するREADまたはSELECT権限が必要です。