プライマリ・コンテンツに移動
Oracle® Database管理者ガイド
12cリリース1 (12.1)
B71301-11
目次へ移動
目次
索引へ移動
索引

前
次

33 分散データベース・システムのアプリケーション開発

分散データベース・システムのアプリケーション開発には、アプリケーション・データの分布の管理、データベース・リンクによって確立される接続の制御、参照整合性の維持、分散問合せのチューニング、およびリモート・プロシージャのエラー処理などのタスクが含まれます。

関連項目:

Oracle Database環境でのアプリケーション開発の詳細は、『Oracle Database開発ガイド』を参照してください

33.1 アプリケーション・データの分散の管理

分散データベース環境では、データベース管理者と共同でデータの最適な格納場所を決めます。

その際、次の点について考慮します。

  • 個々の場所から転送されるトランザクション数

  • 各ノードで使用されるデータ(表の部分)の量

  • パフォーマンス特性とネットワークの信頼性

  • 各種ノードの速度とディスクの容量

  • ノードまたはリンクが使用できないときの重要度

  • 表間の参照整合性の必要性

33.2 データベース・リンクにより確立される接続の制御

SQL文やリモート・プロシージャ・コールの中でグローバル・オブジェクト名が参照されると、ローカル・ユーザーにかわってデータベース・リンクがリモート・データベース内のセッションへの接続を確立します。

リモートの接続とセッションは、それまでにローカルのユーザー・セッションに対して接続が確立されていない場合にのみ作成されます。

リモート・データベースとの間に確立された接続とセッションは、アプリケーションやユーザーによって明示的に終了されないかぎり、ローカル・ユーザーのセッションの間存続します。データベース・リンクを経由してSELECT文を発行すると、UNDOセグメントにトランザクション・ロックが設定されます。セグメントを再び解放するには、COMMIT文またはROLLBACK文を発行する必要があります。

アプリケーションで不要になった高コストの接続を切断するには、データベース・リンクを使用して確立されたリモート接続を終了することが有効です。リモートの接続とセッションを終了するには、CLOSE DATABASE LINK句を指定したALTER SESSION文を使用します。たとえば、次のトランザクションを発行した場合を考えます。

SELECT * FROM emp@sales;
COMMIT;

次の文は、salesデータベース・リンクが指すリモート・データベース内のセッションを終了します。

ALTER SESSION CLOSE DATABASE LINK sales;

ユーザー・セッションのデータベース・リンク接続をクローズするには、ALTER SESSIONシステム権限が必要です。

注意:

データベース・リンクをクローズする前に、まずそのリンクを使用しているカーソルをすべてクローズし、次にそのリンクを使用している現行トランザクションがあればそのトランザクションを終了してください。

関連項目:

ALTER SESSION文の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。

33.3 分散システムの参照整合性の維持

返されたエラー・メッセージをすべてチェックするようにアプリケーションを設計し、分散更新の一部が失敗したことを示すエラー・メッセージがないかを確認します。失敗を検出した場合は、トランザクション全体をロールバックしてからアプリケーションの処理を進めるようにしてください。

たとえば、整合性制約違反など、分散型の文の一部が失敗した場合、データベースはエラー番号ORA-02055を返します。以降の文またはプロシージャ・コールは、ROLLBACKまたはROLLBACK TO SAVEPOINTが発行されるまで、エラー番号ORA-02067を返します。

データベースでは、宣言参照整合性の制約を分散システムのノード間で定義することは許可されていません。つまり、1つの表での宣言参照整合性の制約では、リモート表の主キーまたは一意キーを参照する外部キーを指定することはできません。ただし、トリガーを使用してノード間の親子の表関係を維持することは可能です。

トリガーを使用して分散データベースの複数のノードにまたがる参照整合性を定義する場合、ネットワーク障害により、親表へのアクセスだけでなく子表へのアクセスも制限される可能性があることに注意してください。たとえば、子表がsalesデータベースに存在し、親表がhqデータベースに存在すると想定します。2つのデータベース間のネットワーク接続に障害が発生すると、参照整合性トリガーがhqデータベース内の親表へアクセスする必要があるため、子表に対するDML文が処理(子表に行を挿入したり、子表の外部キーの値を更新するような処理)を進めることができない場合があります。

