2016-04-06 12 views
1

私はマスター/ディテールテーブルの状況があります。マスターテーブルのすべてのエントリについて、私はディテールテーブルで数十を持っています。patial第2テーブルのデータを基にしたインデックス

これらは私のテーブルであると言うことができます:

+----------------------- 
| Master 
+----------------------- 
| master_key integer, 
| insert_date timestamp 
+----------------------- 

+----------------------- 
| Detail 
+----------------------- 
| detail_key integer, 
| master_key integer 
| quantity numeric 
| amount numeric 
+----------------------- 

そして、私の最も使用されるクエリは

SELECT extract(year from insert_date) AS Insert_Year, extract(month from insert_date) AS Insert_Month, sum(quantity) AS Quantity, sum(amount) AS Amount 
FROM Master, Detail 
WHERE (amount not null) and (insert_date <= '2016-12-31') and (insert_date >= '2015-01-01') and (Detail.master_key=Master.master_key) 
GROUP BY Insert_Year, Insert_Month 
ORDER BY Insert_Year ASC, Insert_Month ASC; 

のようなものである。このクエリは、長年のデータのトンが両方のテーブルに存在するため、減速するなり、 。原因

私は両方のテーブルにインデックスを持っているとEXPLAIN ANALYZEはINDEXスキャンが穴の実行時間の80%以上のモードを取ることを私に伝えます。

"Sort (cost=44013.52..44013.53 rows=1 width=19) (actual time=17073.129..17073.129 rows=16 loops=1)" 
" Sort Key: (date_part('year'::text, master.insert_date)), (date_part('month'::text, master.insert_date))" 
" Sort Method: quicksort Memory: 26kB" 
" -> HashAggregate (cost=44013.49..44013.51 rows=1 width=19) (actual time=17073.046..17073.053 rows=16 loops=1)" 
"  Group Key: date_part('year'::text, master.insert_date), date_part('month'::text, master.insert_date)" 
"  -> Nested Loop (cost=0.43..43860.32 rows=15317 width=19) (actual time=0.056..15951.178 rows=843647 loops=1)" 
"    -> Seq Scan on master (cost=0.00..18881.38 rows=3127 width=12) (actual time=0.027..636.202 rows=182338 loops=1)" 
"     Filter: ((date(insert_date) >= '2015-01-01'::date) AND (date(insert_date) <= '2016-12-31'::date))" 
"     Rows Removed by Filter: 443031" 
"    -> Index Scan using idx_detail_master_key on detail (cost=0.43..7.89 rows=7 width=15) (actual time=0.055..0.077 rows=5 loops=182338)" 
"     Index Cond: (master_key = master.master_key)" 
"     Filter: (amount IS NOT NULL)" 
"     Rows Removed by Filter: 2" 
"Planning time: 105.317 ms" 
"Execution time: 17073.396 ms" 

私の考えは、インデックスのサイズを部分的に定義して減らすことでした。ほとんどの場合、過去2年間のデータのみが照会されます。これはそれだけで概念実証する必要があり、最終版ではありませんし、それが失敗した原因の

CREATE INDEX idx_detail_table_master_keys 
ON detail (master_key) 
WHERE master_key in (SELECT master_key FROM master WHERE (extract(year from insert_date) = 2016) or (extract(year from insert_date) = 2015)) 

は、だから私はそのような何かを試してみました。 PGAdminインデックス作成でサブセレクトを使用できないと伝えます。

だから私の質問は:それは他のテーブルのデータに基づか、部分インデックスを作成するためにposipleていますか?

私はこのような星座をスピードアップするヒントに感謝します。

よろしく

+0

のコメントを見る[編集]あなたの質問と 'の出力を追加クエリーのために 'explain(analyze、verbose)'を実行します。無関係ですが、 'where'句で古い旧式の暗黙的な結合ではなく、明示的な' JOIN'演算子を実際に使い始めるべきです。 –

+0

@a_horse_with_no_name:EXPLAIN結果に合わせるために、詳細テーブルとクエリをdesimplyfyしました。しかし、その完了;)。 この質問のアイデアは、私の現在のクエリを改善するだけでなく、一般的に同様の構成をスピードアップする方法を学ぶことです。なぜ私はできるだけシンプルにしようとしたのですか? – Mike

+1

@Mike 'CREATE INDEX idx_detail_table_master_insertのように' date(insert_date)のインデックスを作成してみてください。 ONマスターを使用していますbtree(date(insert_date)) ' –

答えて

0

のPostgreSQLなどのリレーショナルデータベースが参加する3つの方法があるので別のテーブルのデータに基づか、部分インデックスを作成することはできません:ネストされたループ、ハッシュ結合やソートマージを。これらのメソッドはすべて、結合のテーブルを別々にロードします。データベース・オプティマイザは、これらのメソッドのどちらを使用するか、またどの方向で結合を実行するかを決定するため、別の表のデータをカバーする表索引を作成することは意味がありません。そのため、そのようなインデックスを定義することはできません。このトピックについてのより詳細な説明はここで見つけることができます:http://use-the-index-luke.com/sql/join(およびオンラインブックの次のセクションを)

さらなる最適化のためにガブリエルのメッセンジャー

関連する問題