私が理解しているように、次のようなクエリをPostgresに送信すると、
SELECT id FROM table1 WHERE name = $1;
Postgresはクエリプランを作成します。プランは、同じセッションの同じクエリに対してキャッシュされます。しかし、関数を作成する場合:
CREATE OR REPLACE FUNCTION get_table1 (parname text) RETURNS bigint
LANGUAGE plpgsql AS
$$BEGIN
RETURN (SELECT id FROM table1 where name = parname);
END$$;
クエリプランは、今後のすべてのセッションでキャッシュされます。
クエリアナライザーが呼び出される頻度を確認して、この理論を検証したいと思います。 Postgresがクエリを解析する回数を検査する方法はありますか?
可能であれば、1秒あたりの#parsesやmin/max/avg解析時間などを監視したいと思います。
not「将来のすべてのセッションのために」クエリプランを保存できます。クエリプランは、現在のセッションでのみ保存されます。そして、いくつかの有利な条件下でのみ再利用されます。
アドホックSQLクエリの計画はまったく保存されないです。 PL/pgSQL関数内のすべてのクエリは準備されたステートメントのように扱われます。また、クエリの計画以外にも多くの手順があります。
Postgres 9.1以降の大幅な変更があることに注意することが重要です。ここでは、一般的な計画がより一般的に保存され、PL/pgSQL内のステートメントに再利用されました。これはpg 9.2でかなり賢くなりました。
マニュアル (太字強調):
準備されたステートメントは、現在のデータベースセッションの間のみ持続します。
クエリプランについてはまだ何も言っていません:
PREPARE
ステートメントを実行すると、指定されたステートメントは解析、分析、および書き換えになります。続いてEXECUTE
コマンドが発行されると、準備されたステートメントは計画されて実行されますです。
さらに下に:
準備されたステートメントが十分な回数実行された場合、サーバーは毎回再計画するのではなく、最終的には一般的な計画を保存して再利用することを決定するとなる場合があります。これは、準備されたステートメントにパラメーターがない場合、すぐに発生します。それ以外の場合は、一般的なプランが特定のパラメーター値に依存するプランよりもそれほど高価ではないように見える場合にのみ発生します。通常、一般的なプランは、クエリのパフォーマンスが、指定された特定のパラメーター値の影響をほとんど受けないと推定される場合にのみ選択されます。
genericプランが使用されているかどうかを確認する方法は?
PostgreSQLが準備済みステートメントに使用しているクエリプランを調べるには、
EXPLAIN
を使用します。汎用プランが使用されている場合、それにはパラメーターシンボル$n
が含まれますが、カスタムプランには現在の実際のパラメーター値が代入されます。
savedプランは常に一般的なプランですが、その逆はありません。
準備されたステートメントはどこに保存されますか?
pg_prepared_statements
システムビューをクエリすると、セッションで使用可能なすべての準備済みステートメントを確認できます。
これらは通常、EXPLAIN
出力には表示されません。追加のモジュール auto-explain をインストールして、それらの計画をログに書き込むこともできます。詳細はこちら:
PL/pgSQL関数の Plan Caching の詳細については、マニュアルを直接お読みください。