関連項目:

トリガーを使用した参照整合性の規定の詳細は、『Oracle Database PL/SQL言語リファレンス』を参照してください。

33.4 分散問合せのチューニング

ローカルのOracle Databaseサーバーは、分散問合せを対応する数のリモート問合せに分割し、次に、その問合せを実行するためにリモート・ノードに送信します。リモート・ノードは問合せを実行し、その結果をローカル・ノードに返します。その後、ローカル・ノードは必要な後処理を行い、ユーザーまたはアプリケーションに結果を戻します。

注意:

SQLプロファイル、SQL計画ベースライン、SQLパッチおよび格納されたアウトラインなどのSQL管理オブジェクトは、問合せでデータベース・リンクを使用してリモート表を参照する場合に、想定したとおりに動作しないことがあります。たとえば、SQL計画管理で、問合せにSQL計画ベースラインを使用する場合、リモートで実行される問合せの部分は、SQL計画ベースラインが作成されたときとは違う計画を使用することがあります。

33.4.1 連結インライン・ビューの使用

分散問合せを最適化する最も効果的な方法は、リモート・データベースへのアクセスをできるだけ抑えて必要なデータのみを取得することです。

たとえば、分散問合せで5つのリモート表を2つの異なるリモート・データベースから参照し、複合フィルタ(WHERE r1.salary + r2.salary > 50000など)を使用するとします。この場合、リモート・データベースへのアクセスを1回にし、フィルタをリモート・サイトで適用するように問合せをリライトすることで、問合せのパフォーマンスを改善できます。このリライトにより、問合せを実行するサイトに転送されるデータの量が少なくなります。

リモート・データベースへのアクセスが1回になるように問合せをリライトするには、連結インライン・ビューを使用します。用語の定義は次のとおりです。

  • 連結

    同じデータベースにある2つ以上の表。

  • インライン・ビュー

    親のSELECT文の表に置き換えられるSELECT文。次のカッコで囲まれた部分の埋込みSELECT文がインライン・ビューの例です。

    SELECT e.empno,e.ename,d.deptno,d.dname
       FROM (SELECT empno, ename from
             emp@orc1.world) e, dept d;
    
  • 連結インライン・ビュー

    1つのデータベースのみの複数の表からデータを選択するインライン・ビュー。これを使用すると、リモート・データベースにアクセスする時間が短縮されるため、分散問合せのパフォーマンスが向上します。

連結インライン・ビューを使用して分散問合せを構成し、分散問合せのパフォーマンスを改善することをお薦めします。Oracle Databaseのコストベース最適化を使用すると、分散問合せの多くが透過的にリライトされ、連結インライン・ビューによるパフォーマンスの向上が得られます。

33.4.2 コストベース最適化の使用

コストベース最適化の使用には、クエリー・リライトやコストベース最適化の設定などのタスクの完了が含まれます。

33.4.2.1 コストベース最適化の動作の仕組み

オプティマイザの主なタスクは、連結インライン・ビューを使用するように分散問合せをリライトすることです。

この最適化は、次の3つの手順で実行されます。

  1. マージ可能なビューがすべてマージされます。

  2. オプティマイザが連結問合せブロックのテストを実行します。

  3. オプティマイザが連結インライン・ビューを使用して問合せをリライトします。

問合せがリライトされた後、その問合せが実行され、データ・セットがユーザーに返されます。

コストベース最適化をユーザーに対して透過的に実行する場合は、複数の分散問合せのパフォーマンスを改善することはできません。特に、次のものが分散問合せに含まれている場合、コストベース最適化は効果がありません。

  • 集計

  • 副問合せ

  • 複合SQL

