2017-04-02 6 views
2

私はPostgreSQL 9.6で問題があることを理解している(そしておそらく改善する)のは興味深いです。名前は簡略化されていますが、それ以外はすべてpsqlセッションから取得されます。クエリでのCOUNTの動作とEXPLAINの比較対関数

まず、マテリアライズド・ビューmvから始めます。

CREATE FUNCTION count_mv() RETURNS BIGINT AS $$ 
SELECT COUNT(*) FROM mv; 
$$ LANGUAGE SQL STABLE PARALLEL SAFE; 

CREATE FUNCTION mv_pks() RETURNS TABLE (table_pk INTEGER) AS $$ 
SELECT table_pk FROM mv; 
$$ LANGUAGE SQL STABLE PARALLEL SAFE; 

レッツ・時間いくつかのクエリ:

まず、私は2つの単純な関数を作成します。

db=>\timing on

私は非常に迅速に、マテリアライズド・ビューからの結果をカウントすることができます。

db=> SELECT COUNT(*) FROM mv; 
    count 
--------- 
2567883 
(1 row) 

Time: 79.803 ms 

これがどのように行われているか見てみましょう。

db=> EXPLAIN ANALYZE SELECT COUNT(*) FROM mv; 
                    QUERY PLAN 
----------------------------------------------------------------------------------------------------------------------------------------------- 
Finalize Aggregate (cost=41331.24..41331.25 rows=1 width=8) (actual time=765.681..765.681 rows=1 loops=1) 
    -> Gather (cost=41330.62..41331.23 rows=6 width=8) (actual time=765.557..765.670 rows=7 loops=1) 
     Workers Planned: 6 
     Workers Launched: 6 
     -> Partial Aggregate (cost=40330.62..40330.63 rows=1 width=8) (actual time=760.175..760.175 rows=1 loops=7) 
       -> Parallel Seq Scan on mv (cost=0.00..39261.09 rows=427809 width=0) (actual time=0.014..397.952 rows=366840 loops=7) 
Planning time: 0.326 ms 
Execution time: 769.934 ms 
(8 rows) 

良い。だから、それは複数の労働者を利用しています。しかし、なぜEXPLAIN ANALYZEを使用するとクエリが非常に遅くなるのですか?

ここではcount_mv()関数を使用していますが、と同じ SQLがあり、STABLEと宣言されています。

db=> select count_mv(); 
    count_mv 
------------ 
    2567883 
(1 row) 

Time: 406.058 ms 

Whoa!これはマテリアライズド・ビューの同じSQLよりも遅いのはなぜですか?そしてずっと遅い!それは平行労働者を利用していないのですか?以下の回答で提案されているよう

はEDIT

をBEGIN、私はauto_explainモジュールをロードし、関数呼び出しにEXPLAINのログ出力をチェックします。

Query Text: 
    SELECT COUNT(*) FROM mv; 

    Finalize Aggregate (cost=41331.60..41331.61 rows=1 width=8) (actual time=1345.446..1345.446 rows=1 loops=1) 
     -> Gather (cost=41330.97..41331.58 rows=6 width=8) (actual time=1345.438..1345.440 rows=1 loops=1) 
      Workers Planned: 6 
      Workers Launched: 0 
      -> Partial Aggregate (cost=40330.97..40330.99 rows=1 width=8) (actual time=1345.435..1345.435 rows=1 loops=1) 
        -> Parallel Seq Scan on mv (cost=0.00..39261.38 rows=427838 width=0) (actual time=0.020..791.022 rows=2567883 loops=1) 

新たな質問は、6人の従業員が計画されていますが、誰も立ち上げられない理由です。サーバーはアイドル状態であり、構成は同じであり、照会は同じです。

のEND EDIT

すべての権利。それでは、私はこれを行う場合:

直接 EXPLAIN ANALYZEを使用せずに、マテリアライズド・ビューの行をカウントしていますが、ここで私を信頼する必要がありますと同じ性能
db=> SELECT COUNT(*) FROM mv_pks(); 
    count 
--------- 
2567883 
(1 row) 

Time: 72.687 ms 

:この機能のパフォーマンスはの状態に依存関数が作成されたときにマテリアライズド・ビュー。ここでの高速なタイミングは、テーブルが空のときに関数を作成した結果です。テーブルがいっぱいになったときに関数を再作成すると、関数は1000ミリ秒以上実行する必要があります。

  1. なぜSTABLE SQL関数内のSQLクエリは、その関数の外側のクエリよりもそんなに遅くはパラメータを取っていない:私の質問に要約する

  2. EXPLAIN ANALYZEを使用するとSQLクエリが非常に遅くなるのはなぜですか?
  3. なぜマテリアライズド・ビューまたは他の方法よりも遅くに行を数えるに、等価的に高速のいずれかとすることができる機能から行を数えるとき、私は、関数を作成したときに応じて、すべての異なった結果を得るのですか?

ありがとうございます!

1の場合

答えて

1

)、あなたは、関数内のクエリのための計画を示すことができauto_explainを、使用して自分自身を見つけることができます。パラレルプランを使用していますか? 2について

)は、プラットフォームに依存する測定のオーバーヘッドであるが、高くすることができます。

3については

)は、いずれの場合も、SQL計画を比較します。 SQL関数のクエリはキャッシュされていないので、なぜこのように振る舞うべきなのか説明はありません。ディスクからの読み取りとキャッシュからの読み取りの効果を確認するために、テストを複数回繰り返しましたか?

+0

お返事ありがとうございます。 1)素晴らしいモジュール。それは多くのことに非常に役立ちます。新しい説明出力からの並列性の欠如の背後にある理由についての考えはありますか? 2)それを得ました。意味をなさない。それはほぼ10倍だと驚いた。 3)はい。私は何度も試してみました。私は同じSQLで2つの機能を持っていましたが、作成時間が違うため、前後に1つずつ実行して、これらの異なる結果を得ることができました。奇妙な! – rg6

+0

ポイント3)はまだ私には不明です。私は実験しましたが、再現できませんでした。再現可能なテストケースを考え出すことができますか? –

+0

1)の編集を追加しました。賞について:関数内の同じSQLがなぜそれが計画している並列性を使用しないのかについて、あなたはコメントできますか?あるいは、私はEXPLAIN出力を誤解していますか? 3)テストケースではどのような動作が見られますか?いいえ、私はこれを確実に再現することはできません。それはそれほど満足できるものではありません。昨日、私は高速なパフォーマンスで機能を作成できませんでした。今日私はパフォーマンスが遅いものを作ることはできません。それでも、パフォーマンスの異なる既存の関数は、 '\ df +'と同じコードを示します。 – rg6

関連する問題