会社で聞かれた 「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)
結果は副問い合わせと同じでした。
こういうのは、自分の手で試しておくと安心ですね。