postgresqlの実行計画を読み解こう(osc2015 spring/tokyo)
TRANSCRIPT
![Page 1: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/1.jpg)
1
やまそふと
PostgreSQLの実行計画を読み解こう-PostgreSQL SQLチューニング入門-
オープソース カンファレンス 2015 Tokyo/Spring株式会社アシスト
山田 聡
![Page 2: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/2.jpg)
2
Who am I ?
名前:山田 聡(やまだ さとし)
会社:株式会社アシスト
仕事:PostgreSQL+PPASのサポート (●racleも...)
PostgreSQL歴:4年
![Page 3: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/3.jpg)
3
今日の目的
実行計画を読み解き(なんとなくでも)問題点を発見できるようになる!
![Page 4: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/4.jpg)
4
アジェンダ
1.実行計画って何?
2.プラン演算子にはどんなものがあるの?
3.どうやって実行計画を作ってるの?
4.切り札!EXPLAIN
5.問題を解決してみよう!
6.まとめ
![Page 5: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/5.jpg)
5
アジェンダ
1.実行計画って何?
2.プラン演算子にはどんなものがあるの?
3.どうやって実行計画を作ってるの?
4.切り札!Explain Plan
5.問題を解決してみよう!
6.まとめ
![Page 6: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/6.jpg)
6
1.実行計画って何?
実行計画とは欲しいデータへの道筋
でも、道筋はひとつとは限らない
![Page 7: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/7.jpg)
7
1.実行計画って何?
交通手段:プラン演算子
目的地:欲しいデータ
![Page 8: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/8.jpg)
8
1.実行計画って何?
実際は複数の交通手段(プラン演算子)を組み合わせて目的地(データ)へたどり着く
![Page 9: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/9.jpg)
9
交通手段
交通手段
交通手段
旅行
交通手段
交通手段
プラン演算子
実行計画
![Page 10: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/10.jpg)
10
アジェンダ
1.実行計画って何?
2.プラン演算子にはどんなものがあるの?
3.どうやって実行計画を作ってるの?
4.切り札!EXPLAIN
5.問題を解決してみよう!
6.まとめ
![Page 11: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/11.jpg)
11
2.プラン演算子にはどんなものがあるの?
PostgreSQLが各ステップでデータへアクセスするための内部的な処理を示すもの
プラン演算子って?
![Page 12: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/12.jpg)
12
2.プラン演算子にはどんなものがあるの?
分類 演算子
表スキャン Seq Scan
Index Scan
Bitmap Index Scan
Bitmap Heap Scan
Index Only Scan
Subquery Scan
Tid Scan
その他 Function Scan
結合 Nested Loop
Merge Join
Hash Join
分類 演算子
検索結果への処理 Group
limit
Unique
Aggregate
Group Aggregate
Result
結果の結合 Append
SetOp
その他の処理補助 Sort
PostgreSQLの演算子は様々
![Page 13: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/13.jpg)
13
2.プラン演算子にはどんなものがあるの?
(1).Seq Scan (2).Index Scan
0
0
0
0
1
(4).Index Only Scan
検索範囲:広 検索範囲:狭
10100
(3).Bit Map Scan検索範囲:中/特殊 検索範囲:特殊
![Page 14: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/14.jpg)
14
2.プラン演算子にはどんなものがあるの?
・最も基本的なアクセス方法
・取り出す件数が多い時に有効
・表の最後までアクセスする
・シーケンシャルアクセス
表
(1).Seq Scan検索範囲:広
![Page 15: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/15.jpg)
15
2.プラン演算子にはどんなものがあるの?
33
44
66
77
99
63
・取り出す件数が少ない時に有効
・インデックスとテーブルを 交互にアクセス
・ランダムアクセス
表インデックス
(2).Index Scan検索範囲:狭
![Page 16: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/16.jpg)
17
2.プラン演算子にはどんなものがあるの?
1
0
1
0
0
8.1〜
・候補行をビットマップ化してアクセスする
・取り出す件数が中くらいの時に有効
・インデックスを使った結合も可能
Bit Map
インデックス
表
(3).Bit Map Scan検索範囲:中/特殊
![Page 17: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/17.jpg)
18
2.プラン演算子にはどんなものがあるの?
0
0
0
0
1
Visiblity Map
・9.2からの新機能
・ほぼインデックスのみを検索
・Visibility Mapを併用
インデックス
9.2〜(4).Index Only Scan検索範囲:特殊
![Page 18: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/18.jpg)
19
2.プラン演算子にはどんなものがあるの?
(1).Nested Loop Join
88
22
77
55
11
55
88
22
66
99
外部表
88
22
77
55
11
55
88
22
66
99
12578
25689
55
88
22
11
77
88
22
77
55
11
内部表
外部表 内部表
外部表 内部表
(2).Merge Join
(3).Hash Join
特徴:いかなる場合でも選択可能
特徴:ソートが完了すれば早い
特徴:ハッシュをオンメモリで作成できればば早い
3つの結合方法
![Page 19: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/19.jpg)
20
2.プラン演算子にはどんなものがあるの?
(1).Nested Loop Join
・最も基本的な結合方法
・ 外部表がの件数が少なく、内部表にインデックスがあることが望ましい。
・NとMが大きくなればなるほど コストが膨らむ
外部表outer table
内部表inner table
特徴:いかなる場合でも選択可能
![Page 20: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/20.jpg)
21
2.プラン演算子にはどんなものがあるの?
・ 結合前にソートすることで結合処理を削減
・ ソートが出来れば早い。(ソート済みのINDEXがある列との相性が良い)
88
22
77
55
11
55
88
22
66
99
1
2
5
7
8
2
5
6
8
9
外部表outer table
内部表inner table
(2).Merge Join
特徴:ソートが完了すれば早い
![Page 21: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/21.jpg)
22
2.プラン演算子にはどんなものがあるの?
・ 内部表をベースにメモリ上にハッシュ表を作り外部表はこれにアクセスし結合する
・ ハッシュ表を作ってしまえばその後の計算は早い。
外部表outer table
内部表inner tableハッシュ表
55
88
22
11
77
88
22
77
55
11
(3).Hash Join
特徴:ハッシュをオンメモリで作成できればば早い
![Page 22: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/22.jpg)
23
でも、演算子をどうやって使い分けてるの?
![Page 23: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/23.jpg)
24
アジェンダ
1.実行計画って何?
2.プラン演算子にはどんなものがあるの?
3.どうやって実行計画を作ってるの?
4.切り札!EXPLAIN
5.問題を解決してみよう!
6.まとめ
![Page 24: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/24.jpg)
25
3.どうやって実行計画を作ってるの?
実行計画はプランナーが複数作成
行数や対象データを元にコストを計算
コストが最も低いものが最適な実行計画
コスト計算には統計情報を利用
シーケンシャルI/Oで1ページを読み込むコストを1.0とした際の相対値
コストの単位
![Page 25: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/25.jpg)
26
3.どうやって実行計画を作ってるの?
統計情報は事前に収集した情報
表の行数
行サイズの平均
相関
値の分布(ヒストグラム) 等
ANALYZE 表名; で取得
autovacuumでも取得
![Page 26: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/26.jpg)
27
3.どうやって実行計画を作ってるの?
コストの見積もりは統計情報収集時のもの
統計情報が古いと最適化されない可能性も
精度の高いプランには最新の統計情報が必要
統計情報と実行計画
最新の統計情報 プランナー(だいたい)
Goodな実行計画
![Page 27: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/27.jpg)
28
アジェンダ
1.実行計画って何?
2.プラン演算子にはどんなものがあるの?
3.どうやって実行計画を作ってるの?
4.切り札!EXPLAIN
5.問題を解決してみよう!
6.まとめ
![Page 28: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/28.jpg)
29
4.切り札!EXPLAIN
プランナーが作成した"最良の"実行計画を確認するコマンド
コストや行数は統計情報を元にした推定
EXPLAINの出力に追加の情報を加えるオプション
実際にSQLを実行して情報を取得する
負荷のかかるSQLやDMLは注意
"実行時間"や"実際の行数"を取得する
EXPLAIN
EXPLAIN ANALYZE
![Page 29: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/29.jpg)
30
Hash Join (cost=1.09..2.42 rows=14 width=15) Hash Cond: (e.deptno = d.deptno) -> Seq Scan on emp e (cost=0.00..1.14 rows=14 width=11) -> Hash (cost=1.04..1.04 rows=4 width=14) -> Seq Scan on dept d (cost=0.00..1.04 rows=4 width=14)
キーワード 意味
cost 見積もりコスト
rows 見積もり行数
width 見積もり平均長
始動コスト..総コスト※基本的に総コストを見れば良い
EXPLAIN
![Page 30: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/30.jpg)
31
Hash Join (cost=1.09..2.42 rows=14 width=15) (actual time=11.835..11.868 rows=14 loops=1) Hash Cond: (e.deptno = d.deptno) -> Seq Scan on emp e (cost=0.00..1.14 rows=14 width=11) (actual time=11.714..11.723 rows=14 loops=1) -> Hash (cost=1.04..1.04 rows=4 width=14) (actual time=0.037..0.037 rows=4 loops=1) Buckets: 1024 Batches: 1 Memory Usage: 1kB -> Seq Scan on dept d (cost=0.00..1.04 rows=4 width=14) (actual time=0.018..0.021 rows=4 loops=1)
Total runtime: 11.950 ms
キーワード 意味
actual time 実際にかかった時間
rows 実際の行数
loops ステップの繰り返し数
EXPLAIN ANALYZE
1行の時間..最終行の時間※基本的に最終行の時間を見れば良い
![Page 31: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/31.jpg)
32
実行計画は各ステップをノードとするツリー構成
インデントが深いところから実行
子ノードの結果を親ノードが受ける
コスト・実行時間は子ノードからの累積
4.切り札!EXPLAIN
EXPLAIN ANALYZEを読む時に意識するところ
![Page 32: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/32.jpg)
33
実際の結果を見てみましょう
![Page 33: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/33.jpg)
34
EXPLAIN ANALYZESELECT e.empno,d.dname,s.grade FROM emp e JOIN dept d ON e.deptno=d.deptnoJOIN salgrade s on e.sal between s.losal and s.hisalwhere e.job='SALESMAN';
Column | Type ----------+----------------------------- empno | integer ename | character varying(10) job | character varying(9) mgr | integer hiredate | timestamp without time zone sal | integer comm | integer deptno | integer
EMP表
Column | Type --------+----------------------- deptno | integer dname | character varying(14) loc | character varying(13)
DEPT表
Column | Type --------+--------- grade | integer losal | integer hisal | integer
SALGRADE表
4.切り札!EXPLAIN
![Page 34: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/34.jpg)
35
Nested Loop(cost=0.00..7.85 rows=1 width=50)(actual time=0.031..0.089 rows=4 loops=1)
Join Filter: ((emp.sal >= s.losal) AND (emp.sal <= s.hisal)) Rows Removed by Join Filter: 16 -> Nested Loop
(cost=0.00..5.67 rows=1 width=54)(actual time=0.027..0.060 rows=4 loops=1) Join Filter: (emp.deptno = d.deptno) Rows Removed by Join Filter: 12 -> Seq Scan on emp
(cost=0.00..1.18 rows=1 width=12)(actual time=0.014..0.020 rows=4 loops=1)Filter: ((job)::text = 'SALESMAN'::text)Rows Removed by Filter: 10
-> Seq Scan on dept d(cost=0.00..1.05 rows=4 width=50)(actual time=0.001..0.003 rows=4 loops=4)
-> Seq Scan on salgrade s(cost=0.00..1.04 rows=5 width=8)(actual time=0.001..0.002 rows=5 loops=4)
①
②
③
④
⑤
4.切り札!EXPLAIN
出力結果
![Page 35: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/35.jpg)
36
実行結果をツリーにすると
Seq Scan on empcost=1.18
time=0.020
Seq Scan on dept dcost=1.05
time=0.003
x 4
Nested Loopcost=5.67
time=0.060
Seq Scan on salgrade scost=1.04
time= 0.002
x 4
Nested Loopcost=7.85
time=0.089
![Page 36: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/36.jpg)
37
インデントが深いところから
出力結果は子ノードからの累積
各ステップのcost/rows(見積,実際)/actual timeに注目
actual timeが跳ね上がっているステップ
rowsが見積もりと離れているステップ
4.切り札!EXPLAIN
実行結果を見るポイント
疑わしいポイント
![Page 37: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/37.jpg)
38
アジェンダ
1.実行計画って何?
2.プラン演算子にはどんなものがあるの?
3.どうやって実行計画を作ってるの?
4.切り札!EXPLAIN
5.問題を解決してみよう!
6.まとめ
![Page 38: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/38.jpg)
39
5.問題を解決してみよう!
Column | Type --------------+--------- exception_id | integer(primary key) complete | boolean
EXCEPTION表
Column | Type -------------------------+--------- exception_notice_map_id | integer exception_id | integer notice_id | integer
EXCEPTION_NOTICE_MAP表
complete列の分布
TRUE
FALSE
IndexIndex
● indexは両表のexception_id列のみ作成
● complete列はFalseのデータが1%未満
(1000行/10000000行)
![Page 39: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/39.jpg)
40
5.問題を解決してみよう!
EXPLAIN ANALYZESELECT exception_id,exception_notice_map_idFROM exceptionJOIN exception_notice_map USING (exception_id)WHERE complete is false and notice_id=3;
実行するSQL
![Page 40: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/40.jpg)
41
5.問題を解決してみよう!
Hash Join (cost=175782.31..405182.03 rows=53172 width=8) (actual time=1834.952..1844.389 rows=9 loops=1) Hash Cond: (exception.exception_id = exception_notice_map.exception_id) -> Seq Scan on exception (cost=0.00..144263.00 rows=5000000 width=4) (actual time=789.879..790.120 rows=1000 loops=1) Filter: (complete IS FALSE) Rows Removed by Filter: 9999000 -> Hash (cost=174037.01..174037.01 rows=106344 width=8) (actual time=1044.821..1044.821 rows=100202 loops=1) Buckets: 4096 Batches: 4 Memory Usage: 690kB -> Seq Scan on exception_notice_map (cost=0.00..174037.01 rows=106344 width=8) (actual time=0.081..991.670 rows=100202 loops=1) Filter: (notice_id = 3) Rows Removed by Filter: 9900798
Total runtime: 1844.486 ms
結果
![Page 41: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/41.jpg)
42
– 最上位のノードはrows=9 →9行戻すSQL
– 結合はHash Join– 処理時間は1844.486 ms(約2秒)
もっと早くならないかな?
状況整理
![Page 42: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/42.jpg)
43
5.問題を解決してみよう!
Hash Join (cost=175782.31..405182.03 rows=53172 width=8) (actual time=1834.952..1844.389 rows=9 loops=1) Hash Cond: (exception.exception_id = exception_notice_map.exception_id) -> Seq Scan on exception (cost=0.00..144263.00 rows=5000000 width=4) (actual time=789.879..790.120 rows=1000 loops=1) Filter: (complete IS FALSE) Rows Removed by Filter: 9999000 -> Hash (cost=174037.01..174037.01 rows=106344 width=8) (actual time=1044.821..1044.821 rows=100202 loops=1) Buckets: 4096 Batches: 4 Memory Usage: 690kB -> Seq Scan on exception_notice_map (cost=0.00..174037.01 rows=106344 width=8) (actual time=0.081..991.670 rows=100202 loops=1) Filter: (notice_id = 3) Rows Removed by Filter: 9900798
Total runtime: 1844.486 ms
OK!
OK!
ずれてる!?
見積との差をチェック
![Page 43: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/43.jpg)
44
5.問題を解決してみよう!
exception表でcompelete is Falseの行は
5000000行くらいかな結合相手も行が多いしたくさん
もどりそうだからHashJoinしよう
(cost=0.00..144263.00 rows=5000000 width=4)(actual time=789.879..790.120 rows=1000 loops=1)
1000行しかなかった…
プランナー プランナー
![Page 44: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/44.jpg)
45
そうだ、ANALYZE、しよう
![Page 45: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/45.jpg)
46
5.問題を解決してみよう!
Nested Loop (cost=0.43..152601.93 rows=11 width=8) (actual time=792.030..794.257 rows=9 loops=1) -> Seq Scan on exception (cost=0.00..144262.43 rows=1000 width=4) (actual time=790.677..790.885 rows=1000 loops=1) Filter: (complete IS FALSE) Rows Removed by Filter: 9999000 -> Index Scan using idx_nmap_exception_id on exception_notice_map (cost=0.43..8.33 rows=1 width=8) (actual time=0.003..0.003 rows=0 loops=1000) Index Cond: (exception_id = exception.exception_id) Filter: (notice_id = 3) Rows Removed by Filter: 1 Total runtime: 817.182 ms
ずれがなくなった!!
早くなった!1844.486 ms→817.182 ms
ANALYZE後
![Page 46: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/46.jpg)
47
ANALYZEで最新の統計を使いましょう!
![Page 47: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/47.jpg)
48
5.問題を解決してみよう!
Nested Loop (cost=0.43..152601.93 rows=11 width=8) (actual time=792.030..794.257 rows=9 loops=1) -> Seq Scan on exception (cost=0.00..144262.43 rows=1000 width=4) (actual time=790.677..790.885 rows=1000 loops=1) Filter: (complete IS FALSE) Rows Removed by Filter: 9999000 -> Index Scan using idx_nmap_exception_id on exception_notice_map (cost=0.43..8.33 rows=1 width=8) (actual time=0.003..0.003 rows=0 loops=1000) Index Cond: (exception_id = exception.exception_id) Filter: (notice_id = 3) Rows Removed by Filter: 1 Total runtime: 817.182 ms
1%未満の行にSeq Scanでアクセスしている
complete列の分布
TRUE
FALSE
再度結果を確認
![Page 48: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/48.jpg)
49
5.問題を解決してみよう!
Seq Scanを辞めたいならINDEXを張るのが定石
でもcomplete列はTrue/Falseの2種類しかない
カーディナリティが低いのでINDEX作成の負荷が心配
INDEXを使って欲しいのがFalseの時だけ
INDEXをつけるのは難しいかな・・・?
![Page 49: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/49.jpg)
50
そうだ部分インデックスがあるじゃないか!
CREATE INDEX idx_is_complete ON exception(complete) WHERE complete IS false;
![Page 50: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/50.jpg)
51
5.問題を解決してみよう!
条件を満たす行のみを保持するインデックス
頻出値にインデックスを付けずに済むため
インデックスのサイズが小さいインデックスの更新処理が発生しにくいので
更新パフォーマンスが有利
部分インデックって?
![Page 51: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/51.jpg)
52
5.問題を解決してみよう!
部分INDEX作ったら...
Nested Loop (cost=0.71..8347.79 rows=11 width=8) (actual time=0.266..5.241 rows=9 loops=1) -> Index Scan using idx_is_complete on exception (cost=0.28..8.29 rows=1000 width=4) (actual time=0.073..0.680 rows=1000 loops=1) Index Cond: (complete = false) -> Index Scan using idx_nmap_exception_id on exception_notice_map (cost=0.43..8.33 rows=1 width=8) (actual time=0.004..0.004 rows=0 loops=1000) Index Cond: (exception_id = exception.exception_id) Filter: (notice_id = 3) Rows Removed by Filter: 1
Total runtime: 5.286 ms
Index Scanが使われるようになった!
817.182 ms->5.286 ms160倍早い!
![Page 52: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/52.jpg)
53
PostgreSQLの色々な機能を活用しよう!・部分インデックス・Materialized View 等(細かい部分はマニュアルで)
![Page 53: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/53.jpg)
54
アジェンダ
1.実行計画って何?
2.プラン演算子にはどんなものがあるの?
3.どうやって実行計画を作ってるの?
4.切り札!Explain Plan
5.問題を解決してみよう!
6.まとめ
![Page 54: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/54.jpg)
55
6.まとめ
欲しいデータへの道筋
プラン演算子の組み合わせ
プランナーが統計情報で見積もり
実行計画って
![Page 55: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/55.jpg)
56
6.まとめ
インデントが深いところから
見積もりがずれているところから
時間が伸びているところから
EXPLAIN ANALYZEで問題を探すなら
![Page 56: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/56.jpg)
57
6.まとめ
見積もりがおかしかったら→ANALYZE してみましょう
アクセス行数が少ないのにSeq Scanだったら→インデックスを検討しましょう
PostgreSQLの機能を活用しましょう
最新のPostgreSQLを使いましょう
問題に対処するには
![Page 57: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/57.jpg)
58
それでも解決しない時はどうすればいいのだろう?
![Page 58: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/58.jpg)
59
6.まとめ
(VACUUMとANALYZEを実行している前提)
PostgreSQLのバージョンを書く
EXPLAIN ANALYZEの結果を必ず書く
クエリ、テーブル、データもできれば含める
[email protected] (英語)[email protected] (日本語)
メーリングリストに相談だ
![Page 59: PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)](https://reader030.vdocuments.net/reader030/viewer/2022032616/55a513681a28ab432d8b47fc/html5/thumbnails/59.jpg)
60
ご清聴ありがとうございました
参考資料(サイト)Explaining Explain ~ PostgreSQLの実行計画を読む ~ http://lets.postgresql.jp/documents/technical/query_tuning/explaining_explain_ja.pdf/view内部を知って業務に活かす PostgreSQL研究所第4回 http://www2b.biglobe.ne.jp/~caco/webdb-pdfs/vol29.pdf Robert Haas blog http://rhaas.blogspot.com/2011/10/index-only-scans-weve-got-em.html問合せ最適化インサイド http://www.slideshare.net/ItagakiTakahiro/ss-4656848象と戯れ http://postgresql.g.hatena.ne.jp/umitanuki/20110425/1303752697Explaining Explain 第2回 http://www.postgresql.jp/wg/shikumi/study20_materialsExplaining Explain 第3回 http://www.postgresql.jp/wg/shikumi/study21_materials
参考資料(書籍)PostgreSQL 全機能バイブル(技術評論社)PostgreSQL 設計・運用計画の鉄則(技術評論社)