14 データ・カートリッジの設計

データ・カートリッジを設計する際は、様々な項目について考慮する必要があります。

14.1 プログラミング言語の選択

PL/SQL、C/C++またはJavaのオブジェクト型のメソッドを実装できます。PL/SQLおよびJavaのメソッドは、サーバーのアドレス空間で実行されます。C/C++のメソッドは外部プロシージャとしてディスパッチされ、サーバーのアドレス空間の外部で実行されます。

最善の実装方法は、状況に応じて異なります。次に一部のガイドラインを示します。

  • 通常、CまたはC++が関係するコールアウトは、処理が実際にCPUにバインドされる場合に最も高速です。ただし、コールアウトにはディスパッチのコストが伴い、C/C++での処理量が小さい場合にはそのコストが重要になることがあります。

  • PL/SQLは、計算集中型でないメソッドに最も有効です。通常、大きいコード本体が異なる言語で実装されており、データ・カートリッジでそれを使用できる場合や、広範囲な計算を実行する必要がある場合は、PL/SQLよりも他の実装オプションの方が適切です。

  • Javaは、比較的オープンな実装オプションです。通常、Javaはインタプリタで変換されますが、高パフォーマンスのアプリケーションではメソッドのプリコンパイルやジャストインタイム・コンパイラからメリットを得ている場合があります。

14.2 実行者権限

実行者権限メカニズムを使用すると、ファンクションを実行者の権限で実行できます。そのため、カートリッジは専用スキーマ内で有効であり、カートリッジが常駐するスキーマ内のオブジェクトを操作するための権限がなくても他のスキーマで使用できます。

14.3 コールアウトとLOB

コールアウトとともにLOBを使用する際の考慮事項は、次のとおりです。

  • コールアウトをLOB型(BFILE/BLOB)に依存しないようにコーディングするとメリットがあります。

  • カートリッジのPL/SQLレイヤーでは、コールアウトでBFILE固有のロジックが必要にならないようにBFILEをオープンできます(BFILEを操作しないOCILobコールからのエラー・リカバリの場合以外)。

  • 一時LOBがある場合は、一時LOBを使用して割当てとコールが行われるときに発生する可能性があるディープ・コピーに注意する必要があります。必要に応じてBLOBパラメータにNOCOPY(BY REFERENCE)を使用してください。

14.4 状態の保存と受渡し

従来、外部プロシージャにはステートレス・モデルがあります。外部プロシージャの起動時にオープンされた文ハンドルは、すべてコール終了時に暗黙的にクローズされます。

Oracle Databaseでは、OCI文のハンドルやデータベース内の関連する状態などの状態情報を保存して、1つのセッションで行われる外部プロシージャの複数の呼出しで使用できます。デフォルトでは、カートリッジはステートレスですが、OCIMemoryサービスおよびOCIContextサービスをOCI_DURATION_SESSIONや他の適切な期間とともに使用して、状態を保存できます。1つの外部プロシージャ呼出しで作成された文ハンドルを別の呼び出しで再利用できます。データ・カートリッジの開発者は、これらのハンドルを明示的に解放する必要があります。これは、文ハンドルが不要になったらすぐに行うことをお薦めします。その結果、OCIハンドルおよびデータベース内に保持されているその文のすべての状態が解放されます。これはデータ・カートリッジのスケーラビリティの向上に役立ちます。

関連項目:

『Oracle Database PL/SQL言語リファレンス』

14.5 索引の設計

データ・カートリッジの索引の最適な設計の手引きとなるいくつかの要因について考えます。

14.5.1 ドメイン索引のパフォーマンス

ドメイン索引を作成することが常に最善の方法であるとはかぎりません。ドメイン索引を作成することにした場合は、次の事項に注意してください。

  • 複合ドメイン索引の場合、ファンクション実装は、データ・サイズが小さく、結果がデータ・サイズ全体の大部分を占める場合により適切に動作します。

  • 拡張可能オプティマイザを適切に使用するとパフォーマンスを向上できます。

14.5.2 ドメイン索引のコンポーネント名

ドメイン索引実装の内部コンポーネントに対するネーミングが問題になる場合があります。内部データ・オブジェクトの名前は、通常、表および索引に指定する名前に基づきます。問題は、内部オブジェクトの導出名が他のユーザー定義オブジェクトやシステム・オブジェクトと競合しないようにする必要があることです。この問題を回避するには、名前を制限するなんらかのポリシーを開発するか、なんらかのメタデータ管理方法を実装して、DROPCREATEなどの実行中のエラーを回避します。

14.5.3 索引構成表を使用する場合

