18. 式の簡略化
コストベース最適化の効率を高めるための式変形
最適化の単位 = サブクエリ → サブクエリの個数を減らす
Join
SubQuery Scan Join
Join Scan Scan Scan
Scan Scan
ルールベース = 開発者のノウハウの書き下し
副問合せの引き上げ(pull-up)
IN, ANY, サブクエリ, 明示的JOINなどを親クエリに一体化
OUTER JOIN を INNER JOIN に変換
例:SELECT ... FROM A LEFT JOIN B ON (...) WHERE B.y = 42;
関数のインライン化
関数内外を跨った最適化 (SQLで書かれた関数のみ)
18
19. 例:明示的なJOINをFROM句に変換
SQL SELECT * FROM A, B WHERE
A.i = B.i AND A.x = 10 AND B.y < 100;
SELECT * FROM A JOIN B ON A.i = B.i
WHERE A.x = 10 AND B.y < 100;
SELECT * FROM A,
(SELECT * FROM B WHERE y < 100) B
WHERE A.i = B.i AND A.x = 10;
Join
A.i = B.i
最適化しやすい
表現に変換
Scan on A Scan on B
A.x = 10 B.y < 100
19
20. 式の事前評価
事前評価
暗黙の条件の追加 / 冗長な条件の削除
定数式(処理の間、結果が変わらない式)の最適化
条件の追加と削除
暗黙の条件の明示化
例:A=B and B=C ⇒ A=C
冗長な条件の削除
例:10 < x AND 20 < x ⇒ 20 < x
例:X OR TRUE ⇒ TRUE
定数式の最適化
Plannerの時点で先に結果を求めておく
例:abs(-5) ⇒ 5
20
33. Joinの順番
テーブル A
結合 AB
テーブル B 結合 ABC
SELECT * テーブル C
FROM A, B, C
WHERE テーブル A
A.foo = B.foo
テーブル B 結合 ABC
AND
結合 BC
B.bar = C.bar 2つずつ
テーブル C
AND 結合
…; テーブル A
結合 CA
テーブル B 結合 ABC
テーブル C
33
関係の指定が無いため
34. Pathの列挙
A
•SeqScan
AB
•IndexScan
•NestLoop
•BitmapScan
•MergeJoin
•HashJoin ABC
B
C
Scan
SeqScan
有用なインデックスを使ったIndexScan
有用なインデックスを組み合わせたBitmapScan
Join
NestLoop (内外入れ替え)
MergeJoin (ソート済み or コスト最小+ソート)
HashJoin (内外入れ替え)
34
40. 実行計画生成の仕上げ
MIN/MAX用の特別な最適化
MIN/MAX を以下の形に置き換え
ORDER BY column ASC/DESC LIMIT 1
集約関数にもかかわらずインデックスが使える
集約関数は基本的にはインデックスを使わない
(SUM, AVERAGE, …)
実行計画のトップノードとして追加
GROUP BY 用の集約ノード
ORDER BY 用のソートノード
DISTINCT 用の重複除去ノード (Sort + Unique)
40
43. 値の内容による最適な実行計画の変化
候補となる行数が変化すると、
最適な実行計画が変わる場合がある
例:SELECT * FROM A, B WHERE
A.x = X AND B.y = Y AND A.id = B.id
A.x = X の絞込みが強い
絞込みの強さ
NestLoop 外:A→内:B
B.y = Y の絞込みが強い Join
A.id = B.id
NestLoop 外:B→内:A
IndexScan + HashJoin
Scan Scan
SeqScan + HashJoin
A.x = X B.y = Y
IndexScan + MergeJoin
43
53. 複数の選択条件の認識
複数の選択条件
独立とみなす
Selectivity(A and B) = Selectivity(A) × Selectivity(B)
範囲選択条件
Selectivity(A < x < B) =
Selectivity(A < x) + Selectivity(x < B) - 1
最小値 A<x
x<B 最大値
53
54. 統計情報を利用できない場合
定数名 値 説明
DEFAULT_EQ_SEL 0.5% 等号 A = b
DEFAULT_INEQ_SEL 33.3% 不等号 A < b
DEFAULT_RANGE_INEQ_SEL 0.5% 範囲 b < A < c
DEFAULT_MATCH_SEL 0.5% LIKE
DEFAULT_UNK_SEL 0.5% IS NULL
DEFAULT_NUM_DISTINCT 200 = 1/EQ_SEL
(未知のテーブルの行数) ページ数/行サイズ or 1000
工夫されている点
行/ページ = ~100 程度を仮定
EQ は 1%(ページごとひとつずつ)より低い
RANGE (0.5%) ≠ INEQ2 (11.1%)
54
64. EXPLAINコマンド
EXPLAIN : 実行計画を見るためのコマンド
例
EXPLAIN SELECT i FROM tbl WHERE i = 10;
出力
Index Scan using idx on tbl
① (cost=0.00..3.07 rows=5 width=4)
Index Cond: (i = 10) ② ③
解釈
① テーブル tbl を インデックス idx を使って読み取り
② 初期コストは0.00, 総合コストは3.07
③ 5行が出力されると推定
64
65. 例:SQLの書き方とインデックスの使用可否
1. min, max (8.0以前)
SELECT min(x) FROM …;
SELECT x FROM … ORDER BY x LIMIT 1;
2. キャスト (7.4以前)
WHERE int8column = 4;
WHERE int8column = 4::int8;
※8.0以降も int4→OID→int8 のキャストには注意
3. 計算
WHERE lower(文字列) = ‘abc’;
CREATE INDEX index ON table ( lower(文字列) );
WHERE floor(整数/10) = 16;
WHERE 整数 BETWEEN 10*16 AND 10*(16+1)-1;
65
66. 例:統計情報の精度不足
サンプリング数の設定
ALTER TABLE table ALTER column SET STATISTICS 1-1000 ;
EXPLAIN ANALYZE
SELECT … FROM order_line, item
WHERE ol_o_id = N AND ol_i_id = i_id ORDER BY ol_i_id;
STATISTICS = 10
Merge Join (cost=2779.93 rows=1832) (actual time=116.244 rows=3)
Merge Cond: ("outer".ol_i_id = "inner".i_id)
→ Sort (rows=1834) (rows=3) Sort Key: ol_i_id
→ Index Scan using idx_ol_o_id on order_line (rows=1834) (rows=3)
Index Cond: (ol_o_id = N::numeric)
→ Sort (rows=10010) (rows=7924) Sort Key: i_id
→ Seq Scan on item i (rows=10010) (rows=10000)
STATISTICS = 1000
Sort (cost=53.69 rows=16) (actual time=0.125 rows=3) Sort Key: ol_i_id
→ Nested Loop (rows=16) (rows=3)
→ Index Scan using idx_ol_o_id on order_line (rows=16) (rows=3)
Index Cond: (ol_o_id = N::numeric)
→ Index Scan using pk_i on item (rows=1) (rows=1)
Index Cond: ("outer".ol_i_id = i_id)
66