4

pl/pgsql でクエリ プランのキャッシュがどのように機能するか理解できません。

JOINs とs を使用してオールインワン クエリを作成したいIFので、複数の異なるクエリ パラメータを使用し、複数のテーブルを検索します。

最初は、pl/pgsql を使用すると、パラメーターの組み合わせごとに異なる計画が生成されると考えていましたが、そうではありません。複数のテーブルがあるためです。

PL/pgSQL 関数に直接現れる SQL コマンドは、実行のたびに同じテーブルと列を参照する必要があります。つまり、SQL コマンドでパラメーターをテーブルまたは列の名前として使用することはできません。この制限を回避するために、PL/pgSQL EXECUTE ステートメントを使用して動的コマンドを作成できますが、新しい解析分析を実行し、実行ごとに新しい実行計画を作成するという代償を払います。 ここから

毎回新しい分析を実行すると、物事が遅くなる可能性があると思います。使用しないEXECUTE場合

ステートメントにパラメーターがない場合、または何度も実行される場合、SPI マネージャーは、特定のパラメーター値に依存しない汎用プランを作成し、それをキャッシュして再利用することを検討します。通常、これは、実行計画がその中で参照される PL/pgSQL 変数の値にあまり敏感でない場合にのみ発生します。もしそうなら、毎回計画を生成することは純利益です。ここから

その場合、一般的なプランを使用する必要がありますか? 毎回計画がないので速いですか、それとも遅いですか?少なくともそれらはキャッシュされます。私のクエリは動的であるため、変数に敏感ですが、

もしそうなら、毎回計画を生成することは純利益です。

実際に意味?EXECUTE毎回 /planを使用することは、一般的なものよりも良いですか、それとも悪いですか? 「ネットウィン」は私を混乱させます。

一般的な計画が不正確で、EXECUTE/planning が毎回遅くなる場合、わざわざ pl/pgsql を使用する必要はありません。次に、いくつかの if を使用して簡単なクエリを作成できます。

要するに、速度とプラン キャッシングの点でEXECUTE/plan each timeが優れているか劣っているかについては、結論を出すことはできません。generic cached plan説明とアドバイスをお願いします、私は混乱しています。

参考までに、これは私が作成しているものです。mytablesそのまま動作しますが、およびの IF がさらに追加されます。mywhere

DROP FUNCTION IF EXISTS __aa(ii int, fk int);
CREATE  FUNCTION __aa(ii int, fk int) RETURNS TABLE(id INTEGER,val text, fd integer) AS $$
DECLARE 
myt text;
mytables text;
mywhere text;
BEGIN

mytables := 'dyn_tab2';
mywhere := 'dyn_tab2.id=$1';
IF fk IS NOT NULL
THEN
mywhere := mywhere || 'AND dyn_tab2.fk_id=$2';
END IF;

RETURN QUERY EXECUTE format('
SELECT dyn_tab2.id, dyn_tab2.value, dyn_tab2.fk_id 
FROM %I WHERE ' ||mywhere,
mytables) 
USING ii, fk;

END;
$$
LANGUAGE 'plpgsql';

ありがとう

4

1 に答える 1

12

静的クエリ ( なしEXECUTE) のプランは常にキャッシュされ、動的クエリ ( ありEXECUTE) のプランはキャッシュできません。

あなたの場合、とにかく静的クエリを使用することは不可能です。引用するように、それはクエリでテーブルの固定セットしか使用できないことを意味するからです。

ドキュメントにある静的クエリと動的クエリのトレードオフに関する議論に混乱しているようです。

定義:クエリ パラメータは$1、静的クエリの PL/pgSQL 変数名のように、クエリ文字列の一部ではない値です。

静的クエリの場合、手順は次のとおりです。

最初の 5 回の実行では、実際のパラメーター値を使用して計画され (「カスタム計画」)、推定実行時間が、実際のパラメーター値を無視する計画 (「汎用計画」) よりも大幅に短くない場合、ジェネリック プランは 6 回目の実行から使用されます。

ジェネリック プランはキャッシュされるため、6 回目の実行以降はプランニング コストが発生しません。

動的クエリは、実行されるたびに計画されます。

トレードオフは次のとおりです。動的クエリは、実行されるたびに計画コストがかかりますが、常に実際のパラメーター値を使用して計画されるため、最終的にはより適切な実行計画が得られ、クエリの実行時間を節約できます。

クエリがパラメーター値に敏感である場合、最適なプランはパラメーター値によって大きく異なることを意味するため、通常、毎回クエリを計画すると成功します。

パラメーターのないクエリは、単一のセッションの有効期間中にテーブルの内容が大幅に変更され、キャッシュされたプランが最適でなくなる場合を除き、常にプランのキャッシュから利益を得ることができます。

于 2018-01-16T08:33:06.703 に答える