2016-04-06 11 views
2

私はPostgreSQLのを使用していると私は私のSQLクエリとの奇妙な問題を抱えています。 私はを使用していPARAMTERウィッヒ日によって。私の要求は同じ操作をしません。は、ネステッド・ループを使用したSQLクエリのパフォーマンスを向上させる - PostgreSQLの

これは私の作業クエリです:

SELECT DISTINCT app.id_application 
FROM stat sj 
LEFT OUTER JOIN groupe gp ON gp.id_groupe = sj.id_groupe 
LEFT OUTER JOIN application app ON app.id_application = gp.id_application 
WHERE date_stat >= '2016/3/01' 
AND date_stat <= '2016/3/31' 
AND (date_stat = date_gen-1 or (date_gen = '2016/04/01' AND date_stat = '2016/3/31')) 
AND app.id_application IS NOT NULL 

このクエリは、(私は行の多くを持っているので、私のために大丈夫です)周りの2 secondesをとります。私たちは4月6日です現在の月の同じクエリ(をしようとしているときは、今

HashAggregate (cost=375486.95..375493.62 rows=667 width=4) (actual time=2320.541..2320.656 rows=442 loops=1) 
    -> Hash Join (cost=254.02..375478.99 rows=3186 width=4) (actual time=6.144..2271.984 rows=263274 loops=1) 
    Hash Cond: (gp.id_application = app.id_application) 
    -> Hash Join (cost=234.01..375415.17 rows=3186 width=4) (actual time=5.926..2200.671 rows=263274 loops=1) 
      Hash Cond: (sj.id_groupe = gp.id_groupe) 
      -> Seq Scan on stat sj (cost=0.00..375109.47 rows=3186 width=8) (actual time=3.196..2068.357 rows=263274 loops=1) 
       Filter: ((date_stat >= '2016-03-01'::date) AND (date_stat <= '2016-03-31'::date) AND ((date_stat = (date_gen - 1)) OR ((date_gen = '2016-04-01'::date) AND (date_stat = '2016-03-31'::date)))) 
       Rows Removed by Filter: 7199514 
      -> Hash (cost=133.45..133.45 rows=8045 width=12) (actual time=2.677..2.677 rows=8019 loops=1) 
       Buckets: 1024 Batches: 1 Memory Usage: 345kB 
       -> Seq Scan on groupe gp (cost=0.00..133.45 rows=8045 width=12) (actual time=0.007..1.284 rows=8019 loops=1) 
    -> Hash (cost=11.67..11.67 rows=667 width=4) (actual time=0.206..0.206 rows=692 loops=1) 
      Buckets: 1024 Batches: 1 Memory Usage: 25kB 
      -> Seq Scan on application app (cost=0.00..11.67 rows=667 width=4) (actual time=0.007..0.101 rows=692 loops=1) 
       Filter: (id_application IS NOT NULL) 
    Total runtime: 2320.855 ms 

ので、私はすべて取得しようとしている:私はEXPLAIN実行すると、このクエリに対してANALYZE私はこれを持っています同じクエリ

SELECT DISTINCT app.id_application 
FROM stat sj 
LEFT OUTER JOIN groupe gp ON gp.id_groupe = sj.id_groupe 
LEFT OUTER JOIN application app ON app.id_application = gp.id_application 
WHERE date_stat >= '2016/04/01' 
AND date_stat <= '2016/04/30' 
AND (date_stat = date_gen-1 or (date_gen = '2016/05/01' AND date_job = '2016/04/30')) 
AND app.id_application IS NOT NULL 

4月のAPPLICATION_ID)は、このクエリは現在、120秒かかります。

HashAggregate (cost=375363.50..375363.51 rows=1 width=4) (actual time=186716.468..186716.532 rows=490 loops=1) 
-> Nested Loop (cost=0.00..375363.49 rows=1 width=4) (actual time=1.945..186619.404 rows=118990 loops=1) 
    Join Filter: (gp.id_application = app.id_application) 
    Rows Removed by Join Filter: 82222090 
    -> Nested Loop (cost=0.00..375343.49 rows=1 width=4) (actual time=1.821..171458.237 rows=118990 loops=1) 
      Join Filter: (sj.id_groupe = gp.id_groupe) 
      Rows Removed by Join Filter: 954061820 
      -> Seq Scan on stat sj (cost=0.00..375109.47 rows=1 width=8) (actual time=0.235..1964.423 rows=118990 loops=1) 
       Filter: ((date_stat >= '2016-04-01'::date) AND (date_stat <= '2016-04-30'::date) AND ((date_stat = (date_gen - 1)) OR ((date_gen = '2016-05-01'::date) AND (date_stat = '2016-04-30'::date)))) 
       Rows Removed by Filter: 7343798 
      -> Seq Scan on groupe gp (cost=0.00..133.45 rows=8045 width=12) (actual time=0.002..0.736 rows=8019 loops=118990) 
    -> Seq Scan on application app (cost=0.00..11.67 rows=667 width=4) (actual time=0.003..0.073 rows=692 loops=118990) 
      Filter: (id_application IS NOT NULL) 
    Total runtime: 186716.635 ms 

だから私はこの問題は、公演があるまで、私のクエリから条件の数を減らすことによって、どこから来たのか検索することを決めた。だから私も、このクエリに分析し、今では同じ操作を持っていないEXPLAIN走りましたもう一度受け入れてください。

だからのみ、このパラメータ

WHERE date_stat >= '2016/04/01' 

でそれは(最初の作業のクエリなど)のみ1.9secondes を取り、それはまた、2つのパラメータで働いている:

WHERE date_stat >= '2016/04/01' 
AND app.id_application IS NOT NULL 

しかし、私は追加しようとすると、それらの行のうちの1つ私はExplainのネストされたループを持っています

AND date_stat <= '2016/04/30' 
AND (date_stat = date_gen-1 or (date_gen = '2016/05/01' AND date_stat = '2016/04/30')) 

誰かがどこから来るか考えていますか?

+1

は '両方のクエリにANALYZE'を説明し、あなたの質問に両方の出力を追加実行します。また、そのテーブルにインデックスがありますか? –

+0

は、日付を変更すると、オプティマイザは、より多くの行 – Mihai

+0

@Mihaiそれともオプティマイザ「thiks」があるより多くの行をスキャンする必要がありますを意味し、データ配信の問題かもしれません。だから、 'ANALYZE'出力をEXPLAIN(やテーブルの上にANALYZE VACUUMを実行する)私たちを与える方が良いでしょう。あなたが知っているように、dbクエリの最適化に関する限り、「できる」、「できる」、「可能かもしれない」がたくさんあるからです。 –

答えて

3

オプティマイザの推定に問題がありますように[OK]を、それが見えます。彼は4月のためだけ1 rowので、彼は行(その場合の118,990)の大多数のための非常に非効率的であるNESTED LOOPを選ぶがあることをthiks。

  1. テーブルごとにVACCUUM ANALYZEを実行します。これは、死んだタプルや統計をリフレッシュします。
  2. dates再実行

CREATE INDEX date_stat_idx ON <table with date_stat> USING btree (date_stat);のようなクエリに基づいてインデックスを追加することを検討し、

+1

私はVACUM ANALYZE(1 Cのみ)を実行し、パフォーマンスを向上させました(120秒から10秒まで)。私は今、パフォーマンスを向上させるために、インデックスで遊ぶことを試みます、ありがとうございます。 – Dabeliuteef

関連する問題