これらの要素のいずれかが分散問合せに含まれている場合は、問合せの修正方法と、分散問合せのパフォーマンスを改善するためのヒントの使用について、「ヒントの使用」を参照してください。

33.4.2.2 コストベース最適化のためのクエリー・リライト

連結インライン・ビューによるクエリー・リライトに加えて、コストベース最適化の方法を使用すると、参照先の表から収集される統計とオプティマイザが実行する計算に従って分散問合せが最適化されます。

たとえば、コストベースの最適化によって次の問合せを分析します。この例では、表統計が使用できると仮定しています。CREATE TABLE文内の問合せが分析されます。

CREATE TABLE AS (
                 SELECT l.a, l.b, r1.c, r1.d, r1.e, r2.b, r2.c
                 FROM local l, remote1 r1, remote2 r2 
                    WHERE l.c = r.c 
                    AND r1.c = r2.c 
                    AND r.e > 300
                );

この文は、次のようにリライトされます。

CREATE TABLE AS (
                 SELECT l.a, l.b, v.c, v.d, v.e
                 FROM (
                        SELECT r1.c, r1.d, r1.e, r2.b, r2.c
                         FROM remote1 r1, remote2 r2
                         WHERE r1.c = r2.c 
                         AND r1.e > 300
                      ) v, local l
                 WHERE l.c = r1.c
                );

インライン・ビューに別名vが割り当てられ、前述のSELECT文で表としてこの別名を参照できます。連結インライン・ビューを作成すると、リモート・サイトで実行される問合せの量が減少するため、コストのかかるネットワーク通信量を削減できます。

33.4.2.3 コストベース最適化の設定

分散問合せのパフォーマンス改善のためにコストベース最適化を使用するようにシステムを設定すると、その処理がユーザーに対して透過的になります。つまり、問合せの発行時に自動的に最適化が実行されます。

33.4.2.3.1 環境の設定

OPTIMIZER_MODE初期化パラメータを設定し、インスタンスに最適化アプローチを選択するためのデフォルト動作を設定します。

このパラメータは次の方法で設定できます。

  • 初期化パラメータ・ファイルのOPTIMIZER_MODEパラメータを変更します。

  • ALTER SESSION文を発行してセッション・レベルで設定します。

関連項目:

パラメータ・ファイルのOPTIMIZER_MODE初期化パラメータの設定と、コストベース最適化方法を使用するためのシステムの構成の詳細は、『Oracle Database SQLチューニング・ガイド』を参照してください。

33.4.2.3.2 表の分析

コストベース最適化で分散問合せのための最も効率的なパスが選択されるようにするには、問合せに関係する表の正確な統計を提供する必要があります。この操作には、DBMS_STATSパッケージを使用します。

注意:

DBMS_STATSプロシージャを実行するには、表に対してローカルに接続する必要があります。

まずリモート・サイトに接続し、次にDBMS_STATSプロシージャを実行する必要があります。

次のDBMS_STATSプロシージャを使用すると、特定のクラスのオプティマイザ統計を収集できます。

  • GATHER_INDEX_STATS

  • GATHER_TABLE_STATS

  • GATHER_SCHEMA_STATS

  • GATHER_DATABASE_STATS

たとえば、分散トランザクションが日常的にscott.dept表にアクセスするとします。コストベースのオプティマイザが引き続き最適な方法を確実に選択するように、次の文を実行します。

BEGIN
   DBMS_STATS.GATHER_TABLE_STATS ('scott', 'dept');
END;

関連項目:

  • 統計生成の詳細は、『Oracle Database SQLチューニング・ガイド』を参照してください。

  • DBMS_STATSパッケージの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。

33.4.3 ヒントの使用

ヒントにより、コストベース最適化の機能を拡張できます。

33.4.3.1 ヒントの使用について

文が十分に最適化されない場合は、ヒントを使用してコストベース最適化の機能を拡張できます。特に、独自の問合せを記述して連結インライン・ビューを使用する場合は、分散問合せがリライトされないようにコストベース・オプティマイザに指示を与えます。