特にほとんどのデータが索引に含まれている場合は、2次索引を使用することで、表および独立した索引にデータを格納するよりも処理を効率的に行うことができるため、IOT上に2次索引を作成できます。複数の方法でデータにアクセスする場合は、これによって大きなメリットを得ることができます。Oracle9iより前のリリースでは、IOTに作成できる索引は1つのみでした。

14.5.4 LOBへの索引構造の格納

索引構造をLOBに格納できますが、最適なパフォーマンスが得られるようにLOBを慎重にチューニングしてください。特定のLOBに頻繁にアクセスする場合は、CACHEオプションを指定して表を作成し、LOB索引を個別の表領域に置きます。LOBを頻繁に更新する場合は、TURN OFF LOGGINGを実行し、CHUNKサイズの倍数単位で読み書きします。LOBの特定部分に頻繁にアクセスする場合は、LOBバッファリングまたは独自のバッファリング方法を使用して読取りまたは書込みをバッファに入れます。

14.5.5 外部索引構造

拡張可能索引付けフレームワークでは、ユーザー定義索引の意味と表現をカートリッジ開発者が指定します。Oracleでは、索引構成表のように基本的な索引実装が提供されます。複合索引構造を格納するために、バイナリまたはキャラクタLOBも使用できる場合があります。索引構成表、BLOBおよびCLOBは、すべてデータベース内で有効です。さらに、ユーザー定義索引をBFILEのようなデータベース外部の構造に格納することもできます。

外部索引構造を使用すると、索引を最も柔軟に表現できます。外部索引構造が特に役立つのは、インメモリ索引付け構造の開発に着手している場合です。たとえば、オペレーティング・システム・ファイルに索引データを格納すると、実行時にメモリー・マップ・ファイルに読み取られます。このような場合は、外部索引ルーチンでBFILEとして処理されます。

外部索引構造は優れたパフォーマンスも提供できますが、これにはある程度のコストを伴います。データベース外部の索引構造がデータベースのトランザクション・セマンティクスに関与しない場合、データベース内の索引構造については、データと同時実行される索引更新をアトミックにします。これは、データの更新により拡張可能索引付けインタフェースを介して外部索引の更新が起動される場合に、失敗するとデータ更新はロールバックされますが、索引は更新されないことを意味します。データベースでロールバックできるのは、データベース内部のデータ更新のみで、外部索引構造をデータベース・ロールバックと同期的にロールバックすることはできません。外部索引構造は、読取り専用アクセスの場合に最も有効と思われます。データ更新が関与する場合は、そのセマンティクスが複雑になります。

14.5.6 複数行フェッチ

ODCIIndexFetch()ルーチンがコールされると、演算子述語を満たす行すべてのROWIDが戻されます。ODCIIndexFetch()ルーチンで戻すことのできる最大行数はnrows(nrowsODCIIndexFetch()ルーチンの引数)です。nrowsの値は、なんらかの内部ファクタに基づいてOracleにより決定されます。最適な問合せパフォーマンスを達成するために戻す必要のある適切な行数がわかっている場合は、この行数がnrowsのかわりにODCIRidList VARRAYで戻されるように指定できます。ODCIRidListの値の数がnrows以下である必要があることに注意してください。

カートリッジ設計者は、戻される行数を判断できる最適のユーザーです。たとえば、索引の1500のROWIDがまとめて格納されていて、nrowsが2000の場合は、2000行ではなく1500行を戻すのが最適となります。それ以外の場合、ユーザーは3000個のROWIDを取り出し、その中から2000個を戻す必要があり、1000個のROWIDが戻されないことになります。

特定の最適化を念頭においていない場合は、nrowsの値を使用して戻される行数を決定できます。現在、nrowsの値は2000に設定されています。

コールアウトを使用する索引を実装する場合は、複数行フェッチを使用して最大行数をサーバーにフェッチします。これにより、コールアウトのコストが相殺されます。

関連項目:

ODCIIndexFetch()

14.6 演算子の設計

オプティマイザが索引付けされた実装を使用しないように選択した場合は、すべてのドメイン索引に演算子の索引付き実装とファンクション実装の両方を含む必要があります。ただし、索引付け構造を使用するとファンクションの結果を生成できます。

14.7 拡張可能オプティマイザを考慮した設計

データ・カートリッジは、拡張可能オプティマイザを考慮して設計する方が効率的になる場合があります。

14.7.1 コストと選択性の重み付け

コストを見積もる際に、OracleはCPU、I/Oおよびネットワークの関連コストを考慮します。

14.7.2 ファンクションのコスト

一般的なプロファイラまたはツールを使用して、Cの関数の実行コストを判断できます。SQL問合せの場合は、問合せのEXPLAIN PLANにより問合せのコストの概算見積りが得られます。また、tkprofユーティリティを使用すると、操作に関連するCPUとI/Oのコスト情報を収集できます。さらに、SELECT FROM DUALのSQL問合せにコールアウトを使用し、tkprofを使用してコストを見積もると、コールアウトの実行コストを判断できます。

