バージョンごとのドキュメント一覧

38.7. 関数の変動性分類 #

<title>Function Volatility Categories</title>

Every function has a <firstterm>volatility</firstterm> classification, with the possibilities being <literal>VOLATILE</literal>, <literal>STABLE</literal>, or <literal>IMMUTABLE</literal>. <literal>VOLATILE</literal> is the default if the <link linkend="sql-createfunction"><command>CREATE FUNCTION</command></link> command does not specify a category. The volatility category is a promise to the optimizer about the behavior of the function: すべての関数は変動性区分を持ちます。 取り得る区分は、VOLATILESTABLE、もしくはIMMUTABLEです。 CREATE FUNCTIONコマンドで分類の指定がなければデフォルトでVOLATILEになります。 変動性に関する分類は、その関数の動作に関するオプティマイザへの約束事です。

For best optimization results, you should label your functions with the strictest volatility category that is valid for them. 最適化の結果を最善にするためには、関数に対して有効かつ最も厳密な変動性区分を付けなければなりません。

Any function with side-effects <emphasis>must</emphasis> be labeled <literal>VOLATILE</literal>, so that calls to it cannot be optimized away. Even a function with no side-effects needs to be labeled <literal>VOLATILE</literal> if its value can change within a single query; some examples are <literal>random()</literal>, <literal>currval()</literal>, <literal>timeofday()</literal>. 副作用を持つ関数はすべてVOLATILEと付けなければなりません。 こうした関数は最適化できないためです。 関数が副作用を持たなかったとしても、単一問い合わせ内で値が変動する場合はVOLATILEと付けなければなりません。 例えば、random()currval()timeofday()などです。

Another important example is that the <function>current_timestamp</function> family of functions qualify as <literal>STABLE</literal>, since their values do not change within a transaction. その他の重要な例は、current_timestamp系列の関数は、それらの値がトランザクション内で変わらないことから、STABLEと見なされます。

There is relatively little difference between <literal>STABLE</literal> and <literal>IMMUTABLE</literal> categories when considering simple interactive queries that are planned and immediately executed: it doesn't matter a lot whether a function is executed once during planning or once during query execution startup. But there is a big difference if the plan is saved and reused later. Labeling a function <literal>IMMUTABLE</literal> when it really isn't might allow it to be prematurely folded to a constant during planning, resulting in a stale value being re-used during subsequent uses of the plan. This is a hazard when using prepared statements or when using function languages that cache plans (such as <application>PL/pgSQL</application>). 計画作成を行い、すぐに実行されるような単一の対話式問い合わせを考えた場合、相対的にSTABLE区分とIMMUTABLE区分との違いはあまりありません。 このような場合、関数が計画作成中に一度実行されるか、問い合わせ実行中に一度実行されるかがあまり問題になりません。 しかし、計画が保存され、後で再利用される場合は大きな違いが現れます。 本来ならば関数が計画作成段階で早めに定数を保持できない場合にIMMUTABLEを付けると、その後にこの計画を使用する時に古くて意味のない値が再利用されてしまうことになります。 これは、プリペアド文や計画をキャッシュする関数言語(PL/pgSQLなど)を使用する場合は危険です。

For functions written in SQL or in any of the standard procedural languages, there is a second important property determined by the volatility category, namely the visibility of any data changes that have been made by the SQL command that is calling the function. A <literal>VOLATILE</literal> function will see such changes, a <literal>STABLE</literal> or <literal>IMMUTABLE</literal> function will not. This behavior is implemented using the snapshotting behavior of MVCC (see <xref linkend="mvcc"/>): <literal>STABLE</literal> and <literal>IMMUTABLE</literal> functions use a snapshot established as of the start of the calling query, whereas <literal>VOLATILE</literal> functions obtain a fresh snapshot at the start of each query they execute. SQLもしくは標準手続き言語で作成された関数では、変動性分類で決定される2番目に重要な性質があります。 すなわち、その関数を呼び出すSQLコマンドによりなされてきたすべてのデータ変更の可視性です。 VOLATILE関数はそのような変更を捕らえますが、STABLEまたはIMMUTABLE関数はそうしません。 この動作はMVCC(第13章を参照)のスナップショット処理の動作を使用して実装されています。 STABLEIMMUTABLE関数は、呼び出す問い合わせの開始時点で成立したスナップショットを使用しますが、VOLATILE関数はそれぞれの問い合わせの実行開始時点の作りたてのスナップショットを取得します。

注記

Functions written in C can manage snapshots however they want, but it's usually a good idea to make C functions work this way too. しかし、C言語で作成された関数は、どのようにでもスナップショットを管理できますが、通常C関数でもこのように動作させることは良い考えです。

Because of this snapshotting behavior, a function containing only <command>SELECT</command> commands can safely be marked <literal>STABLE</literal>, even if it selects from tables that might be undergoing modifications by concurrent queries. <productname>PostgreSQL</productname> will execute all commands of a <literal>STABLE</literal> function using the snapshot established for the calling query, and so it will see a fixed view of the database throughout that query. このスナップショット処理の動作のため、同時実行の問い合わせによって別途変更されている可能性があるテーブルから選択していたとしても、SELECTコマンドのみを含む関数は、安全にSTABLE印を付けられます。 PostgreSQLは、呼び出し元の問い合わせに対して確立されたスナップショットを使用してSTABLE関数のすべてのコマンドを実行します。 したがってその問い合わせの間、データベースに対して固定された視点で値を参照することになります。

The same snapshotting behavior is used for <command>SELECT</command> commands within <literal>IMMUTABLE</literal> functions. It is generally unwise to select from database tables within an <literal>IMMUTABLE</literal> function at all, since the immutability will be broken if the table contents ever change. However, <productname>PostgreSQL</productname> does not enforce that you do not do that. IMMUTABLE関数内のSELECTコマンドも同様のスナップショット処理の動作を使用します。 ただし、一般的に、IMMUTABLE関数内でデータベースのテーブルを検索(SELECT)することは勧められません。 テーブルの内容が変わってしまった場合にその不変性が壊れてしまうためです。 しかし、PostgreSQLでは強制的に検索(SELECT)できないようにはしていません。

A common error is to label a function <literal>IMMUTABLE</literal> when its results depend on a configuration parameter. For example, a function that manipulates timestamps might well have results that depend on the <xref linkend="guc-timezone"/> setting. For safety, such functions should be labeled <literal>STABLE</literal> instead. よくあるエラーは、設定パラメータに依存する結果となる関数にIMMUTABLEと付けることです。 例えば、タイムスタンプを操作する関数は、おそらくTimeZoneの設定に依存した結果になります。 こうした関数は、安全のため代わりにSTABLEと付けてください。

注記

<productname>PostgreSQL</productname> requires that <literal>STABLE</literal> and <literal>IMMUTABLE</literal> functions contain no SQL commands other than <command>SELECT</command> to prevent data modification. (This is not a completely bulletproof test, since such functions could still call <literal>VOLATILE</literal> functions that modify the database. If you do that, you will find that the <literal>STABLE</literal> or <literal>IMMUTABLE</literal> function does not notice the database changes applied by the called function, since they are hidden from its snapshot.) PostgreSQLはデータの変更を防ぐためにSTABLE関数とIMMUTABLE関数がSELECT以外のSQLコマンドを含まないことを要求します。 (こうした関数はまだデータベースを変更するVOLATILE関数を呼び出すことができますので、これは防弾条件として完全ではありません。 これを行うと、STABLEもしくはIMMUTABLE関数は、そのスナップショットからそれらが隠されていることから、呼び出した関数によるデータベースの変更に気がつきません。)