9.5 メソッドの設計上の考慮点
メソッドを使用した作業時に検討する特別な考慮点があります。
内容は次のとおりです。
9.5.1 メソッド・ファンクションに対する言語の選択
メソッド・ファンクションは、Oracleでサポートされる任意の言語(PL/SQL、Java、Cなど)で実装できます。
特定のアプリケーション用に言語を選択する場合は、次の要因を考慮してください。
-
使いやすさ
-
SQLコール
-
実行速度
-
同一/異なるアドレス空間
一般に、アプリケーションで主に計算を実行する場合には、Cが適していますが、比較的多くのデータベース・コールを実行する場合は、PL/SQLまたはJavaが適しています。
Cで実装されるメソッドは、外部プロシージャを使用して、サーバーとは別のプロセスで実行されます。それに対して、JavaまたはPL/SQLで実装されるメソッドは、サーバーと同じプロセスで実行されます。
メソッドの実装例
この項で説明する例では、異なる言語で実装されたメソッドを持つオブジェクト型が関係しています。この例では、オブジェクト型ImageType
は、ID
属性(一意に識別されるNUMBER
)およびIMG
属性(イメージを格納するBLOB
)を持ちます。オブジェクト型ImageType
は、次のメソッドを持ちます。
-
get_name
メソッド: データベース内でイメージの名前を検索してフェッチします。このメソッドは、PL/SQLで実装されています。 -
rotate
メソッド: イメージを回転します。このメソッドは、Cで実装されています。 -
clear
メソッド: 指定された色の新しいイメージを戻します。このメソッドは、Javaで実装されています。
Cでメソッドを実装する場合は、外部Cルーチンが含まれるライブラリを指す、LIBRARY
オブジェクトを定義する必要があります。Javaでメソッドを実装する場合を想定して、この例では、メソッドを持つJavaクラスがコンパイルされ、Oracleにアップロードされていると仮定しています。
例9-12に、オブジェクト型の定義およびそのメソッドを示します。
注意:
タイプ・メソッドは、Javaの静的メソッドのみにマップできます。
関連項目:
-
詳細は、『Oracle Database Java開発者ガイド』を参照してください
-
言語の選択の詳細は、「Oracleプログラム環境のオブジェクト・サポート」を参照してください
例9-12 様々な言語で実装されたメソッドを持つオブジェクト型の作成
CREATE LIBRARY myCfuncs TRUSTED AS STATIC / CREATE TYPE ImageType AS OBJECT ( id NUMBER, img BLOB, MEMBER FUNCTION get_name return VARCHAR2, MEMBER FUNCTION rotate return BLOB, STATIC FUNCTION clear(color NUMBER) return BLOB);/ CREATE TYPE BODY ImageType AS MEMBER FUNCTION get_name RETURN VARCHAR2 IS imgname VARCHAR2(100); sqlstmt VARCHAR2(200); BEGIN sqlstmt := 'SELECT name INTO imgname FROM imgtab WHERE imgid = id'; EXECUTE IMMEDIATE sqlstmt; RETURN imgname; END; MEMBER FUNCTION rotate RETURN BLOB AS LANGUAGE C NAME "Crotate" LIBRARY myCfuncs; STATIC FUNCTION clear(color NUMBER) RETURN BLOB AS LANGUAGE JAVA NAME 'myJavaClass.clear(oracle.sql.NUMBER) return oracle.sql.BLOB'; END; /
9.5.2 静的メソッド
静的メソッドは、SELF
値が第1パラメータとして渡されない点で、メンバー・メソッドと異なります。SELF
の値が問題ではないメソッドは、静的メソッドとして実装する必要があります。静的メソッドは、ユーザー定義コンストラクタに使用できます。
例9-13では、コンストラクタに類似したメソッドで、明示的な入力パラメータに基づいてその型のインスタンスを作成し、指定された表にそのインスタンスを挿入します。
例9-13 静的メソッドを持つオブジェクト型の作成
CREATE TYPE atype AS OBJECT( a1 NUMBER, STATIC PROCEDURE newa ( p1 NUMBER, tabname VARCHAR2, schname VARCHAR2)); / CREATE TYPE BODY atype AS STATIC PROCEDURE newa (p1 NUMBER, tabname VARCHAR2, schname VARCHAR2) IS sqlstmt VARCHAR2(100); BEGIN sqlstmt := 'INSERT INTO '||schname||'.'||tabname|| ' VALUES (atype(:1))'; EXECUTE IMMEDIATE sqlstmt USING p1; END; END; / CREATE TABLE atab OF atype; BEGIN atype.newa(1, 'atab', 'HR'); END; /
9.5.3 メンバー・プロシージャでのSELF IN OUT NOCOPYの使用について
メンバー・プロシージャにSELF
が宣言されていない場合、そのパラメータ・モードはデフォルトでIN
OUT
に設定されます。ただし、デフォルトの動作には、NOCOPY
コンパイラ・ヒントは含まれません。「メンバー・メソッド」を参照してください。
IN
OUT
実パラメータの値が対応する仮パラメータにコピーされるため、パラメータがラージ・オブジェクト型のインスタンスなどの大きなデータ構造を保持している場合、コピーによって実行速度が遅くなります。
パフォーマンスを改善するために、パラメータとしてラージ・オブジェクト型を渡す場合、SELF
IN
OUT
NOCOPY
を含められます。次に例を示します。
MEMBER PROCEDURE my_proc (SELF IN OUT NOCOPY my_LOB)
関連項目:
-
NOCOPY
を使用した場合のパフォーマンスの問題および使用上の制限事項は、『Oracle Database PL/SQL言語リファレンス』を参照してください。 -
CREATE
PROCEDURE
文でのNOCOPY
の使用方法の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。
9.5.4 タイプ・メソッドの戻り値に基づくファンクション索引
ファンクション索引は、式またはファンクションの戻り値に基づいた索引です。このファンクションは、オブジェクト型のメソッド・ファンクションの場合もあります。
メソッド・ファンクションに基づくファンクション索引は、索引付けの対象となっている列または表の各オブジェクト・インスタンスに対するファンクションの戻り値をあらかじめ計算しておいて、それらの値を索引に格納します。この索引では、ファンクションを評価しなおすことなく列や表が参照されます。
ファンクション索引は、WHERE
句にファンクションを含む問合せのパフォーマンスを向上させる場合に役立ちます。たとえば、次のコードにはオブジェクト表emps
の問合せが含まれています。
CREATE TYPE emp_t AS OBJECT( name VARCHAR2(36), salary NUMBER, MEMBER FUNCTION bonus RETURN NUMBER DETERMINISTIC); / CREATE TYPE BODY emp_t IS MEMBER FUNCTION bonus RETURN NUMBER DETERMINISTIC IS BEGIN RETURN self.salary * .1; END; END; / CREATE TABLE emps OF emp_t ; SELECT e.name FROM emps e WHERE e.bonus() > 2000;
この問合せを評価するためには、この表の各行オブジェクトに対するbonus()
を評価する必要があります。bonus()
の戻り値に対してファンクション索引がある場合は、この評価の作業はすでに実行済なので、Oracleの動作としては、索引内にある問合せ結果を検索するのみですみます。これによって、Oracleが問合せを実行した結果を戻す速度が向上します。
ファンクションの戻り値の索引付けが効果的に実行できるのは、戻り値が一定である場合、つまり、ファンクションが各オブジェクト・インスタンスに対して常に同じ値を戻す場合のみです。このため、ファンクション索引でユーザー定義ファンクションを使用する場合は、前述の例のように、DETERMINISTIC
キーワードを使用してそのファンクションを宣言しておく必要があります。このキーワードによって、各オブジェクト・インスタンスの入力引数値の集合に対して、このファンクションから常に一定の値が戻されることが保証されます。
次の例では、表emps
のメソッドbonus()
に対するファンクション索引を作成します。
例9-14 メソッドに対するファンクション索引の作成
CREATE INDEX emps_bonus_idx ON emps x (x.bonus()) ;