14.7.2.1 ファンクションの選択性

述語の選択性とは、述語により戻される行数を表の合計行数で除算した値です。選択性は、表の行数に対する、述語により戻される行数の割合です。

選択性ファンクションでは、表について収集された統計を使用して、表の行数のうち引数リストを指定した述語で戻される行数のパーセンテージを判別する必要があります。たとえば、Image SelectedImageよりも大きいイメージを判別する述語IMAGE_GREATER_THAN (Image SelectedImage)の場合は、データベース内のイメージのサイズのヒストグラムを使用して選択性を計算できます。

統計は、述語の選択性とドメイン索引のコストの計算に影響する場合があります。

14.7.2.2 表の統計

表について収集された統計は、述語の選択性の計算に影響する場合があります。つまり、ユーザーは統計を参考にすることで、表および列について収集する必要のある述語の選択性をより適切に判断できます。データを操作できる述語がわかっていれば、収集する統計を決定する際に役立ちます。

たとえば空間ドメインの場合、VARRAY内で空間オブジェクトのノードを含む要素の平均数、最小数および最大数は、収集すると役立つ統計です。

14.7.2.3 索引の統計

ドメイン索引の分析時には、ドメイン索引を構成する基礎となるオブジェクトの統計を分析する必要があります。たとえば、ドメイン索引が表で構成されている場合、ドメイン索引の分析時には統計収集ファンクションで表を分析する必要があります。ドメイン索引にアクセスするコストは、その索引について収集された統計の影響を受ける場合があります。たとえば、ドメイン索引にアクセスするコストは、ドメイン索引へのアクセス時にアクセスされる各種の表の合計データ・ブロック数を選択性で乗算した値として概算できます。

コスト、選択性および統計ファンクションを正確に定義するには、ドメインを十分に理解している必要があります。前述のガイドラインは、コスト、選択性および統計ファンクションの作業中における一部の考慮事項を理解するに当たって参考となることを意図したものです。通常は、デフォルトのコストおよび選択性を使用することから始めて、関心のある問合せの動作を観察することをお薦めします。

14.8 メンテナンスを考慮した設計

データ・カートリッジを設計する際の、メンテナンス関連の考慮事項は次のとおりです。

特にカートリッジで多数のオブジェクト、ビュー、表などをメンテナンスする場合には、ユーザーのためにオブジェクト間のリレーションシップを維持するためのメタデータ表を作成することを検討してください。これにより、カートリッジを開発して使用中にメンテナンスするという複雑さが軽減されます。

14.9 カートリッジのインストールの有効化

  • カートリッジにREADMEを添付して、ユーザーにインストール方法を指示します。

  • 可能な場合は、sqlplus @imginstのようにデータベースにカートリッジを一度にインストールできるようにします。

  • コールアウトを使用する場合は、ユーザーにlistenerの起動方法を指示します。

  • ユーザーにextprocの設定方法を指示します。ほとんどのユーザーにはextprocに関する知識がなく、多くのユーザーはリスナーを設定したことがありません。これは、カートリッジをデプロイする際に重要な問題になります。

  • Oracle Software Packagerを使用すると、instantiate_fileアクションを使用してカスタムのSQLインストール・スクリプトを容易に作成できます。この機能では、インストール時にファイル内の変数を置換し、インストール用にカスタマイズされたスクリプトとファイルをユーザーに提供できます。

関連項目:

listenerおよびextprocの設定の詳細は、『Oracle Databaseアドバンスト・アプリケーション開発者ガイド』を参照してください。

14.10 移植性を考慮した設計

データ・カートリッジの移植性を高めるための考慮事項は、次のとおりです。

  • oratypes.hのデータ型を使用します。

  • できるかぎりOCIコールを使用します。

  • できるかぎりANSI C準拠を規定するスイッチを使用します。

  • ANSI C関数プロトタイプを使用します。

  • できるかぎり開発サイクルの早期段階でターゲット・プラットフォーム上で作成し、テストします。これにより、プラットフォーム固有のコードを特定することが容易になり、再設計に最大限の時間をかけることができます。

移植性が低下する原因は、次のとおりです。

  • エンディアン(ビッグ/リトル)固有のデータの格納。

  • 浮動小数点データ(IEEE/VAX/その他)の格納。

  • オペレーティング・システム固有のコール(使用する必要がある場合は、オペレーティング・システム固有のレイヤーに隔離します。ただし、必要なコールがOCIになく、POSIXにもない場合、困難な問題が生じる可能性があります)。

  • 64ビット・プラットフォームにおけるintsize_tとしての暗黙的キャスト