無料スクリプト配布のPHP.TO   PHPの実用的なtips PHPマニュアル MySQLマニュアル Apacheマニュアル PostgreSQLマニュアル マニュアル検索    

35.6. 関数の変動性分類

すべての関数は 変動性 区分を持ちます。 取り得る区分は、 VOLATILE STABLE 、もしくは IMMUTABLE です。 CREATE FUNCTION コマンドで分類の指定がなければデフォルトで VOLATILE になります。 変動性に関する分類は、その関数の動作に関するオプティマイザへの約束事です。

最適化の結果を最善にするためには、関数に対して有効かつ最も厳密な変動性区分を付けなければなりません。

副作用を持つ関数はすべて VOLATILE と付けなければなりません。 こうした関数は最適化することができないためです。 関数が副作用を持たなかったとしても、単一問い合わせ内で値が変動する場合は VOLATILE と付けなければなりません。 例えば、 random() currval() timeofday() などです。

その他の重要な例は、 current_timestamp 系列の関数は、それらの値がトランザクション内で変わらないことから、 STABLE と見なされます。

計画作成を行い、すぐに実行されるような単一の対話式問い合わせを考えた場合、相対的に STABLE 区分と IMMUTABLE 区分との違いはあまりありません。 このような場合、関数が計画作成中に一度実行されるか、問い合わせ実行中に一度実行されるかがあまり問題になりません。 しかし、計画が保存され、後で再利用される場合は大きな違いが現れます。 本来ならば関数が計画作成段階で早めに定数を保持することができない場合に IMMUTABLE を付けると、その後にこの計画を使用する時に古くて意味のない値が再利用されてしまうことになります。 これは、プリペアド文や計画をキャッシュする関数言語( PL/pgSQL など)を使用する場合は危険です。

SQLもしくは標準手続き言語で作成された関数では、変動性分類で決定される2番目に重要な性質があります。 すなわち、その関数を呼び出すSQLコマンドによりなされてきたすべてのデータ変更の可視性です。 VOLATILE 関数はそのような変更を捕らえますが、 STABLE または IMMUTABLE 関数はそうしません。 この動作はMVCC( 第13章 を参照)のスナップショット処理の動作を使用して実装されています。 STABLE IMMUTABLE 関数は、呼び出す問い合わせの開始時点で成立したスナップショットを使用しますが、 VOLATILE 関数はそれぞれの問い合わせの実行開始時点の作りたてのスナップショットを取得します。

注意: しかし、C言語で作成された関数は、どのようにでもスナップショットを管理することができますが、通常C関数でもこのように動作させることは良い考えです。

このスナップショット処理の動作のため、同時実行の問い合わせによって別途変更されている可能性があるテーブルから選択していたとしても、 SELECT コマンドのみを含む関数は、安全に STABLE とすることができます。 PostgreSQL は、呼び出し元の問い合わせに対して確立されたスナップショットを使用して STABLE 関数のすべてのコマンドを実行します。 したがってその問い合わせの間、データベースに対して固定された視点で値を参照することになります。

IMMUTABLE 関数内の SELECT コマンドも同様のスナップショット処理の動作を使用します。 ただし、一般的に、 IMMUTABLE 関数内でデータベースのテーブルを検索(SELECT)することは勧められません。 テーブルの内容が変わってしまった場合にその普遍性が壊れてしまうためです。 しかし、 PostgreSQL では強制的に検索(SELECT)できないようにはしていません。

よくあるエラーは、設定パラメータに依存する結果となる関数に IMMUTABLE と付けることです。 例えば、タイムスタンプを操作する関数は、おそらく TimeZone の設定に依存した結果になります。 こうした関数は、安全のため代わりに STABLE と付けてください。

注意: PostgreSQL リリース8.0より前のリリースでは、 STABLE 関数と IMMUTABLE 関数がデータベースを変更できないという必要条件がシステムによって禁止されていませんでした。 リリース8.0以降では、この区分のSQL関数や手続き言語関数に対して SELECT 以外のSQLコマンドを含めないことを必要条件とすることにより、これを禁止しています。 (こうした関数はまだデータベースを変更する VOLATILE 関数を呼び出すことができますので、これは防弾条件として完全ではありません。 これを行うと、 STABLE もしくは IMMUTABLE 関数は、そのスナップショットからそれらが隠されていることから、呼び出した関数によるデータベースの変更に気がつきません。)


powered by SEO.CUG.NET