また、データベース環境に関する特別な情報(統計、負荷、ネットワークおよびCPUの制限事項、分散問合せなど)を持っている場合は、ヒントを指定してコストベース最適化を適切に誘導できます。たとえば、データベース環境の情報に基づく連結インライン・ビューを使用して、独自に最適化した問合せを記述した場合は、NO_MERGEヒントを指定することにより、オプティマイザが問合せをリライトしないようにできます。

この手法は、分散問合せに集計、副問合せまたは複合SQLが含まれている場合に特に役立ちます。このタイプの分散問合せはオプティマイザによってリライトできないため、NO_MERGEを指定すると、オプティマイザは「コストベース最適化の動作の仕組み」で説明されている手順をスキップします。

DRIVING_SITEヒントを使用すると、リモート・サイトを問合せ実行サイトとして機能するように定義できます。この方法では、問合せがリモート・サイトで実行され、データがローカル・サイトに返されます。リモート・サイトにデータの大部分が格納されているときは、このヒントが特に役立ちます。

関連項目:

ヒントの使用の詳細は、『Oracle Database SQLチューニング・ガイド』を参照してください。

33.4.3.2 NO_MERGEヒントの使用

NO_MERGEヒントは、データベースで連結されない可能性のあるSQL文にインライン・ビューがマージされないようにします。

このヒントはSELECT文に埋め込み、インライン・ビューを引数として使用するSELECT文の先頭、またはインライン・ビューを定義する問合せブロック内のいずれかに記述できます。

/* with argument */

SELECT /*+NO_MERGE(v)*/ t1.x, v.avg_y
   FROM t1, (SELECT x, AVG(y) AS avg_y FROM t2 GROUP BY x) v,
   WHERE t1.x = v.x AND t1.y = 1;

/* in query block */

SELECT t1.x, v.avg_y
   FROM t1, (SELECT /*+NO_MERGE*/ x, AVG(y) AS avg_y FROM t2 GROUP BY x) v,
   WHERE t1.x = v.x AND t1.y = 1;

通常、このヒントは、データベース環境の情報に基づいて最適化した問合せを作成したときに使用します。

関連トピック

33.4.3.3 DRIVING_SITEヒントの使用

DRIVING_SITEヒントを使用すると、問合せが実行されるサイトを指定できます。

コストベース最適化によって実行が行われる場所を決定することをお薦めしますが、オプティマイザを無効にする場合は、手動で実行サイトを指定できます。

DRIVING_SITEヒントを使用したSELECT文の例を次に示します。

SELECT /*+DRIVING_SITE(dept)*/ * FROM emp, dept@remote.com
   WHERE emp.deptno = dept.deptno;

関連トピック

33.4.4 実行計画の分析

分散問合せのチューニングの際に重要なこととして、実行計画の分析があります。

分析結果から得られるフィードバックは、データベースのテストと検証を行う上で重要な要素になります。計画を比較するときは、検証が特に重要になります。たとえば、コストベースの最適化によって分散問合せを最適化する実行計画を、ヒント、連結インライン・ビューおよびその他の方法を使用して問合せを手動で最適化する計画と比較します。

関連項目:

実行計画、EXPLAIN PLAN文およびその結果の解釈方法の詳細は、『Oracle Database SQLチューニング・ガイド』を参照してください。

33.4.4.1 実行計画の生成

データベース内に実行計画を格納する場所を準備すると、指定した問合せの計画を表示するための準備が完了します。SQL文を直接実行するかわりに、EXPLAIN PLAN FOR句に文を追加します。

たとえば、次のような文を実行できます。

EXPLAIN PLAN FOR
   SELECT d.dname 
   FROM dept d
      WHERE d.deptno 
      IN (SELECT deptno 
          FROM emp@orc2.world
          GROUP BY deptno
          HAVING COUNT (deptno) >3
          )
/

33.4.4.2 実行計画の表示

前述のSQL文を実行すると、実行計画がPLAN_TABLEに一時的に格納されます。

