この章では、Oracle Database Gatewayの主要な機能について説明します。この章の内容は、次のとおりです。
SQLとPL/SQLのサポート
異機種間レプリケーション
パススルーSQL
結果セットのサポート
データ・ディクショナリ変換
日時データ型
2フェーズ・コミット・プロトコル
ピース単位のLONGデータ型
SQL*PlusのDESCRIBEコマンド
分散環境におけるSQLの制約
Oracleのオプティマイザと異機種間サービス
|
注意: この章で説明する機能は、すべての異機種間サービスのゲートウェイで使用可能であるとはかぎりません。これらの機能に対する汎用サポート(異機種間サービスで提供)が必要であるのみでなく、そのドライバのサポートも追加する必要があります。ご使用のゲートウェイに特定の機能がサポートされているかどうかは、該当するゲートウェイのマニュアルを参照して判断してください。 |
SQL文の変換とデータ型のマッピングは、機能に基づいて実行されます。PL/SQLコールは、Oracle以外のシステムのストアド・プロシージャにマップされます。SQL文に関してリモート・システムに機能がない場合は、単純な問合せが発行されるか、文が複数の問合せに分割されます。その後、Oracleデータベースでの後処理によって必要な結果が得られます。
異機種間サービスでは、ほとんどの場合はOracle以外のシステムをOracle分散セッションに取り込むことができますが、これにはいくつかの制限があります。一般的な制限事項を次に示します。
SQL文のCONNECT BY句に対するサポートはありません。
ROWIDのサポートには制限があります。詳細は、個々のゲートウェイのドキュメントを参照してください。Oracle Universal ROWIDデータ型は、異機種間サービスを使用するどのゲートウェイでもサポートされません。
ラージ・オブジェクト(LOB)、抽象データ型(ADT)および参照データ型(REF)はサポートされません。
リモート・パッケージはサポートされません。
リモート・ストアド・プロシージャでは、REF CURSOR型のout引数は指定できますが、inまたはin-outオブジェクトは使用できません。
Oracle異機種間サービス・エージェントでは、共有データベース・リンクはサポートされません。
|
注意: 各ゲートウェイには、前述の一般的な制限事項に加えて、付加的な制限事項が存在する場合があります。製品の制限事項の全リストは、個々のゲートウェイのマニュアルを参照してください。 |
Oracle以外のシステムとOracle Databaseの間では、マテリアライズド・ビューを使用してデータをレプリケートできます。
マテリアライズド・ビューは、特定の時点でOracle以外のマスター・サイトの表からキャプチャされたデータをインスタンス化します。この時点はリフレッシュ操作によって定義され、リフレッシュ操作が、このデータをOracle Databaseにコピーし、Oracleシステム上のコピーをOracle以外のシステムのマスター・コピーと同期します。その後、マテリアライズド・データがOracle Databaseでビューとして使用できるようになります。
レプリケーション機能は、リフレッシュをスケジュールし、マテリアライズド・ビューを管理しやすいようにレプリケーション・グループに収集するためのメカニズムを提供します。リフレッシュ・グループにより、複数のマテリアライズド・ビューをシングル・オブジェクトと同様にリフレッシュできます。
異機種間レプリケーションのサポートは、必ずOracle間レプリケーション機能全体のサブセットに限定されます。
プライマリ・サイトにすることができるのは、Oracle以外のシステムのみです。マテリアライズド・ビューはOracle Databaseにしか作成できないためです。
マテリアライズド・ビューでは、完全リフレッシュを使用する必要があります。これは、高速リフレッシュを使用するには、Oracle以外のシステムでOracle固有の機能が必要になるためです。
タイプによっては、Oracle以外のシステム上で表を参照する目的では作成できないマテリアライズド・ビューがあります。主キーと副問合せのマテリアライズド・ビューはサポートされますが、ROWIDとOBJECT IDのマテリアライズド・ビューはサポートされません。これは、ROWIDの書式と内容についてはSQL規格がなく、Oracle以外のシステムにはOracleオブジェクトが実装されていないためです。
Oracleの異機種間サービス機能を介したOracle以外のデータへのアクセスには、その他の制限が適用されます。次に最も重要な制限事項を示します。
固定ビューにマップされる表列のOracle以外のデータ型には、Oracleデータ型との互換性(つまりマッピング)が必要です。通常、このことは、ANSI SQL規格により定義されたデータ型について該当します。
副問合せのマテリアライズド・ビューでは、Oracle以外の個々のシステムにより制限される言語機能を使用できない場合があります。異機種間サービスは、多くのケースで、Oracle Database内で問合せを処理することでそのような言語機能をサポートします。場合によっては、異機種間サービスが問合せを実行するまで、Oracle以外のシステムに制限があることがわからないこともあります。
次の例に、Oracle以外のシステムからOracleデータ・ストアにデータをレプリケートする3つのマテリアライズド・ビューの基本設定と使用例を示します。
|
注意: 次の例で、remote_dbはOracle DatabaseからアクセスするOracle以外のシステムを指します。
これらの例を環境にあわせて変更してください。そのままの状態では実行しないでください。 |
例1: 異機種間レプリケーションに使用するマテリアライズド・ビューの作成
この例では、以降の例に使用する3つのマテリアライズド・ビューを作成します。
customer@remote_db表の主キーのマテリアライズド・ビューを作成します。
CREATE MATERIALIZED VIEW pk_mv REFRESH COMPLETE AS
SELECT * FROM customer@remote_db WHERE "zip" = 94555;
orders@remote_db表およびcustomer@remote_db表の副問合せのマテリアライズド・ビューを作成します。
CREATE MATERIALIZED VIEW sq_mv REFRESH COMPLETE AS
SELECT * FROM orders@remote_db o WHERE EXISTS
(SELECT c."c_id" FROM customer@remote_db c
WHERE c."zip" = 94555 and c."c_id" = o."c_id" );
remote_db上の複数の表からのデータの複合マテリアライズド・ビューを作成します。
CREATE MATERIALIZED VIEW cx_mv
REFRESH COMPLETE AS
SELECT c."c_id", o."o_id"
FROM customer@remote_db c,
orders@remote_db o,
order_line@remote_db ol
WHERE c."c_id" = o."c_id"
AND o."o_id" = ol."o_id";
例2: 異機種間レプリケーションに使用するリフレッシュ・グループの設定
BEGIN
dbms_refresh.make('refgroup1',
'pk_mv, sq_mv, cx_mv',
NULL, NULL);
END;
/
例3: 3つのマテリアライズド・ビューすべての強制リフレッシュ
BEGIN
dbms_refresh.refresh('refgroup1');
END;
/
|
関連項目: マテリアライズド・ビューとレプリケーション機能の詳細は、『Oracle Databaseアドバンスト・レプリケーション』を参照してください。 |
パススルーSQL機能を使用すると、文を最初にOracle Databaseで解析せずに直接Oracle以外のシステムに送ることができます。この機能は、Oracle以外のシステムでOracleに等価文のない文での操作が見込まれる場合に役立ちます。
この項には、次の項目が含まれます。
DBMS_HS_PASSTHROUGHパッケージの使用
パススルーSQLの使用による影響の検討
パススルーSQL文の実行
PL/SQLのDBMS_HS_PASSTHROUGHパッケージを使用すると、Oracle以外のシステムで直接パススルーSQL文を実行できます。このパッケージで実行される文は、標準のSQL文と同じトランザクションで実行されます。
DBMS_HS_PASSTHROUGHパッケージは仮想パッケージです。概念上は、Oracle以外のシステムに常駐します。ただし、実際には、このパッケージのコールは異機種間サービスにより仲介され、1つ以上の異機種間サービス・コールにマップされます。次に、これらの異機種間サービス・コールは、ドライバによりOracle以外のシステムのAPIにマップされます。クライアント・アプリケーションは、Oracle以外のシステムのストアド・プロシージャをコールする場合と同じ方法で、データベース・リンクを介してパッケージ内のプロシージャをコールします。異機種間サービスにより実行される特殊処理は、ユーザーに対して透過的です。
|
関連項目: このパッケージの詳細は、『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照してください。 |
Oracle以外のシステムでトランザクションを暗黙的にコミットまたはロールバックするパススルーSQL文を実行すると、そのトランザクションに影響します。たとえば、一部のシステムでは、データ定義言語(DDL)文を含むトランザクションが暗黙的にコミットされます。Oracle Databaseは迂回されるため、トランザクションがOracle以外のシステムにコミットされたことを認識しません。そのため、Oracle Databaseではトランザクションがコミットされない間に、Oracle以外のシステムでデータがコミットされる可能性があります。
Oracle Databaseでトランザクションがロールバックされると、Oracle DatabaseとOracle以外のシステム間でデータに一貫性がなくなる可能性があります。このような状況では、グローバルなデータ非一貫性が発生します。
アプリケーションで通常のCOMMIT文を実行すれば、Oracle DatabaseはOracle以外のシステムと分散トランザクションを調整できることに注意してください。パススルー機能を使用して実行される文は、分散トランザクションの一部となります。
次の表に、DBMS_HS_PASSTHROUGHパッケージで提供されるファンクションとプロシージャを示します。これらを使用してパススルーSQL文を実行できます。
INSERT
UPDATE
DELETE
DDL
非問合せ文を実行するには、EXECUTE_IMMEDIATEファンクションを使用します。たとえば、データベース・リンクsalesdbを使用してアクセスできるOracle以外のシステムでDDL文を実行するには、次のように入力します。
DECLARE
num_rows INTEGER;
BEGIN
num_rows := DBMS_HS_PASSTHROUGH.EXECUTE_IMMEDIATE@salesdb
('CREATE TABLE dept1 (n SMALLINT, loc CHARACTER(10))');
END;
変数num_rowsには、実行された文によって影響を受ける行数が割り当てられます。DDL文の場合は、0(ゼロ)が戻されます。EXECUTE_IMMEDIATEファンクションでは問合せを実行できず、バインド変数を使用できないことに注意してください。
バインド変数を使用すると、同じSQL文に様々な値を指定して複数回使用できるため、SQL文に必要な解析回数が減少します。たとえば、表に4行挿入する場合は、SQL文を1回解析し、行ごとにバインドして実行できます。1つのSQL文に0個以上のバインド変数を使用できます。
バインド変数を使用してパススルーSQL文を実行する手順は、次のとおりです。
カーソルをオープンします。
Oracle以外のシステムでSQL文を解析します。
変数をバインドします。
Oracle以外のシステムでSQL文を実行します。
カーソルをクローズします。
図3-1に、バインド変数を使用した非問合せ実行のフロー図を示します。
文でバインド変数を指定する方法は、Oracle以外のシステムの構文により決定されます。たとえば、Oracleシステムでは、先行コロンを使用してバインド変数を定義します。次に例を示します。
... UPDATE emp SET sal=sal*1.1 WHERE ename=:ename; ...
この文で、enameはバインド変数です。Oracle以外のシステムでは、バインド変数の指定に疑問符が必要になる場合があります。次に例を示します。
... UPDATE emp SET sal=sal*1.1 WHERE ename= ?; ...
バインド変数の手順では、ホスト・プログラム変数(この場合はPL/SQL)をこれらの各バインド変数と位置的に関連付ける必要があります。たとえば、前述の文を実行するには、次のPL/SQLプログラムを使用します。
DECLARE
c INTEGER;
nr INTEGER;
BEGIN
c := DBMS_HS_PASSTHROUGH.OPEN_CURSOR@salesdb;
DBMS_HS_PASSTHROUGH.PARSE@salesdb(c,
'UPDATE emp SET SAL=SAL*1.1 WHERE ename=?');
DBMS_HS_PASSTHROUGH.BIND_VARIABLE@salesdb(c,1,'JONES');
nr:=DBMS_HS_PASSTHROUGH.EXECUTE_NON_QUERY@salesdb(c);
DBMS_OUTPUT.PUT_LINE(nr||' rows updated');
DBMS_HS_PASSTHROUGH.CLOSE_CURSOR@salesdb(c);
END;
問合せでは、非問合せとは異なり、SELECT文から結果セットが取得されます。結果セットは、カーソルの使用により取得されます。
図3-2に、パススルーSQL問合せのステップを示します。システムでSELECT文が解析された後、FETCH_ROWプロシージャで結果セットの各行を取得できます。行が取得された後、GET_VALUEプロシージャを使用してSELECT構文のリスト項目をプログラム変数に取り出します。すべての行が取得された後に、カーソルをクローズできます。
すべての行を取得する必要はありません。カーソルのオープン後は、いつでもカーソルをクローズできます。
次の例では、問合せが実行されます。
DECLARE
val VARCHAR2(100);
c INTEGER;
nr INTEGER;
BEGIN
c := DBMS_HS_PASSTHROUGH.OPEN_CURSOR@salesdb;
DBMS_HS_PASSTHROUGH.PARSE@salesdb(c,
'select ENAME
from EMP
where DEPTNO=10');
LOOP
nr := DBMS_HS_PASSTHROUGH.FETCH_ROW@salesdb(c);
EXIT WHEN nr = 0;
DBMS_HS_PASSTHROUGH.GET_VALUE@salesdb(c, 1, val);
DBMS_OUTPUT.PUT_LINE(val);
END LOOP;
DBMS_HS_PASSTHROUGH.CLOSE_CURSOR@salesdb(c);
END;
SELECT文の解析後は、FETCH_ROWファンクションが0(ゼロ)を戻すまで、ループ内で行がフェッチされて出力されます。
各種リレーショナル・データベースでは、ストアド・プロシージャで結果セット(1つ以上の行セット)を戻すことができます。
従来、データベースのストアド・プロシージャの動作は、高水準プログラミング言語のプロシージャと同じでした。引数の数は一定で、IN、OUTまたはIN OUT型を使用できました。プロシージャにn引数が指定されている場合は、結果として最大n個の値が戻されます。ただし、ストアド・プロシージャでSELECT * FROM empなどの問合せを実行して結果を戻す必要がある場合があります。emp表の列数は固定ですが、プロシージャの作成時には行数を指示する手段がありません。このため、このような問合せの結果を戻す従来のストアド・プロシージャを作成できませんでした。その結果、複数のリレーショナル・データベース・ベンダーがストアド・プロシージャから結果セットを戻す機能を追加していますが、戻す方法はリレーショナル・データベースごとに異なっています。
Oracleには、REF CURSORというデータ型が用意されています。ストアド・プロシージャでは、他のすべてのOracleデータ型と同様に、このデータ型をINまたはOUT引数として使用できます。Oracle Databaseでは、ストアド・プロシージャにはREF CURSOR型の出力引数が必要です。次に、SQL文のカーソルをオープンし、その出力パラメータのそのカーソルにハンドルを置きます。これにより、コール元は他のカーソルの場合と同じ方法でREF CURSORから取得できます。
Oracle Databaseは、結果セットを戻す以外に多くの処理を行うことができます。REF CURSORデータ型をPL/SQLルーチンに入力引数として渡し、クライアント・プログラムとPL/SQLルーチン間、または複数のPL/SQLルーチン間でやり取りできます。
この項には、次の項目が含まれます。
Oracle以外のシステムでの結果セットのサポート
異機種間サービスでの結果セットのサポート
Oracle以外の複数のシステムで、ストアド・プロシージャにより結果セットを戻すことができますが、その方法は異なります。通常、Oracle以外のデータベースでの結果セットのサポートは次の2つのモデルのいずれかに基づいています。
モデル1: 結果セットのサポート
ユーザーは、ストアド・プロシージャの作成時に、そのストアド・プロシージャが戻すことのできる結果セットの最大数を明示的に指定できます。実行時には、ストアド・プロシージャは0(ゼロ)から指定された最大数の範囲内で結果セットをオープンできます。ストアド・プロシージャの実行後に、クライアント・プログラムは埋込みSQLディレクティブを使用するか、クライアントのライブラリ・ファンクションをコールして、これらの結果セットへのハンドルを取得できます。その後、クライアント・プログラムは、通常のカーソルと同様に結果セットから取得できます。
モデル2: 結果セットのサポート
このモデルでは、ストアド・プロシージャから戻される結果セット数の制限は指定されていません。モデル1とOracle Databaseにはどちらも制限があります。Oracle Databaseでは、ストアド・プロシージャから戻すことができる結果セットの数はREF CURSOR OUT引数の数以下です。モデル1では、ストアド・プロシージャ言語のディレクティブを使用して上限が指定されます。モデル2がOracle Databaseおよびモデル1と異なるもう1つの点は、これらでは結果セットに対するハンドルが戻されないことです。かわりに、これらはストアド・プロシージャから戻された結果セット全体を送信します。Oracle DatabaseではハンドルはREF CURSOR OUT引数です。モデル1では、これはストアド・プロシージャの実行後に別に取得されます。Oracle Databaseとモデル1の両方で、ハンドルが取得された後で、ハンドルに対するフェッチを実行して結果セットのデータが取得されます。複数のカーソルが開いており、任意の順序でフェッチすることができます。ただし、モデル2のケースでは、すべてのデータがすでに送信されています。ストアド・プロシージャによって決定された順序で結果セットが届き、プロシージャの出力引数が最後に届きます。最初の結果セット全体を取得してから2番目の結果セット全体を取得し、すべての結果セットを取得するまで続ける必要があります。最後に、ストアド・プロシージャのOUT引数が取得されます。
結果セットのサポートは、Oracle以外のデータベースではそれぞれ異なっています。これらすべてをOracleのREF CURSORモデルにマップする必要があります。Oracle以外のシステム間では動作が異なるため、異機種間サービスでの結果セットのサポートは、接続先となるOracle以外のシステムに応じて2つの方法のいずれかになります。
異機種間サービスでの結果セットのサポートについては、次の注意事項があります。
結果セットのサポートは異機種間サービスの汎用コードに含まれますが、この機能をゲートウェイで動作させるには、ドライバもこれを実装する必要があります。すべてのドライバが結果セットのサポートを実装しているわけではありません。ゲートウェイがサポートされることを確認する必要があります。
異機種間サービスでは、ストアド・プロシージャからのREF CURSOR OUT引数がサポートされます。INおよびIN OUT引数はサポートされません。
REF CURSOR OUT引数は、すべて匿名参照カーソルです。異機種間サービスで戻されるREF CURSORには型がありません。
Oracle以外のシステムのストアド・プロシージャから戻される各結果セットは、OracleドライバによりREF CURSOR型のOUT引数にマップされます。クライアント・プログラムは、REF CURSOR型の複数のOUT引数を持つストアド・プロシージャを検知します。ストアド・プロシージャの実行後に、クライアント・プログラムはOracleストアド・プロシージャにより戻されるREF CURSORの場合と同じ方法で、そのREF CURSORからフェッチできます。3.4.1.1項で説明したように、異機種間サービスはゲートウェイへの接続時にカーソル・モードになります。
特定のストアド・プロシージャが戻すことのできる結果セットには最大数があります。戻される結果セットの数は、ストアド・プロシージャのREF CURSOR OUT引数の数以下です。戻される結果セットの数は、この上限より少なくてもかまいませんが、上限を超えることはできません。
3.4.1.2項で説明したシステムの場合、戻すことのできる結果セットの最大数はありません。モデル1(3.4.1.1項)の場合は、プロシージャが戻すことのできる結果セットの最大数、およびドライバが異機種間サービスに戻すことのできる結果セットの最大数は、REF CURSOR OUT引数の数により、ストアド・プロシージャに指定されています。ストアド・プロシージャの実行時に、戻される結果セットが最大数より少なければ、その他のREF CURSOR OUT引数はNULLに設定されます。
モデル2のデータベース・サーバーのもう1つの問題は、データベースによって送信された順序で結果セットを取得する必要があることです。このため、異機種間サービスがこれらのデータベースに接続するときにカーソル・モードで実行できません。これらのストアド・プロシージャによって戻される結果セットにアクセスするには、異機種間サービスを逐次モードにする必要があります。
逐次モードでは、ドライバから戻されるプロシージャ記述に次の情報が含まれます。
リモート・ストアド・プロシージャのすべての入力引数
出力引数はなし
REF CURSOR型のOUT引数1つ(ストアド・プロシージャから戻される最初の結果セットに対応)
クライアントは、このREF CURSORからフェッチし、仮想パッケージ・ファンクションDBMS_HS_RESULT_SET.GET_NEXT_RESULT_SETをコールして、次の結果セットに対応するREF CURSORをフェッチします。すべての結果セットが取得されるまでこのファンクション・コールが繰り返されます。最後に戻される結果セットは、リモート・ストアド・プロシージャのOUT引数となります。
逐次モードの主な制限事項は、次のとおりです。
リモート・ストアド・プロシージャから戻された結果セットは、送信された順に取得される必要があります。
ストアド・プロシージャが実行されると、以前に実行されたストアド・プロシージャから戻された結果セットがすべて(データが取得されたかどうかに関係なく)クローズされます。
|
関連項目: ゲートウェイを介した結果セットのサポート方法の詳細は、ご使用のゲートウェイ固有のマニュアルを参照してください。 |
ほとんどのデータベース・システムには、なんらかの形式のデータ・ディクショナリがあります。データ・ディクショナリは、システムの各種ユーザーにより作成されたデータベース・オブジェクトに関する情報のコレクションです。リレーショナル・データベースの場合、データ・ディクショナリはデータベース内のデータに関する情報を含む表およびビューのセットです。この情報には、システムを使用するユーザーやユーザーが作成したオブジェクト(表、ビュー、トリガーなど)に関する情報が含まれます。ほとんどすべてのデータ・ディクショナリには(データベース・システムに関係なく)同じ情報が含まれていますが、情報の編成方法はデータベース・システムごとに異なります。
たとえば、Oracleのデータ・ディクショナリ・ビューALL_CATALOGには、データベース内の表、ビューおよび順序のリストが表示されます。これには3つの列があり、1列目はオブジェクトの所有者名を示すOWNER、2列目はオブジェクト名を示すTABLE_NAME、3列目はデータ型を示すTABLE_TYPEです。このフィールドの値は、オブジェクト型に応じてTABLE、VIEW、SEQUENCEなどです。ただし、Sybaseの場合、同じ情報がsysusersおよびsysobjectsという2つの表に格納され、その列名はOracleのALL_CATALOG表の列名とは異なります。また、Oracle Databaseでは、テーブルのタイプはTABLEまたはVIEWの値で始まります。たとえば、Sybaseでは、Uはユーザー表、Sはシステム表、Vはビューを意味します。
クライアント・プログラムがSybaseシステムにあるALL_CATALOG表からの情報を必要とする場合は、ALL_CATALOG@database_linkを参照する問合せをゲートウェイに送信します。この問合せは、異機種間サービスによりsystablesの該当する問合せに変換されてから、たとえば、Sybaseシステムに送信されます。
SELECT SU."name" OWNER, SO."name" TABLE_NAME, DECODE(SO."type", 'U ','TABLE', 'S ', 'TABLE', 'V ', 'VIEW') TABLE_TYPE FROM "dbo"."sysusers"@remote_db SU, "dbo"."sysobjects"@remote_db SO WHERE SU."uid" = SO."uid" AND (SO."type" = 'V' OR SO."type" = 'S' OR SO."type" = 'U');
Oracleデータ・ディクショナリ表に対する問合せの変換を、Oracle以外のシステムのデータ・ディクショナリ表に対する同等の問合せに反映するには、そのOracle以外のシステムのためのデータ・ディクショナリ変換が異機種間サービスで必要です。データ・ディクショナリ変換は、Oracle以外のシステムの1つ以上のデータ・ディクショナリ表(Oracleのデータ・ディクショナリ表と列名や形式が同じ)に対するビューの定義(すなわちSELECT文)です。ほとんどのデータ・ディクショナリ変換はこの例ほど単純ではありません。多くの場合、情報は多数の表に分散しているため、データ・ディクショナリ変換はそれらの表の複雑な結合になります。
場合によっては、Oracle以外のシステムに情報が存在していないため、Oracleデータ・ディクショナリ表に変換が含まれないこともあります。このような場合、ゲートウェイは変換をアップロードできないため、疑似実行と呼ばれる別のアプローチを実装することがあります。ゲートウェイがデータ・ディクショナリ表を疑似実行する場合、ゲートウェイは異機種間サービスに情報を提供し、異機種間サービスはローカル・データベースを問い合せてデータ・ディクショナリ表の説明を取得します。データの取得を求められると、行が選択されなかったとレポートします。
Oracle Databaseには次の5つの日時データ型があります。
TIMESTAMP
TIMESTAMPWITHTIMEZONE
TIMESTAMPWITHLOCALTIMEZONE
INTERVALYEARTOMONTH
INTERVALDAYTOSECOND
異機種間サービスの汎用コードは、SQLおよびストアド・プロシージャにおいてはOracle日時データ型をサポートします。ただし、異機種間サービスでは、データ・ディクショナリ変換やデータ・ディクショナリ変換を伴う問合せでは、これらのデータ型がサポートされません。
異機種間サービスの汎用コードで日時データ型がサポートされていても、特定のゲートウェイに対するサポートは、Oracle以外のシステム用のドライバに日時のサポートが実装されているかどうかによって異なります。Oracle以外のシステムに制限があるため、サポートがドライバに実装されていても、サポートは部分的になる場合があります。詳細は、ご使用のゲートウェイのドキュメントを参照してください。
ユーザーは、Oracle以外のシステムのタイムスタンプ書式をゲートウェイ初期化ファイル内で設定する必要があります。設定するパラメータは、HS_NLS_TIMESTAMP_FORMATおよびHS_NLS_TIMESTAMP_TZ_FORMATです。また、ユーザーは初期化ファイル内でHS_TIME_ZONEを設定し、Oracle以外のシステムのローカル・タイム・ゾーンも設定する必要があります。
|
関連項目: 日時データ型の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。 |
異機種間サービスは、2フェーズ・コミット・プロトコルを実装するためのインフラストラクチャを提供します。そのサポート範囲はゲートウェイおよびリモート・システムに応じて異なります。詳細は、ご使用のゲートウェイのドキュメントを参照してください。
|
関連項目: 2フェーズ・コミット・プロトコルの詳細は、『Oracle Database管理者ガイド』を参照してください。 |
以前のバージョンのゲートウェイでは、LONGデータ型のサポートが限定されていました。LONGは、最大2GBの文字またはRAWデータ(LONG RAW)を格納するOracleのデータ型です。これらの旧バージョンでは、LONGデータは単一のピースとして扱われていたため、LONGデータのサイズが4MBに制限されていました。このため、処理できるデータのサイズにメモリーとネットワーク帯域幅という制限が課されていました。現行のゲートウェイの機能は、異機種間で2GBのLONGデータ全体をサポートするように拡張されました。ゲートウェイによって、データがエージェントとOracle Database間でピース単位で処理されるようになり、大容量のメモリーとネットワーク帯域幅の要件がなくなりました。
異機種間サービスの初期化パラメータHS_LONG_PIECE_TRANSFER_SIZEを使用すると、転送されるピースのサイズを設定できます。たとえば、異機種間ソースから2GBのLONGデータを取得する場合を考えます。ピースを小さくすると、必要なメモリーは少なくなりますが、すべてのデータを取得するために必要なラウンドトリップは増加します。ピースを大きくすると、ラウンドトリップ回数は減少しますが、内部的に中間ピースを格納するために必要なメモリー容量が増大します。そのため、初期化パラメータを使用して最適のパフォーマンス(つまり、ラウンドトリップ回数とメモリー所要量との最適なトレードオフ)が得られるようにシステムをチューニングできます。初期化パラメータを設定しない場合、デフォルトのピース・サイズとして64KBが使用されます。
|
注意: この機能を、クライアント側のLONGデータに対するピース単位操作と混同しないでください。クライアント側でのピース単位のFETCHおよびINSERT操作は、旧バージョンのゲートウェイで動作しており、今後も動作します。クライアント側での唯一の違いは、旧バージョンのゲートウェイでフェッチできるLONGデータは最大4MBのみであったのに対して、このバージョンでは2GBのLONGデータを取得できることです。4MBはこのデータ型の最大容量のわずか0.2%であるため、これは大幅な改善です。 |
SQL*Plus DESCRIBEコマンドを使用してOracle以外のシステムのオブジェクトを記述できます。ただし、いくつかの制限事項があります。たとえば、異機種間リンクを使用した場合には、パッケージ、順序、シノニムまたは型を記述できません。
この項では、分散環境におけるSQLに対する制約について説明します。これらの制約は、Oracle以外のシステムまたはリモートOracleデータベースへのアクセスが行われる分散環境に適用されます。
この項には、次の項目が含まれます。
リモート参照と異機種間参照
重要な制限事項
|
注意: 異機種間アクセスに関するルールの多くは、リモート参照にも適用されます。詳細は、『Oracle Database管理者ガイド』の分散データベースに関する項を参照してください。 |
文は、制限付きではありますが、その文で参照されているデータベース・ノードまたはローカル・ノード上で実行できます。参照されるオブジェクトすべてが1つの参照先ノードに解決される場合、Oracleはそのノードで問合せの実行を試みます。/*+ REMOTE_MAPPED */または/*+ DRIVING_SITE */ヒントを使用すると、参照先ノードで強制的に実行できます。文が発行された場所とは異なるノードに転送される場合、その文をリモート・マップ文と呼びます。
リモート・マップ文に対しては、完全なデータ型チェックのサポートがあります。チェックの結果により、一貫したデータ型チェックと完全なデータ型の強制が提供されます。
|
関連項目: 4.5項「Oracleデータベース・サーバーのSQL構文の処理」 |
文のリモート・マップを可能にする方法には、特定のルールまたは制限が適用されます。これらのルールが遵守されていない場合、エラーが発生します。発行される文にこれらのルールすべてとの一貫性があるかぎり、ルールの適用順序は関係ありません。ルールや制限については、3.10.2項を参照してください。
分散環境でのリモート・マッピングにSQLを使用する場合は、異なる制約が存在します。この分散環境には、Oracle Database Gatewayを介してアクセスされるOracle以外のデータベースのみでなく、リモートのOracleデータベースも含めることができます。
次の項では、分散環境でリモート・マッピングに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つの特殊な事例には、USER、USERENVおよび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文は、リモート・マップできません。
つまり、INSERT、UPDATE、DELETEの場合、SQL文は実行できません(ルールBを参照)。ただし、サポートされていない演算子または構成メンバーが、コールバック・リンクで実行できる場合、SQL文を実行できる場合があります。
SELECTの場合は、その他のルールが対象の文をリモート・マップするように要求していないかぎり、このルールの影響を受ける文でも常に実行できます。このルールの影響を受けるSELECT文は、リモートのSELECT操作を介して必要なすべてのデータをフェッチし、サポートされない演算子を処理するか、ローカルSQLエンジンを使用してローカルに構成することにより実行されます。
リモートのSELECT操作とは、ローカル表データの行を取得する操作とは異なり、リモート表データの行を取得する操作です。リモートSELECTの場合の最悪のケースは、全表スキャンです。全表スキャンは、リモート表のすべてのデータをネットワークを介してフィルタせずにフェッチすることです(SELECT * FROM EMPなど)。
全表スキャンは高コストであるため、Oracleでは回避するよう試みます。リモート表に使用可能な索引がある場合は、ネットワークでフェッチされる行の数を減らすために、これらの索引をWHERE句の条件で使用します。
Oracle Databaseにより生成されたSQL文をチェックするには、その文を記述し、REMOTE操作ごとにEXPLAIN PLAN表のOTHER列を問い合せます。
|
関連項目: リモート参照を含むEXPLAIN PLANを解析する方法の詳細は、3.11.1項を参照してください。 |
たとえば、次の文を考えてみます。
SELECT COUNT(*) FROM emp@remote_db WHERE hiredate < sysdate;
この文では次の出力が戻されます。
COUNT(*)
----------
14
1 row selected.
リモート表スキャンは次のとおりです。
SELECT hiredate FROM emp;
sysdateはremote_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文にSEQUENCEまたは順序が含まれている場合は、その文を各順序が常駐するサイトにマップする必要があります。
リモートではOracle以外の順序はサポートされないため、このルールが異機種間アクセス・モジュールに適用されることはありません。
ルールI: 文に1つ以上のユーザー定義演算子が含まれている場合は、その文を各演算子が定義されているノードにマップする必要があります。
文にユーザー定義演算子が含まれている場合は、その文全体をその演算子が定義されているデータベース・ノードにリモート・マップする必要があります。
ルールJ: 重複するバインド変数を含む文はリモート・マップできません。
この制限を回避するには、一意のバインド変数を使用して数値でバインドします。
Oracleのオプティマイザを異機種間サービスと併用できます。異機種間サービスは、Oracle以外のシステムのそれぞれの表について特定の表および索引統計情報を収集し、この情報をOracle Databaseに渡します。Oracleのコストベース・オプティマイザは、この情報を問合せ計画の作成時に使用します。
その他にも、コストベース・オプティマイザでは複数の最適化が実行されます。最も重要な最適化は、リモート・ソートの排除とリモート結合です。
この項には、次の項目が含まれます。
例: 索引統計と表統計の使用
例: リモート結合の最適化
Oracle以外のアクセスに対するオプティマイザの制限
Oracleデータベースに10行の表を作成する次の文を考えてみます。
CREATE TABLE T1 (C1 number);
DBMS_STATSパッケージを使用して表を分析します。次に例を示します。
DBMS_STATS.GATHER_TABLE_STATS ('SCOTT','T1');
DBMS_STATS.GENERATE_STATS ('SCOTT','T1');
前述の例では、スキーマ名をSCOTTとし、表名をT1としています。DBMS_STATSパッケージの詳細は、『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照してください。
Oracle以外のシステムに1000行を含む表を作成します。
次のSQL文を発行します。
SELECT a.* FROM remote_t1@remote_db a, T1 b
WHERE a.C1 = b.C1;
Oracleオプティマイザは、エージェントに対して次のSQL文を発行します。
SELECT C1 FROM remote_t1@remote_db;
この文は、Oracle以外のシステムから1000行すべてをフェッチし、Oracleデータベース内で結合を実行します。
remote_t1表のC1列に一意の索引を追加して同じSQL文を再発行すると、エージェントはローカルt1のC1の値ごとに次のSQL文を受信します。
... SELECT C1 FROM remote_t1@remote_db WHERE C1 = ?; ...
|
注意: ?はバインド・パラメータ・マーカーです。また、Oracleにより生成されたバインド変数を含む結合条件は、ネステッド・ループ結合方法についてのみ生成されます。 |
SQL実行計画を確認するには、SQL文のEXPLAIN PLANを生成します。最初に、adminディレクトリにutlxplanをロードします。
次のように入力します。
EXPLAIN PLAN FOR SELECT a.* FROM remote_t1@remote_db a, T1 b
WHERE a.C1 = b.C1;
次の文を入力してutlxplsユーティリティ・スクリプトを実行します。
@utlxpls
OPERATION REMOTEは、リモートSQLが参照されていることを示します。
どの文が送信されるかを確認するには、次の文を入力します。
SELECT ID, OTHER FROM PLAN_TABLE WHERE OPERATION = 'REMOTE';
ここでは、Oracleデータベースのリモート結合最適化機能の例を示します。
|
注意: Oracle以外のシステムからの表を使用するEXPLAIN PLANは、ローカルまたはリモートのOracle表スキャンを使用する同様の文とは異なる場合があります。これは、Oracle以外の表についてOracleで使用可能な統計に制限があるためです。最も重要なのは、Oracle以外の表の非一意索引には列を選択できないことです。使用可能な統計に制限があるため、次の例はリモート結合を実際に実行したときの内容とは異なる場合があり、あくまでも一例にすぎません。 |
次の例を考えてみます。
EXPLAIN PLAN FOR SELECT e.ename, d.dname, f.ename, f.deptno FROM dept d, emp@remote_db e, emp@remote_db f WHERE e.mgr = f.empno AND e.deptno = d.deptno AND e.empno = f.empno; @utlxpls
次のような出力が表示されます。
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost
| Inst |IN-OUT|
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2000 | 197K| 205 |
|* 1 | HASH JOIN | | 2000 | 197K|
205 |
| 2 | TABLE ACCESS FULL | DEPT | 21 | 462 | 2 |
|* 3 | HASH JOIN | | 2000 | 154K|
201 |
| 4 | REMOTE | | 2000 | 66000
| 52 |
| 5 | REMOTE | | 2000 | 92000
| 52 |
---------------------------------------------------------------------------
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Query Block Name / Hint Alias (identified by operation id):
-----------------------------------------------------------
1 - sel$1 / D
2 - sel$1 / D
3 - sel$1 / F
4 - sel$1 / F
5 - sel$1 / E
Predicate Information (identified by operation id):
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
---------------------------------------------------
1 - access("E"."DEPTNO"="D"."DEPTNO")
3 - access("E"."MGR"="F"."EMPNO" AND "E"."EMPNO"="F"."EMPNO")
次の文を発行します。
SET long 300 SELECT other FROM plan_table WHERE operation = 'REMOTE';
次のような出力が表示されます。
OTHER -------------------------------------------------------------------------------- SELECT "EMPNO","ENAME","DEPTNO" FROM "EMP" SELECT "EMPNO","ENAME","MGR","DEPTNO" FROM "EMP" SELECT "EMPNO","ENAME","DEPTNO" FROM "EMP" SELECT "EMPNO","ENAME","MGR","DEPTNO" FROM "EMP"
次に、Oracle以外のシステムへのアクセスに対するオプティマイザの制限を示します。
リモート・オブジェクトに関する列統計情報はありません。このため、適切な実行計画が得られない場合があります。実行計画を検証し、ヒントを使用して最適化してください。
リモート結合を強制するオプティマイザ・ヒントはありません。ただし、リモート問合せブロック最適化を使用すると、問合せをわずかにリライトしてリモート結合を実現することができます。
前項の例の記述は、次の形式にリライトできます。
SELECT v.ename, d.dname, d.deptno FROM dept d,
(SELECT /*+ NO_MERGE */
e.deptno deptno, e.ename ename emp@remote_db e, emp@remote_db f
WHERE e.mgr = f.empno
AND e.empno = f.empno;
)
WHERE v.deptno = d.deptno;
この例では、リモート結合が保証されています。これは、NO_MERGEヒントを使用してネストした問合せ内に分離されるためです。