By default, a function is just a <quote>black box</quote> that the database system knows very little about the behavior of. However, that means that queries using the function may be executed much less efficiently than they could be. It is possible to supply additional knowledge that helps the planner optimize function calls. デフォルトでは、関数は、データベースシステムがその振舞いについてごく一部しか知らない単なる「ブラックボックス」です。 しかし、これは、関数を使う問い合わせがその実力よりもずっと効率悪く実行されるかもしれないことを意味します。 プランナが関数呼び出しを最適化するのを助ける補足の情報を提供できます。
Some basic facts can be supplied by declarative annotations provided in
the <link linkend="sql-createfunction"><command>CREATE FUNCTION</command></link> command. Most important of
these is the function's <link linkend="xfunc-volatility">volatility
category</link> (<literal>IMMUTABLE</literal>, <literal>STABLE</literal>,
or <literal>VOLATILE</literal>); one should always be careful to
specify this correctly when defining a function.
The parallel safety property (<literal>PARALLEL
UNSAFE</literal>, <literal>PARALLEL RESTRICTED</literal>, or
<literal>PARALLEL SAFE</literal>) must also be specified if you hope
to use the function in parallelized queries.
It can also be useful to specify the function's estimated execution
cost, and/or the number of rows a set-returning function is estimated
to return. However, the declarative way of specifying those two
facts only allows specifying a constant value, which is often
inadequate.
CREATE FUNCTION
コマンドで宣言的な注釈として、いくつかの基本的な実態を提供できます。
この中でも最も重要なものは、関数の変動性分類(IMMUTABLE
、STABLE
またはVOLATILE
)です。関数を定義する時にはこれを正しく指定するよう常に注意すべきです。
並列問い合わせでその関数を使いたいのなら、並列処理での安全性の性質(PARALLEL UNSAFE
、PARALLEL RESTRICTED
またはPARALLEL SAFE
)も指定しなければなりません。
関数の推定実行コストや集合を返す関数が返すと推定される行数を指定することも有用な場合があります。
しかし、この2つの実態を指定する宣言的な方法は定数を指定することしか許しておらず、それは多くの場合不適切です。
It is also possible to attach a <firstterm>planner support function</firstterm> to an SQL-callable function (called its <firstterm>target function</firstterm>), and thereby provide knowledge about the target function that is too complex to be represented declaratively. Planner support functions have to be written in C (although their target functions might not be), so this is an advanced feature that relatively few people will use. SQLで呼び出せる関数(対応する対象関数と呼ばれます)にプランナサポート関数を結び付け、それによって複雑すぎて宣言的に表現できない対象関数に関する知識を提供することも可能です。 (対象関数はそうではありませんが)プランナサポート関数はCで書かなければなりませんので、これは比較的少数の人が使う先進的な機能です。
A planner support function must have the SQL signature プランナサポート関数には以下のSQLシグネチャがなければなりません。
supportfn(internal) returns internal
It is attached to its target function by specifying
the <literal>SUPPORT</literal> clause when creating the target function.
対象関数を作成する時にSUPPORT
句を指定することで対象関数に結び付けられます。
The details of the API for planner support functions can be found in
file <filename>src/include/nodes/supportnodes.h</filename> in the
<productname>PostgreSQL</productname> source code. Here we provide
just an overview of what planner support functions can do.
The set of possible requests to a support function is extensible,
so more things might be possible in future versions.
プランナサポート関数のAPIの詳細は、PostgreSQLソースコードのファイルsrc/include/nodes/supportnodes.h
で見つけられます。
ここではプランナサポート関数ができることの概略を説明するにとどめます。
サポート関数へ可能なリクエストの集合は拡張可能ですので、将来のバージョンではより多くのことが可能になっているでしょう。
Some function calls can be simplified during planning based on
properties specific to the function. For example,
<literal>int4mul(n, 1)</literal> could be simplified to
just <literal>n</literal>. This type of transformation can be
performed by a planner support function, by having it implement
the <literal>SupportRequestSimplify</literal> request type.
The support function will be called for each instance of its target
function found in a query parse tree. If it finds that the particular
call can be simplified into some other form, it can build and return a
parse tree representing that expression. This will automatically work
for operators based on the function, too — in the example just
given, <literal>n * 1</literal> would also be simplified to
<literal>n</literal>.
(But note that this is just an example; this particular
optimization is not actually performed by
standard <productname>PostgreSQL</productname>.)
We make no guarantee that <productname>PostgreSQL</productname> will
never call the target function in cases that the support function could
simplify. Ensure rigorous equivalence between the simplified
expression and an actual execution of the target function.
一部の関数呼び出しでは、関数固有の属性に基づいて計画作成中に単純化できます。
例えば、int4mul(n, 1)
はn
だけに単純化できます。
この種の変形は、SupportRequestSimplify
リクエスト型プランナサポート関数に実装することにより実行されます。
問い合わせ解析木で見つかった対象関数それぞれに対して、サポート関数が呼び出されます。
特定の呼出しが別の形に単純化できることが分かれば、その式を表現する解析木を作成して返します。
これは、その関数に基づく演算子に対しても自動的に行なわれます—上の例ではn * 1
もn
へと単純化されます。
(しかし、これは単なる例であることに注意してください。この特定の最適化は、標準のPostgreSQLでは実際には行なわれません。)
サポート関数が単純化する状況では、PostgreSQLが対象関数を呼び出すことはないとは保証しません。
単純化された式と対象関数の実際の実行が厳密に等しいことを確実にしてください。
For target functions that return <type>boolean</type>, it is often useful to estimate
the fraction of rows that will be selected by a <literal>WHERE</literal> clause using that
function. This can be done by a support function that implements
the <literal>SupportRequestSelectivity</literal> request type.
boolean
を返す対象関数に対しては、その関数を使ったWHERE
句により選択される行の割合を推定するのが有用な場合がよくあります。
これはSupportRequestSelectivity
リクエスト型を実装したサポート関数で行なえます。
If the target function's run time is highly dependent on its inputs,
it may be useful to provide a non-constant cost estimate for it.
This can be done by a support function that implements
the <literal>SupportRequestCost</literal> request type.
対象関数の実行時間が、その入力に大きく依存する場合には、それに対応する定数でないコスト推定を提供するのが有用でしょう。
これはSupportRequestCost
リクエスト型を実装したサポート関数で行なえます。
For target functions that return sets, it is often useful to provide
a non-constant estimate for the number of rows that will be returned.
This can be done by a support function that implements
the <literal>SupportRequestRows</literal> request type.
集合を返す対象関数に対しては、その関数が返す行の数の定数でない推定を提供するのが有用な場合がよくあります。
これはSupportRequestRows
リクエスト型を実装したサポート関数で行なえます。
For target functions that return <type>boolean</type>, it may be possible to
convert a function call appearing in <literal>WHERE</literal> into an indexable operator
clause or clauses. The converted clauses might be exactly equivalent
to the function's condition, or they could be somewhat weaker (that is,
they might accept some values that the function condition does not).
In the latter case the index condition is said to
be <firstterm>lossy</firstterm>; it can still be used to scan an index,
but the function call will have to be executed for each row returned by
the index to see if it really passes the <literal>WHERE</literal> condition or not.
To create such conditions, the support function must implement
the <literal>SupportRequestIndexCondition</literal> request type.
boolean
を返す対象関数に対しては、WHERE
句に現れる関数呼び出しをインデックス可能な演算子句に変換できる場合があります。
変換された句は、正確にその関数の条件と等しいか幾分弱い(すなわち、関数の条件が受け付けない値も受け付けるかもしれません)でしょう。
後者の場合、インデックスの条件は損失があると言われます。それでもインデックスのスキャンには使えますが、それが本当にWHERE
条件を満たすのかどうか、インデックスにより返された各行に対して関数呼び出しを実行しないといけません。
そのような条件を作るには、サポート関数はSupportRequestIndexCondition
リクエスト型を実装しなければなりません。