3.10 分散環境におけるSQLの制約

この項では、分散環境におけるSQLに対する制約について説明します。

これらの制約は、Oracle以外のシステムまたはリモートOracleデータベースへのアクセスが行われる分散環境に適用されます。

トピック:

3.10.1 リモート参照と異機種間参照

異機種間アクセスに関するルールの多くは、リモート参照にも適用されます。

SQL文は、制限付きではありますが、そのSQL文で参照されているデータベース・ノードまたはローカル・ノード上で実行できます。参照されるオブジェクトすべてが1つの参照先ノードに解決される場合、Oracleはそのノードで問合せの実行を試みます。/*+ REMOTE_MAPPED */または/*+ DRIVING_SITE */ヒントを使用すると、参照先ノードで強制的に実行できます。文が発行された場所とは異なるノードに転送される場合、その文はリモート・マップされています。

リモート・マップ文に対しては、完全なデータ型チェックのサポートがあります。チェックの結果により、一貫したデータ型チェックと完全なデータ型の強制が提供されます。

SQL文をリモート・マップするには特定のルールに従う必要があります。これらのルールが遵守されていない場合、エラーが発生します。ルールが適用される順序は関係ありません。

分散環境でのリモート・マッピングにSQLを使用する場合は、異なる制約が存在します。この分散環境には、リモートのOracleデータベースと、Oracle Database Gatewayを介してアクセスされるOracle以外のデータベースを含めることができます。

関連項目:

分散データベースの詳細は、Oracle Database管理者ガイドを参照してください。

3.10.2 分散環境でリモート・マッピングにSQLを使用する場合のルールおよび制限事項

分散環境でリモート・マッピングにSQLを使用する場合のルールおよび制限事項があります。

次の項では、分散環境でリモート・マッピングにSQLを使用する場合に存在する様々なルールまたは制限について説明します。

注意:

以降の例では、remote_db名詞はOracle以外のリモート・システム、remote_oracle_db名詞はリモートのOracle Databaseを指します。

ルールA: データ定義言語文はリモート・マップできません。

Oracleのデータ定義言語では、ターゲット・オブジェクトの構文にはリモート参照の位置がありません。リモート参照を含むデータ定義言語文はローカルに実行されます。異機種間サービスの場合、これは、SQLを使用してOracle以外のデータベースにデータベース・オブジェクトを直接作成できないことを意味します。

次の例に示すように、パススルーSQLを使用してデータベース・オブジェクトを個別に作成できます。

DECLARE
  num_rows INTEGER;
BEGIN 
  num_rows := DBMS_HS_PASSTHROUGH.EXECUTE_IMMEDIATE@remote_db 
  (
     'create table x1 (c1 char, c2 int)'
  ); 
END; 

ルールB: リモート・ターゲット表を使用するINSERT、UPDATEおよびDELETE文はリモート・マップする必要があります。

このルールは、リモートのOracleデータベースよりもOracle以外のリモート・データベースの場合に限定的です。これは、Oracle以外のシステムの表に対するデータ操作言語(DML)文の実行中は、リモート・システムで元のOracleデータベースからデータを取得できないためです。

たとえば、ローカルのemp表からローカルの全従業員をOracle以外のリモートのemp表に挿入するには、次の文を使用します。

INSERT INTO emp@remote_db SELECT * FROM emp;

この文は、リモート・データベースにリモート・マップされます。リモート・データベースに送信されるリモート・マップ文には、empに関する元のデータベースへのリモート参照が含まれます。リモート・データベースが受信するリモート・リンクを、コールバック・リンクと呼びます。

注意:

コールバック・リンクは、汎用の異機種間サービスでサポートされていても、すべての異機種間サービス・エージェントに実装されているとはかぎりません。使用中のデータベース・ゲートウェイでコールバック・リンクが動作するかどうかは、データベース・ゲートウェイのマニュアルを参照して判断してください。

特定のゲートウェイにコールバック・リンクがサポートされていない場合、前述のINSERT文では次のエラーが戻されます。

ORA-02025: all tables in the SQL statement must be at the remote database

このエラーを回避するには、PL/SQLブロックを記述します。次に例を示します。

DECLARE 
CURSOR remote_insert IS SELECT * FROM emp;
BEGIN 
   FOR rec IN remote_insert LOOP
    INSERT INTO emp@remote_db (empno, ename, deptno) VALUES (
      rec.empno,
      rec.ename, 
      rec.deptno 
    );  
   END loop;
END;

もう1つの特殊な事例には、USERUSERENVおよびSYSDATEなど、セッション固有のSQL関数が関係します。これらの関数は、元のサイトで実行する必要があります。これらの関数を含むリモート・マップ文には、コールバック・リンクが含まれます。コールバックがサポートされていないOracle以外のデータベースの場合は、(デフォルトで)制限エラーになる可能性があります。

