PostgreSQL:不変、揮発性、安定


11

IMMUTABLE関数、VOLATILE関数、STABLE関数の定義の本当の意味は不明です。

私はドキュメント、特にそれぞれの定義を読みました。

IMMUTABLEは、関数がデータベースを変更できないことを示し 、同じ引数値が指定された場合は常に同じ結果を返します。つまり、データベースの検索や、引数リストに直接存在しない情報の使用は行いません。このオプションを指定すると、引数がすべて定数の関数の呼び出しはすべて、関数の値ですぐに置き換えることができます。

STABLEは、関数がデータベースを変更できず、単一のテーブルスキャン内で同じ引数値に対して常に同じ結果を返すが、その結果はSQLステートメント間で変わる可能性があることを示します。これは、データベースルックアップ、パラメーター変数(現在のタイムゾーンなど)などに依存する結果を持つ関数の適切な選択です(現在のコマンドによって変更された行をクエリするAFTERトリガーには不適切です)。 current_timestamp関数ファミリーは、トランザクション内で値が変化しないため、安定と見なされます。

VOLATILEは、関数の値が単一のテーブルスキャン内でも変更される可能性があるため、最適化を実行できないことを示します。この意味で揮発性であるデータベース関数は比較的少数です。いくつかの例は、random()、currval()、timeofday()です。ただし、副作用がある関数は、その結果がかなり予測可能であっても、呼び出しが最適化されないように、揮発性に分類する必要があることに注意してください。例はsetval()です。

私の混乱は不変の条件と機能が安定したとしていますALWAYSまたは一貫して同じ引数与えられた同じ結果を返します。

IMMUTABLE定義は、関数がデータベース検索を行わないか、引数リストに直接存在しない情報を使用しないことを示しています。つまり、私にとっては、そのような関数はクライアントから提供されたデータを操作するために使用され、SELECTステートメントを含むべきではないということです...

STABLEの場合、定義は同じですが、常に同じ結果を返す必要があると述べています。つまり、私にとっては、関数が同じ引数で呼び出されるたびに、同じ結果を返す必要があります(まったく同じ行、毎回)。

したがって、私にとって...つまり、更新可能な1つまたは複数のテーブルに対してSELECTを実行する関数は、揮発性でなければならないということです。

しかし、再び...それは私には正しく聞こえません。

これを私のユースケースに戻すと、常に追加されているテーブルで複数のJOINを使用してSELECTステートメントを実行する関数を書いているので、同じ引数を使用しても、関数呼び出しは呼び出されるたびに異なる結果を返すことが期待されます。

それで、それは私の機能が揮発性であるべきであることを意味しますか?ドキュメントは、この意味で揮発性であるデータベース関数が比較的少ないことを示していますが

ありがとうございました!

回答:


15

IMMUTABLE結果は入力のみに依存する純粋な関数でなければなりません。これは非常に厳しい要件です。他の不変関数を呼び出すこと、テーブルにアクセスすること、構成プロパティの値にアクセスすることなどはできません。

STABLEそれ自体である任意の入力を使用できますSTABLE:その他STABLEまたはIMMUTABLE関数、およびSELECTテーブルのクエリ。これらのテーブルの関数のビューはクエリの現在のスナップショット内で変更されないため、テーブルをクエリしても安全です。current_setting(...)現在のステートメント内で割り当てられないことがわかっている限り、GUC値()にアクセスできます。

VOLATILE 関数は、上記に当てはまらないものすべてです。

  • 副作用のあるもの
  • 書き込みを行うものすべて
  • PostgreSQLスナップショットで管理されていない外部データをクエリするもの
  • ...

一般的には、正当VOLATILEな理由がない限り、すべて残しておいてください。

使用する主な理由IMMUTABLEは、インデックス式の一部として使用される関数を記述する場合です。


1
「テーブルにアクセスできません。」公平に言えば、彼らはできるし、そうする。より一般的なルールは、テーブルがデータベースを再起動せずに意味のある変異をすることは想定されていないということです。
エヴァンキャロル

STABLEがテーブルアクセスを許可している場合、VOLATILEを超える/上に最適化がありますか?
Brooks

私の頭の上を覚えていないでください、ドキュメント/コードをチェックする必要があります。
クレイグリンガー

4

STABLEの場合、太字にする必要がある部分は、「SQLステートメントによって結果が変わる可能性がある」です。

イミュータブルなものは決して変わることはありません。あなたは、データベースサーバー、実行を再開したとしてもyum update(もちろんバグがあることができます!)、(のようなあなたの設定を変更しdatestyletimezonedefault_text_search_configextra_float_digits、など)、またはサーバーハードウェアは完全に置き換える(同じアーキテクチャの古いハードウェアとして、そうバイナリファイルはまだ互換性があります)。

1つのSQLステートメント内で、外部クエリと同じスナップショットを使用してクエリを実行するため、他のテーブルに同時に加えた変更は表示されないため、記述した関数はSTABLEのように聞こえます。ここで、関数がサーバーへの新しい接続を開き、その独立した接続内でクエリを実行すると、異なるスナップショットを使用しているため、関数が揮発性になります。


IMMUTABLE(クエリ、接続、再起動、惑星の破壊と再構築の間、データベースが変更された場合でも)とVOLATILE(関数がそれはそれが呼ばれた)。あれは正しいですか?それでは、STABLEは、関数がデータベースを変更せず、そのコンテキスト外のデータベースにアクセスしないことを意味します。STABLEの定義は、必要以上に複雑であるように感じます...それとも私は何かを省いていますか?
Brooks

PostgreSQLには実際にIMMUTABLE、照合順序に関するいくつかの問題があります。glibc(または、新しいPgではiconv)が照合順序の定義を変更しないことを信頼しています。実際には、そのような変更を検出する方法はありません。これは、サイレントインデックスの破損につながることができます:(異なるOSのバージョンなどの間で複製するときには、ほとんどの問題だ。
クレイグリンガー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.