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:
すべての関数は変動性区分を持ちます。
取り得る区分は、VOLATILE
、STABLE
、もしくはIMMUTABLE
です。
CREATE FUNCTION
コマンドで分類の指定がなければデフォルトでVOLATILE
になります。
変動性に関する分類は、その関数の動作に関するオプティマイザへの約束事です。
A <literal>VOLATILE</literal> function can do anything, including modifying
the database. It can return different results on successive calls with
the same arguments. The optimizer makes no assumptions about the
behavior of such functions. A query using a volatile function will
re-evaluate the function at every row where its value is needed.
VOLATILE
関数は、データベースの変更を含む、すべてを行うことができます。
同一引数で続けて呼び出したとしても異なる結果を返すことができます。
オプティマイザはこうした関数の振舞いに対する前提を持ちません。
VOLATILE関数を使用した問い合わせは、その行の値を必要とするすべての行においてその関数を再評価します。
A <literal>STABLE</literal> function cannot modify the database and is
guaranteed to return the same results given the same arguments
for all rows within a single statement. This category allows the
optimizer to optimize multiple calls of the function to a single
call. In particular, it is safe to use an expression containing
such a function in an index scan condition. (Since an index scan
will evaluate the comparison value only once, not once at each
row, it is not valid to use a <literal>VOLATILE</literal> function in an
index scan condition.)
STABLE
関数はデータベースを変更できません。
また、単一の文内ですべての行に対して同一の引数を渡した場合に同一の結果を返すことが保証されています。
この区分により、オプティマイザは複数の関数の呼び出しを1つの呼び出しに最適化できます。
特に、インデックススキャン条件内でこうした関数を含んだ式を使用することは安全です。
(インデックススキャンは行ごとに一度ではなく、一度だけ比較値の評価を行いますので、インデックススキャン条件内でVOLATILE
関数を使用することは意味がありません。)
An <literal>IMMUTABLE</literal> function cannot modify the database and is
guaranteed to return the same results given the same arguments forever.
This category allows the optimizer to pre-evaluate the function when
a query calls it with constant arguments. For example, a query like
<literal>SELECT ... WHERE x = 2 + 2</literal> can be simplified on sight to
<literal>SELECT ... WHERE x = 4</literal>, because the function underlying
the integer addition operator is marked <literal>IMMUTABLE</literal>.
IMMUTABLE
関数はデータベースを変更できません。
また、同一引数に対する呼び出しは常に同一の結果を返すことが保証されています。
問い合わせが定数の引数でこうした関数を呼び出した場合、オプティマイザはこの関数を事前に評価できます。
例えば、SELECT ... WHERE x = 2 + 2
といった問い合わせは、SELECT ... WHERE x = 4
のように単純化できます。
これは、整数加算演算子の基になる関数がIMMUTABLE
として宣言されているためです。
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章を参照)のスナップショット処理の動作を使用して実装されています。
STABLE
とIMMUTABLE
関数は、呼び出す問い合わせの開始時点で成立したスナップショットを使用しますが、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
関数は、そのスナップショットからそれらが隠されていることから、呼び出した関数によるデータベースの変更に気がつきません。)