Oracleデータベースにアクセスする ~oracle_fdwを使いこなすために~
PostgreSQLには、PostgreSQLの外部にある様々なデータに対してアクセスするための仕組みとして、外部データラッパー(FDW: Foreign Data Wrapper)が用意されています。Oracleデータベースにアクセスするための外部データラッパーであるoracle_fdwの使い方については、「Oracleデータベースにアクセスする ~oracle_fdwの基本的な使い方~」で紹介しています。
今回は、oracle_fdwをより効果的に利用するためのポイントについて解説します。
なお、確認に使用した環境は、PostgreSQL 11.1、oracle_fdw 2.1.0、Oracle Instant Client 18.5(OCIライブラリー)、Oracle Database 18c XEです。
1. プッシュダウン(push down)の仕組み
外部データラッパーには、プッシュダウンという機構があり、oracle_fdwにも備わっています。この機構は、クライアントから問合せのあったSQL文に含まれるWHERE句(検索条件)、ORDER BY句(ソート条件)、および、JOIN句(結合条件)の処理を、リモート側で実行させます。なお、WHERE句とJOIN句については、ローカルとリモートとの間のデータ転送量を抑え、通信におけるボトルネックを減少させる効果があります。例えば、外部テーブルの1000件のデータに対してWHERE句で10件に絞り込むようなSELECT文を実行する場合、Oracle側で絞り込みを行い、その結果をPostgreSQL側に送信することで、通信量を100分の1に抑えることができます。
以下に、WHERE句、ORDER BY句、および、JOIN句のプッシュダウンについて、利用上のポイントを解説します。
1.1 WHERE句のプッシュダウン
問合せのSQL文にWHERE句があると、WHERE句に記述されたステートメントがOracleデータベースに渡され、実行されます。その際に注意が必要な点は、WHERE句のステートメントに関数が使われていると、その関数もOracle側で実行されることです。PostgreSQLとOracleデータベースでは、同じ関数名であっても仕様に違いがある場合があります。そのため、WHERE句のステートメントに関数がある場合は、Oracle側の関数仕様を確認しておく必要があります。
ここで、EXPLAINコマンドで実行計画を出力することで、WHERE句がプッシュダウンされることを確認してみます。なお、ANALYZEおよびVERBOSEオプションを指定することにより、Oracle側で実行されるSQL文(Oracle query:)と実行計画(Oracle plan:)も出力します。「Foreign Scan」ブロックがOracle側のテーブルに対する実行計画であり、「Oracle query:」にWHERE句があり、「Oracle plan:」のところに検索条件があることから、WHERE句に記述されたステートメントがOracle側で実行されていることを確認できます。

次に、WHERE句のステートメントにRPAD関数を使用したときの実行結果を見てみます。この関数は、OracleデータベースとPostgreSQLにおいて、マルチバイト文字を使用した場合の実行結果が異なります。以下のSQL文のように、WHERE句ステートメントに、PostgreSQLの仕様を意識して「RPAD(name, 8, '*') = 'あいう*****'」と指定しても、このSQL文が実行されるときにWHERE句ステートメントがプッシュダウンされるため、RPAD関数はOracle側で実行されます。nameカラムに「あいう」というデータが存在しているとき、RPAD(name, 8, '*')の実行結果は「あいう**」になり、WHERE句の条件に合いません。そのため、このSQL文の実行結果は0行になります。

1.2 ORDER BY句のプッシュダウン
Loading component...
Loading component...
Loading component...
Loading component...
Loading component...
1.3 JOIN句のプッシュダウン
問合せのSQL文にJOIN句があると、JOIN句に記述されたステートメントがOracleデータベースに渡され、Oracle側で結合が実行される場合があります。JOIN句のプッシュダウンには、以下の制約などがあるため、確認しておく必要があります。
Loading component...
Loading component...
Loading component...
Loading component...
Loading component...
2. 更新トランザクションの利用
Loading component...
- 外部テーブルを同時更新しないようにする
- 例外「シリアライズの失敗 SQLSTATE(40001)」が発生したら、ROLLBACKして、再度トランザクションを実行する(Oracle側のエラー:「ORA-08177: can't serialize access for this transaction」)
Loading component...
またoracle_fdwは、プリペアドステートメント(PREPARE)、および、2相コミット(PREPARE TRANSACTIONなど)については、Oracleデータベースを含む制御が必要になるため、サポートしていません。
3. データ型の違い
Loading component...
Loading component...
Loading component...
Loading component...
4. 外部テーブル定義の制約とデフォルト値
Loading component...
4.1 制約チェックとデフォルト値適用のタイミング
Loading component...
Loading component...
Loading component...
参考
図2のINSERT文の制約違反エラーのメッセージを示します。DETAILに「ORA-01400:」があることから、Oracleデータベース側でエラーが発生していることが分かります。
Loading component...
4.2 推奨に従わない場合の問題点
外部テーブルを定義する際に、制約やデフォルト値を、連携先のOracle側のテーブル定義の設定に合わせて指定しなかった場合、以下のような問題が発生する場合があるため、注意が必要です。
Loading component...
Loading component...
Loading component...
Loading component...
5. その他の利用時のポイント
oracle_fdwを利用する上での、その他のポイントを以下に示します。
Loading component...
oracle_fdwを実際に利用することを想定し、考慮すべきいくつかの重要な点について解説しました。詳細な点については、oracle_fdwのドキュメントを参照の上、ご利用ください。
2020年3月27日公開
こちらもおすすめ
Loading component...
Loading component...
富士通のソフトウェア公式チャンネル(YouTube)
富士通のミドルウェア製品のご紹介や各種イベント・セミナーの講演内容、デモンストレーションなどの動画をご覧いただけます。











