4

PostgresQL9.1用のPg/PLSQL関数を開発しています。SQLクエリで変数を使用すると、オプティマイザは不適切な実行プランを作成します。しかし、変数をその値に置き換えれば、計画は大丈夫です。例えば:

v_param := 100;
select count(*)
  into result
  from <some tables>
 where <some conditions>
       and id = v_param

3秒で実行

select count(*)
  into result
  from <some tables>
 where <some conditions>
       and id = 100

300msで実行

最初のケースでは、オプティマイザはv_paramの任意の値に対して固定プランを生成します。

2番目のケースでは、オプティマイザーは指定された値に基づいてプランを生成し、プランのキャッシュを使用しないにもかかわらず、大幅に効率的です。

オプティマイザーを動的バインディングなしでプランを生成し、クエリを実行するたびにプランを生成するようにすることは可能ですか?

4

2 に答える 2

7

これは、リリースされたばかりのPostgreSQL9.2のTomLaneによって劇的に改善されました。特にPostgreSQL9.2の新機能を参照してください。

プリペアドステートメントは、パラメータの値を知らなくても、一度最適化されていました。9.2では、プランナーは送信されたパラメーターに関して特定のプランを使用します(クエリは実行時にプランニングされます)。ただし、クエリが複数回実行され、プランナーが一般的なプランが特定のプランよりもそれほど高価ではないと判断した場合を除きます。 。

SET enable_...これは、以前はパラメータ、を使用したラッパー関数の使用EXECUTE、またはその他の醜いハックが必要だった、長年の苦痛な疣贅でした。これで、「正常に機能する」はずです。

アップグレード。

auto_explainこれを読んでいる他の人は、パラメータ化/準備されたクエリの計画が自分でクエリを実行したときに得られるものとは異なるため、この問題があなたを悩ませているかどうかを知ることができexplainます。確認するには、PREPARE ... SELECTそれEXPLAIN EXECUTEを試して、別のプランを取得するかどうかを確認してくださいEXPLAIN SELECT

この以前の回答も参照してください。

于 2012-09-11T11:22:46.930 に答える
3

動的クエリはキャッシュされたプランを使用しないため、9.1以前ではEXECUTEUSINGステートメントを使用できます。クレイグが書いたように、9.2はこの回避策なしで動作するはずです。

v_param := 100;
EXECUTE 'select count(*) into result from <some tables> where <some conditions>
   and id = $1' USING v_param;
于 2012-09-11T11:31:51.350 に答える