たとえば、次の文を考えてみます。

DELETE FROM emp@remote_db WHERE hiredate > sysdate;

この文は次のエラー・メッセージを戻します。

ORA-02070: database REMOTE_DB does not support special functions in this context 

このエラーを解決するには、次のように特殊関数をバインド変数で置き換える必要があります。次に例を示します。

DELETE FROM emp@remote_db WHERE hiredate > :1;

ルールC: NESTED TABLE型の列、ユーザー定義型の列、不透明型の列またはREF型の列を含む表などのオブジェクト機能は、リモート・マップできません。

現在、異機種間アクセスの場合、これらの列型はサポートされていません。したがって、この制限が直接発生することはありません。

ルールD: リモート・サイトでサポートされていない演算子および構成メンバーを含むSQL文は、リモート・マップできません。

INSERTUPDATEまたはDELETE文の場合、SQL文は実行できません(ルールBを参照)。ただし、サポートされていない演算子または構成メンバーが、コールバック・リンクで実行できる場合、SQL文を実行できる場合があります。

SELECT文の場合は、その他のルールが対象の文をリモート・マップするように要求していなければ、このルールの影響を受ける文を実行できます。このルールの影響を受けるSELECT文は、リモートのSELECT操作を介して必要なすべてのデータを取得し、サポートされない演算子を処理するか、SQLエンジンを使用してローカルに構成することにより実行されます。

リモートのSELECT操作とは、ローカル表データの行を取得する操作とは異なり、リモート表データの行を取得する操作です。全表スキャンでは、ネットワークを介してリモート表のすべてのデータがフィルタせずに取得されます(SELECT * FROM EMPなど)。

全表スキャンは高コストであるため、Oracle名詞は回避を試みます。リモート表に使用可能な索引がある場合は、ネットワークで取得される行の数を減らすために、これらの索引をWHERE句の条件で使用します。

Oracle Databaseにより生成されたSQL文をチェックするには、その文を記述し、REMOTE操作ごとにEXPLAIN PLAN表のOTHER列を問い合せます。

関連項目:

リモート参照を含む実行計画を解析する方法の詳細は、例: 索引の統計および表統計の使用を参照してください。

たとえば、次の文を考えてみます。

SELECT COUNT(*) FROM emp@remote_db WHERE hiredate < sysdate;

この文では次の出力が戻されます。

COUNT(*)  
----------
        14
1 row selected.

リモート表スキャンは次のとおりです。

SELECT hiredate FROM emp;

sysdateremote_dbまたは評価ルールでサポートされていないため、フィルタに変換される条件を生成してリモート操作に渡すことはできません。そのため、sysdateはローカルに実行する必要があります。

注意:

リモート表スキャン操作は元の問合せについては一部のみ関連するため、受信行数が予想より大幅に多くなり、パフォーマンスが大幅に低下する場合があります。

ルールE: 表の式を含むSQL文はリモート・マップできません。

異機種間アクセス・モジュールでは表の式がサポートされていないため、この制限が直接発生することはありません。

ルールF: SQL文でLONGデータが選択される場合は、その文をLONGを含む表が常駐するノードにマップする必要があります。

次のタイプの文を考えてみます。

SELECT long1 FROM table_with_long@remote_db, dual; 

(コールバック・リンクがサポートされていない場合)前述の文は次のエラー・メッセージを戻します。

ORA-02025: all tables in the SQL statement must be at the remote database

ルールG: SQL文がSELECT...FOR UPDATE OF...形式の場合、その文はFOR UPDATE OF句で参照される列を持つ表が常駐するノードにマップする必要があります。

SQL文がSELECT...FOR UPDATE OF...形式の場合、その文はFOR UPDATE OF句で参照される列を持つ表が常駐するノードにマップする必要があります。

たとえば、次の文を考えてみます。

SELECT ename FROM emp@remote_db WHERE hiredate < sysdate FOR UPDATE OF empno;

前述の文は、リモート・マップが不可能な場合、次のエラー・メッセージを戻します。

ORA-02070: database REMOTE_DB does not support special functions in this context 

ルールH: SQL文に順序が含まれている場合は、その文を各順序が存在するサイトにマップする必要があります。

リモートではOracle以外の順序はサポートされないため、このルールが異機種間アクセス・モジュールに適用されることはありません。

ルールI: 文にユーザー定義演算子が含まれている場合は、その文を各演算子が定義されているノードにマップする必要があります。

文にユーザー定義演算子が含まれている場合は、その文全体をその演算子が定義されているデータベース・ノードにリモート・マップする必要があります。

ルールJ: 重複するバインド変数を含む文はリモート・マップできません。

この制限を回避するには、一意のバインド変数を使用して数値でバインドします。