より深く知るオプティマイザと そのチューニング 
東京大学生産技術研究所喜連川研究室 
早水悠登川道亮治 
2014/12/05 
PostgreSQLカンファレンス2014 @ 品川AP
ブラックボックスの役割 
2014/12/04 2 
ユーザの”解放”
ブラックボックスと解放 
機能のインターフェースの抽象化 
•“どうやるか” からユーザを解放 
•“やりたいこと” に集中できる 
2014/12/04 3 
リレーショナルデータベースシステム 
•データ処理のブラックボックス
データ処理におけるユーザ解放の歩み 
•アナログ計算器:アンティキティラ島の機械(紀元 前150-100年) など 
•脳内の演算実行からの解放 
•自動計算機械:シッカートの計算機(1623) など 
•演算の実行操作からの解放 
images by Wikimedia commons
データ処理におけるユーザ解放の歩み 
•データ記録の機械化:Tabulating Machine (1840) な ど 
•データ読み書き作業からの解放 
•チューリング機械・電子計算機:ENIAC(1946) など 
•処理手順からの解放 
(cont.) 
images by Wikimedia commons
データ処理におけるユーザ解放の歩み 
•プログラミング言語:FORTRAN(1957), ALGOL58(1958) など 
•機械語からの解放 
•トランザクション処理:SABRE(1960) など 
•データ不整合からの解放 
•リレーショナルモデル:Ingres(1974), System R(1974) など 
•物理的なデータ管理・データ処理方法からの解放 
(cont.)
リレーショナル以前 
• どこにデータがあるか 
• どの順序で処理するか 
• どの方法で処理するか 
2014/12/04 
ユーザナビゲータ 
リレーショナル 
データベース 
• 論理的データと物理的データの分離 
• リレーション・タプル 
• 物理的データ編成は不可視 
• “ほしいデータ”を宣言的に記述 
• データ処理の順序や方法からの解放 
DEPT 
EMP 
PROJ
論理と物理の溝を埋める 
SELECT * FROM DEPT D, EMP E 
WHERE E.D_ID= D.IDAND ... 
•アクセス方式 
•シーケンシャル、索引、・・・ 
•結合方式 
•Nested Loop, Hash, Sort-merge,・・・ 
•集約演算・ソーティング戦略 
•利用するメモリ量・一時ファイル容量 
•・・・ 
クエリオプティマイザ 
リレーショナルデータベースの 
Key enabler
活かすも殺すもオプティマイザ次第 
9 
オプティマイザの理解がリレーショナル 
データベース活用の底力 
進化し続けるテクノロジ
エンジニアの価値 =ブラックボックスの蓋を開ける 
2014/12/04 10
より深く知るオプティマイザ 
2014/12/04 11
クエリ最適化 
与えられたクエリから 
最適なクエリ実行プランを生成 
■“最適”とは? 
•クエリ実行時間が短い 
•系全体のスループットが高い 
•消費電力が低い 
•ボスのクエリだけ最高速 
2014/12/04 12 
など
最適化の枠組み 
• 実行プランのコスト計算式(コストモデル)を設計 
• 最適な実行プランの探索 
• 実行プラン候補の列挙コスト最小のプラン選択 
2014/12/04 13 
コストベース最適化System R (1976) 〜 
コスト: 最適性の指標 
• ≒ 実行時間 
実行時間を見積もる 
コストモデル
Ex) SELECT * FROM EMPWHERE EMP.ID < x 
14 
プラン1: Seq. Scan 
プラン2: Index Scan 
I/Oページ量= (一定) 
x 
I/Oページ量∝x 
I/Oページ量
コストモデル 
クエリ処理を単位処理に分解 
→ ページI/O(seq., random), 1タプル処理, オペレータ実 行, ・・・ 
単位処理の単価と回数によってコストを記述 
2014/12/04 15 
シーケンシャルI/O 
ランダムI/O 
1タプルCPU演算
コストモデル 
単位処理の単価=ハードウェアの特性 
PostgreSQLの場合 
•シーケンシャルI/Oseq_page_cost 
•ランダムI/Orandom_page_cost 
•1タプル処理cpu_tuple_cost 
•1索引タプル処理cpu_index_tuple_cost 
•1回のオペレータ処理cpu_operator_cost 
2014/12/04 16 
オプティマイザのチューニング可能ポイント
コストモデル 
単位処理の回数 
•実行プランやデータ量・分布により変化 
•統計情報を用いた見積り 
•実行プラン毎の計算方法 PostgreSQLの場合 
•SeqScan 
•IndexScan 
•IndexOnlyScan 
•NestLoopJoin 
•HashJoin 
•・・・ 
2014/12/04 17
of SeqScan 
コスト係数 
•関数(演算子)(pg_proc.procostに登録) 
•基本的にコスト係数= 1.0:=, <, >, <=, >=, like, regexp系, ・・・ 
•例外的なもの:obj_description, schema_to_xmlなど 
•ANY / ALL:コスト係数= (演算コスト係数)×(行数見積)×0.5 
•その他文字列を介した型変換、サブプラン等々・・・ 18 
= (テーブルのページ数) 
= (テーブルのタプル数) 
= #qual_operator 
= (タプル数) ×(条件Aコスト係数) 
+ (タプル数) ×(条件Bコスト係数) 
+ ・・・ 
統計情報 
・・・WHERE ANDAND ・・・ 
A 
B 
選択条件(Qual)での 
オペレータ評価回数
of IndexScan 
(A) B+木を下るCPUコスト 
(B) リーフページの索引エントリ走査コスト 
(C) リーフページのI/Oコスト 
(D) テーブルページのI/Oコスト 
(E) タプル走査のCPUコスト 
2014/12/04 19
of IndexScan 
(A) B+木を下るCPUコスト 
(B) リーフページの索引エントリ走査コスト 
2014/12/04 20 
+= log2(#index_tuples) 
ルート付近のB+木ページはI/Oコスト無し 
・・・ほぼバッファプールにキャッシュされている 
+= #qual_operator × #leaf_pages × σ 
選択率σ 
統計情報のヒストグラムやMCVな 
どから見積り
of IndexScan 
(C) I/Oコスト 
索引ページへのI/O 
2014/12/04 21 
+= Y(effective_cache_size, #leaf_pages) 
Mackertand Lohman関数(Yao 関数) 
バッファキャッシュのヒット率を考慮したI/O 回数見積り 
選択率σ
of IndexScan 
(D) テーブルページへのI/Oコスト 
(E) テーブルページ走査CPUコスト 
・タプル数を選択率σから見積り 
・各タプルのコストはSeqScanの場合と同様 
2014/12/04 22 
+= α2 × #match_pages 
索引エントリとテーブルエントリの相関係数α 
α = 0 : ランダムI/O α = 1 : シーケンシャルI/O 
+= (1-α2) × #match_tuples
of NestLoopJoin 
2014/12/04 23 
R⨝S 
Scan R 
r2 
r1 
r3 
r4 
Scan Swith 
r1 
s1 
s2 
s3 
ReScanSwith 
r2 
s1 
s2 
s3 
outer 
inner
of NestLoopJoin 
•#outer_tuples= 1 の場合 
2014/12/04 24 
R⨝S 
Scan R 
r1 
Scan Swith 
r1 
s1 
s2 
s3 
outer 
inner 
Cost = Cost(outer) + Cost(inner) + 
+= #inner_tuples 
+= #qual_operator×#inner_tuples
of NestLoopJoin 
•#outer_tuples> 1 の場合 
R⨝S 
Scan R 
r2 
r1 
r3 
r4 
Scan Swith 
r1 
s1 
s2 
s3 
ReScanSwith 
r2 
s1 
s2 
s3 
outer 
inner 
Cost = Cost(outer) + Cost(inner) + 
+ (#outer_tuples-1) ×Cost(ReScaninner) 
IndexScanのReScanではバッファヒット率が高くなる 
→ 通常のIndexScanより低コスト 
Mackertand Lohman関数の応用により見積り 
+= #inner_tuples×#outer_tuples 
+= #qual_operator×#inner_tuples×#outer_tuples
of HashJoin 
2014/12/04 26
of HashJoin 
Buildフェーズ 
•Cost += Cost(inner) 
2014/12/04 27 
+= #qual_op×#inner_tuples 
+= #inner_tuples 
ハッシュ表作成時の 
ハッシュ関数実行コスト
of HashJoin 
2014/12/04 28 
Buildフェーズ 
•Cost += Cost(inner) 
+= #qual_op×#inner_tuples 
+= #inner_tuples
of HashJoin 
2014/12/04 29 
Buildフェーズ 
•Cost += Cost(inner) 
Probeフェーズ 
•Cost += Cost(outer) 
+= #qual_op×#inner_tuples 
+= #inner_tuples 
+= #qual_op×#bucket_size×0.5 
×#outer_tuples 
+= #match_tuples 
ハッシュ表検索時の 
ハッシュ関数+バケツ内検索コスト
of HashJoin 
2014/12/04 30 
record 
record 
record 
record 
record 
record 
record 
record 
record 
record 
バケツ数: 2 
record 
record 
record 
record 
record 
record 
record 
record 
record 
record 
バケツ数: 5 
record 
record 
record 
record 
record 
record 
record 
record 
record 
record 
build 
平均2.5回のタプル比較 
平均1回のタプル比較 
2.00E+06 
2.20E+06 
2.40E+06 
2.60E+06 
2.80E+06 
0 
50000 
100000 
150000 
Cost 
inner表選択数 
Cost Estimation of Hash Join 
・PostgreSQLのバケツサイズ戦略 
→ inner表選択数に応じて2倍ずつ増やす 
・バケットサイズ拡大直後はコストが低下
of HashJoin 
2014/12/04 
•メモリに収まらない場合: Hybrid Hash Join 
•inner 表とouter 表をハッシュ関数でパーティション分 割してディスク書き込み 
•パーティション毎にinner 表のハッシュ表をbuildouter表をprobe 
+=#inner_pages+ #outer_pages 
+=#inner_pages+ #outer_pages
コストベース最適化ここまでのまとめ 
•実行プランのコストモデル設計 
•候補プランの探索 
2014/12/04 32 
⇔ハードウェア特性 
seq_page_cost 
random_page_cost 
cpu_tuple_cost 
cpu_index_tuple_cost 
cpu_operator_cost 
⇔処理方式・データ特性 
•統計情報 
•ページ数、タプル数、選択率、・・・ 
•アクセスパス 
•SeqScan, IndexScan, ... 
•結合方式 
•NestLoopJoin, HashJoin 
•・・・
コストベース最適化ここまでのまとめ 
•実行プランのコストモデル設計 
•候補プランの探索 
2014/12/04 33 
⇔ハードウェア特性 
seq_page_cost 
random_page_cost 
cpu_tuple_cost 
cpu_index_tuple_cost 
cpu_operator_cost 
⇔処理方式・データ特性 
•統計情報 
•ページ数、タプル数、選択率、・・・ 
•アクセスパス 
•SeqScan, IndexScan, ... 
•結合方式 
•NestLoopJoin, HashJoin 
•・・・
候補プランの探索 
⇔リレーション結合順序の決定 
愚直に列挙すると組み合わせ爆発 
•動的計画法(DP)による網羅的探索 
•少数のリレーション結合の王道 
•ヒューリスティクスによる探索 
•多数のリレーションの妥協策 
2014/12/04 34 
A⨝B⨝C 
A 
B 
⨝ 
C 
⨝ 
A 
C 
⨝ 
B 
⨝ 
B 
A 
⨝ 
C 
⨝ 
A 
B 
⨝ 
C 
⨝ 
A 
C 
⨝ 
B 
⨝ 
B 
A 
⨝ 
C 
⨝ 
・・・
動的計画法によるプラン探索 
•「最適な実行プランの一部もまた最適」と仮定 
•部分的な結合ごとに最適プランを探索 
•最適でないプランを破棄→ 探索候補数の削減 
•結合の数を増やしながら最適プランを逐次探索 
•PostgreSQLのオプティマイザ 
2014/12/04 35 
Left-deep join tree 
Right-deep join tree 
Bushy join tree 
⨝ 
⨝ 
⨝ 
⨝ 
⨝ 
⨝ 
⨝ 
⨝ 
⨝
Ex) A ⨝B ⨝C ⨝D
Ex) A ⨝B ⨝C ⨝D
Ex) A ⨝B ⨝C ⨝D
動的計画法によるプラン探索 
• 探索候補数削減のための工夫 
• 結合条件のある結合のみを考慮 
(ex. ・・・FROM A, B WHERE A.id = B.a_id ・・・) 
• ソート順序による制限 
• 結合リレーション数N 
• 探索候補数O(N!) 
• 探索時間が急速に増加 
→ 大きいNにはヒューリスティクス 
2014/12/04 39
ヒューリスティクス 
•「ある程度よいプランを」「ある程度の時間内に」 
•初期の候補プラン群を生成 
•一定のルールに従い候補プラン群から 次の候補プラン群を生成 
•一定時間繰り返して候補プラン群 を良くしてゆく 
•遺伝的アルゴリズム 
•PostgreSQLのGEQO(N ≧12) 
•焼きなまし法 
•PGCon2010 
2014/12/04 40
コストベース最適化まとめ 
•実行プランのコストモデル設計 
•候補プランの探索 
•動的計画法による網羅的探索 
•ヒューリスティクス:遺伝的アルゴリズム、焼きなまし法 
2014/12/04 41 
⇔ハードウェア特性 
seq_page_cost 
random_page_cost 
cpu_tuple_cost 
cpu_index_tuple_cost 
cpu_operator_cost 
⇔処理方式・データ特性 
•統計情報 
•ページ数、タプル数、選択率、・・・ 
•アクセスパス 
•SeqScan, IndexScan, ... 
•結合方式 
•NestLoopJoin, HashJoin 
•・・・
PostgreSQL! 
クエリ最適化の研究 
•System R (1976) 
•動的計画法によるコストベース最適化 
•Challenging な取り組み 
•Multi-query optimization [T.Sellis, 1987] 
•Dynamic mid-query re-optimization [N.Kabraet.al., 1998] 
•Query progress indicator [G.Luoet.al., 2004] 
•Access cost estimation on distributed object storage [B.Araiet.al., 2010] 
•Query optimization for hierarchical partitioning [H.Herodotouet.al., 2011] 
•SDN-powered optimizer on distributed storage [P.Xionget.al., 2014] 
•Cost estimation improvement with proactive subset query execution [A.Duttet.al., 2014] 
•Pilot Run によるUDFコスト推定[K.Karanasoset.al., 2014] 
2014/12/04 42
まとめ 
•リレーショナルモデルとオプティマイザの 切っても切れない関係 
•コストベース最適化 
2014/12/04 43

より深く知るオプティマイザとそのチューニング