実行計画の結果を表示するには、次のスクリプトを実行します。

@utlxpls.sql

注意:

utlxpls.sqlファイルは$ORACLE_HOME/rdbms/adminディレクトリにあります。

utlxpls.sqlスクリプトを実行すると、指定したSELECT文の実行計画が表示されます。結果は、次のように書式化されます。

Plan Table
-------------------------------------------------------------------------------
| Operation                 |  Name    |  Rows | Bytes|  Cost  | Pstart| Pstop |
-------------------------------------------------------------------------------
| SELECT STATEMENT          |          |       |      |        |       |      |
|  NESTED LOOPS             |          |       |      |        |       |      |
|   VIEW                    |          |       |      |        |       |      |
|    REMOTE                 |          |       |      |        |       |      |
|   TABLE ACCESS BY INDEX RO|DEPT      |       |      |        |       |      |
|    INDEX UNIQUE SCAN      |PK_DEPT   |       |      |        |       |      |
-------------------------------------------------------------------------------

独自の連結インライン・ビューを記述するか、またはヒントを使用して、分散問合せを手動で最適化しようとする場合は、手動最適化の前および後に実行計画を生成するのが最適です。これら両方の実行計画を使用することで、手動最適化の効果を比較し、必要に応じて変更を加え、分散問合せのパフォーマンスを改善できます。

リモート・サイトで実行されるSQL文を表示するには、次のSELECT文を実行します。

SELECT OTHER 
FROM PLAN_TABLE 
   WHERE operation = 'REMOTE';

出力例を次に示します。

SELECT DISTINCT "A1"."DEPTNO" FROM "EMP" "A1" 
   GROUP BY "A1"."DEPTNO" HAVING COUNT("A1"."DEPTNO")>3

注意:

OTHER列の内容全体がうまく表示されない場合は、次のSQL*Plusコマンドを実行してください。

SET LONG 9999999 

33.5 リモート・プロシージャのエラー処理

データベースがプロシージャを実行するとき、エラーが発生する可能性があります。

データベースがプロシージャをローカルまたはリモートの位置で実行するときには、次の4種類の例外が発生する可能性があります。

  • PL/SQLのユーザー定義例外。この例外は、EXCEPTIONキーワードを使用して宣言する必要があります。

  • PL/SQLの事前定義例外。NO_DATA_FOUNDキーワードなど。

  • SQLエラー。ORA-00900ORA-02015など。

  • RAISE_APPLICATION_ERROR()プロシージャを使用して生成されるアプリケーション例外。

ローカル・プロシージャを使用するときは、次のような例外ハンドラを記述して、これらのメッセージをトラップできます。

BEGIN
  ...
EXCEPTION
   WHEN ZERO_DIVIDE THEN
   /* ... handle the exception */
END;

WHEN句には例外名が必要です。RAISE_APPLICATION_ERRORで生成された例外など、例外が名前を持っていない場合は、PRAGMA_EXCEPTION_INITを使用して名前を割り当てることができます。次に例を示します。

DECLARE
  null_salary EXCEPTION;
  PRAGMA EXCEPTION_INIT(null_salary, -20101);
BEGIN
  ...
  RAISE_APPLICATION_ERROR(-20101, 'salary is missing');
...
EXCEPTION
  WHEN null_salary THEN
  ...
END;

リモート・プロシージャのコール中に、例外の処理をローカル・プロシージャの例外ハンドラで行うことができます。リモート・プロシージャはローカルのコール側プロシージャにエラー番号を返す必要があり、返すと前述の例に示すようにコール側プロシージャで例外が処理されます。PL/SQLのユーザー定義例外では、常に、ローカル・プロシージャにORA-06510が返されることに注意してください。

したがって、2つの異なるユーザー定義例外をエラー番号で区別することはできません。その他のリモート例外はすべて、ローカル例外と同じ方法で処理できます。

関連項目:

PL/SQLプロシージャの詳細は、『Oracle Database PL/SQL言語リファレンス』