デフォルトでは、関数は、データベースシステムがその振舞いについてごく一部しか知らない単なる「ブラックボックス」です。 しかし、これは、関数を使う問い合わせがその実力よりもずっと効率悪く実行されるかもしれないことを意味します。 プランナが関数呼び出しを最適化するのを助ける補足の情報を提供できます。
CREATE FUNCTION
コマンドで宣言的な注釈として、いくつかの基本的な実態を提供できます。
この中でも最も重要なものは、関数の変動性分類(IMMUTABLE
、STABLE
またはVOLATILE
)です。関数を定義する時にはこれを正しく指定するよう常に注意すべきです。
並列問い合わせでその関数を使いたいのなら、並列処理での安全性の性質(PARALLEL UNSAFE
、PARALLEL RESTRICTED
またはPARALLEL SAFE
)も指定しなければなりません。
関数の推定実行コストや集合を返す関数が返すと推定される行数を指定することも有用な場合があります。
しかし、この2つの実態を指定する宣言的な方法は定数を指定することしか許しておらず、それは多くの場合不適切です。
SQLで呼び出せる関数(対応する対象関数と呼ばれます)にプランナサポート関数を結び付け、それによって複雑すぎて宣言的に表現できない対象関数に関する知識を提供することも可能です。 (対象関数はそうではありませんが)プランナサポート関数はCで書かなければなりませんので、これは比較的少数の人が使う先進的な機能です。
プランナサポート関数には以下のSQLシグネチャがなければなりません。
supportfn(internal) returns internal
対象関数を作成する時にSUPPORT
句を指定することで対象関数に結び付けられます。
プランナサポート関数のAPIの詳細は、PostgreSQLソースコードのファイルsrc/include/nodes/supportnodes.h
で見つけられます。
ここではプランナサポート関数ができることの概略を説明するにとどめます。
サポート関数へ可能なリクエストの集合は拡張可能ですので、将来のバージョンではより多くのことが可能になっているでしょう。
一部の関数呼び出しでは、関数固有の属性に基づいて計画作成中に単純化できます。
例えば、int4mul(n, 1)
はn
だけに単純化できます。
この種の変形は、SupportRequestSimplify
リクエスト型プランナサポート関数に実装することにより実行されます。
問い合わせ解析木で見つかった対象関数それぞれに対して、サポート関数が呼び出されます。
特定の呼出しが別の形に単純化できることが分かれば、その式を表現する解析木を作成して返します。
これは、その関数に基づく演算子に対しても自動的に行なわれます—上の例ではn * 1
もn
へと単純化されます。
(しかし、これは単なる例であることに注意してください。この特定の最適化は、標準のPostgreSQLでは実際には行なわれません。)
サポート関数が単純化する状況では、PostgreSQLが対象関数を呼び出すことはないとは保証しません。
単純化された式と対象関数の実際の実行が厳密に等しいことを確実にしてください。
boolean
を返す対象関数に対しては、その関数を使ったWHERE
句により選択される行の割合を推定するのが有用な場合がよくあります。
これはSupportRequestSelectivity
リクエスト型を実装したサポート関数で行なえます。
対象関数の実行時間が、その入力に大きく依存する場合には、それに対応する定数でないコスト推定を提供するのが有用でしょう。
これはSupportRequestCost
リクエスト型を実装したサポート関数で行なえます。
集合を返す対象関数に対しては、その関数が返す行の数の定数でない推定を提供するのが有用な場合がよくあります。
これはSupportRequestRows
リクエスト型を実装したサポート関数で行なえます。
boolean
を返す対象関数に対しては、WHERE
句に現れる関数呼び出しをインデックス可能な演算子句に変換できる場合があります。
変換された句は、正確にその関数の条件と等しいか幾分弱い(すなわち、関数の条件が受け付けない値も受け付けるかもしれません)でしょう。
後者の場合、インデックスの条件は損失があると言われます。それでもインデックスの走査には使えますが、それが本当にWHERE
条件を満たすのかどうか、インデックスにより返された各行に対して関数呼び出しを実行しないといけません。
そのような条件を作るには、サポート関数はSupportRequestIndexCondition
リクエスト型を実装しなければなりません。