会社で聞かれた 「UNION が含まれるビューがあるんだけど、インデックス使ってくれる?」という 質問に対して 「データベースがそっちの方が効率が良いと判断したら使ってくれるし、実行計画を取ってみれば?」という 回答をしたんですが、念のため試してみます。
まず、テスト用のテーブルにデータを登録します。
INSERT INTO table1 (f1) SELECT generate_series FROM generate_series(1, 10000);
INSERT INTO table2 (f1) SELECT generate_series FROM generate_series(1, 10000);
generate_series 関数は、便利ですね。
まずお試しに単純な SQL で実行計画を取得。 もちろん事前にテーブルを Analyze しておきます。
EXPLAIN SELECT * FROM table1 WHERE f1 = 1
↓結果
Index Scan using table1_pkey on table1 (cost=0.00..8.27 rows=1 width=8)
Index Cond: (f1 = 1)
インデックス table1_pkey が使用されています。
次に副問い合わせで UNION ALL して実行計画を取得。
EXPLAIN SELECT * FROM (SELECT * FROM table1 UNION ALL SELECT * FROM table2) AS t1 WHERE f1 = 1
↓結果
Result (cost=0.00..16.54 rows=2 width=8) -> Append (cost=0.00..16.54 rows=2 width=8) -> Index Scan using table1_pkey on table1 (cost=0.00..8.27 rows=1 width=8) Index Cond: (f1 = 1) -> Index Scan using table2_pkey on table2 (cost=0.00..8.27 rows=1 width=8) Index Cond: (f1 = 1)
これもちゃんと、インデックス table1_pkey と table2_pkey が使用されています。
ちなみに UNION ALL じゃなくて UNION の場合。
EXPLAIN SELECT * FROM (SELECT * FROM table1 UNION SELECT * FROM table2) AS t1 WHERE f1 = 1
↓結果
Unique (cost=16.57..16.58 rows=2 width=8) -> Sort (cost=16.57..16.57 rows=2 width=8) Sort Key: table1.f1, table1.f2 -> Append (cost=0.00..16.56 rows=2 width=8) -> Index Scan using table1_pkey on table1 (cost=0.00..8.27 rows=1 width=8) Index Cond: (f1 = 1) -> Index Scan using table2_pkey on table2 (cost=0.00..8.27 rows=1 width=8) Index Cond: (f1 = 1)
こちらもインデックスは使ってくれます。
念のため、ビューを作成して試してみます。
CREATE VIEW view1 AS SELECT * FROM (SELECT * FROM table1 UNION ALL SELECT * FROM table2) AS t1
ビューに対して実行計画を取得。
EXPLAIN SELECT * FROM view1 WHERE f1 = 1
↓結果
Result (cost=0.00..16.54 rows=2 width=8) -> Append (cost=0.00..16.54 rows=2 width=8) -> Index Scan using table1_pkey on table1 (cost=0.00..8.27 rows=1 width=8) Index Cond: (f1 = 1) -> Index Scan using table2_pkey on table2 (cost=0.00..8.27 rows=1 width=8) Index Cond: (f1 = 1)
結果は副問い合わせと同じでした。
こういうのは、自分の手で試しておくと安心ですね。