ShikumiBunkakai_2011_10_29

Similar documents
PostgreSQL SQL チューニング入門 ~ Explaining Explain より ~ 2012 年 11 月 30 日 株式会社アシスト 田中健一朗

第 5 章 結合 結合のパフォーマンスに影響を与える結合の種類と 表の結合順序について内部動作を交えて 説明します 1. 結合処理のチューニング概要 2. 結合の種類 3. 結合順序 4. 結合処理のチューニングポイント 5. 結合関連のヒント

はじめに コースの概要と目的 Oracle をより効率的に使用するための SQL のチューニング方法について説明します また 索引の有無 SQL の 記述方法がパフォーマンスにどのように影響するのかを実習を通して理解します 受講対象者 アプリケーション開発者 / データベース管理者の方 前提条件 S

プレポスト【問題】

Oracle9i

第 2 章 問合せの基本操作 この章では データベースから情報を検索する際に使用する SELECT コマンド および SELECT コマンドと 同時に使用する句について説明します 1. 問合せとは 2. 基本的な問合せ 3. 列の別名 4. 重複行を一意にする 5. 検索行の絞込み 6. 文字パター

PostgreSQL 9.3パーティションの効果検証

第 2 章 PL/SQL の基本記述 この章では PL/SQL プログラムの基本的な記述方法について説明します 1. 宣言部 2. 実行部 3. 例外処理部

PostgreSQL 10 技術解説 SRA OSS, Inc. 日本支社 マーケティング部 PostgreSQL 技術グループ 高塚遙 PostgreSQL 最新動向紹介セミナー

PostgreSQL10 を導入! 大規模データ分析事例からみる DWH としての PostgreSQL 活用のポイント 2017/12/5 株式会社 NTT データ 2017 NTT DATA

PA4

Microsoft PowerPoint - 講義補助資料2017.pptx

このドキュメントに記載されている情報 (URL 等のインターネット Web サイトに関する情報を含む ) は 将来予告なしに変更することがあります このドキュメントに記載された内容は情報提供のみを目的としており 明示または黙示に関わらず これらの情報についてマイクロソフトはいかなる責任も負わないもの

Microsoft PowerPoint pptx

タイトルを1~2行で入力 (長文の場合はフォントサイズを縮小)

第 1 章 条件分岐 この章では 条件に応じて処理を分岐する方法について説明します 1. CASE 式で複雑な条件分岐を実現 2. 関数を使用した条件分岐 3. MERGE 文による条件に応じた DML の実行

~~~~~~~~~~~~~~~~~~ wait Call CPU time 1, latch: library cache 7, latch: library cache lock 4, job scheduler co

Oracle9i Reportsのチューニング

今さら聞けない!? Oracle入門 ~後編~

PowerPoint プレゼンテーション

領域サイズの見積方法

untitled

データセンターの効率的な資源活用のためのデータ収集・照会システムの設計

pg_monz 監視アイテム一覧 :Template App PostgreSQL Template App PostgreSQL アプリケーション LLD アイテムトリガー監視タイプ更新間隔ヒストリトレンドデフォルト説明ステータス pg.get pgsql.get.pg.bgwriter Zabb

スライド 1

intra-mart Accel Platform — TableMaintenance ユーザ操作ガイド   第7版   None

次期バージョン PostgreSQL 10 の 新機能とその後の方向性 SRA OSS, Inc. 日本支社 マーケティング部 PostgreSQL 技術グループ 長田 悠吾 db tech showcase OSS

Slide 1

ICDE’15 勉強会 R24-4: R27-3 (R24:Query Processing 3, R27 Indexing)

自己紹介 長田悠吾 (Yugo Nagata) SRA OSS, Inc. 日本支社 PostgreSQL 技術支援 コンサルティング PostgreSQL インターナル講座講師 研究開発 Copyright 2018 SRA OSS, Inc. Japan All right

Microsoft PowerPoint - db03-5.ppt

eラーニング資料 e ラーニングの制作目標 データベース編 41 ページデータベースの基本となる概要を以下に示す この内容のコースで eラーニングコンテンツを作成予定 データベース管理 コンピュータで行われる基本的なデータに対する処理は 次の 4 種類です 新しいデータを追加する 既存のデータを探索

intra-mart Accel Platform — TableMaintenance ユーザ操作ガイド   第8版  

TALON Tips < カレンダー ( 月別 ) の画面を表示する > 株式会社 HOIPOI 第 1.1 版 p. 1

Microsoft PowerPoint - KeySQL50_10g_vlo2.ppt

復習 (SQL 文 ) 3/6 復習 (SQL 文 ) 4/6 表の作成 CREATE TABLE...; 表の削除 DROP TABLE テーブル名 ; 表内のデータが全て消えてしまう. 表内のデータを得る SELECT 列名 FROM 表名...; 表にデータを挿入する. INSERT INTO

リレーショナルデータベース入門 SRA OSS, Inc. 日本支社 Copyright 2008 SRA OSS, Inc. Japan All rights reserved. 1

目次 1 集計関数 / 分析関数とは 2 集計関数 / 分析関数のパフォーマンス効果 3 ケーススタディグループ小計やクロス集計を計算するランキングを表示する前月比較を表示する累計を計算する移動平均を計算する構成比を計算する Oracle8i SQL Oracle8i Oracle Oracle C

メール全文検索アプリケーション Sylph-Searcher のご紹介 SRA OSS, Inc. 日本支社技術部チーフエンジニア Sylpheed 開発者 山本博之 Copyright 2007 SRA OSS, Inc. Japan All right

結合演算 ( 復習 ) データベース論 (9) R 社員番号 氏名麻生太郎安部晋三与謝野馨森喜朗 部門経理課営業課総務課営業課 S 部門経理課営業課総務課 電話 問合せ言語と SQL(2) R S 社員番号

Oracle活用実践演習コース

Dolteng Scaffoldに対する機能追加とマスタ-ディテールScaffoldの紹介

PowerPoint Presentation

,, create table drop table alter table

Microsoft Word - Android_SQLite講座_画面800×1280

Chapter Two

tkk0408nari

_02_3.ppt

この時お使いの端末の.ssh ディレクトリ配下にある known_hosts ファイルから fx.cc.nagoya-u.ac.jp に関する行を削除して再度ログインを行って下さい

: ORDER BY

Slide 1

早分かりS2Dao

スライド 1

PowerPoint -O80_REP.PDF

1,.,,,., RDBM, SQL. OSS,, SQL,,.

CodeGear Developer Camp

PowerPoint プレゼンテーション

Microsoft Word - nvsi_050110jp_netvault_vtl_on_dothill_sannetII.doc

マニュアル訂正連絡票

Exam : J Title : Querying Microsoft SQL Server 2012 Version : DEMO 1 / 10

BC4J...4 BC4J Association JSP BC4J JSP OC4J

第 7 章 ユーザー データ用表領域の管理 この章では 表や索引を格納するユーザー データ用表領域の作成や 作成後のメンテナンスに ついて解説します 1. ユーザー データ用表領域の管理概要 2. ユーザー データ用表領域作成時の考慮事項 3. ユーザー データ用表領域の作成 4. ユーザー データ

Oracleの領域管理~トラブル防止のテクニック~

はじめに コースの概要と目的条件分岐の方法や複雑な集計の手法など SQL のコーディングの幅を広げるためのテクニックについて説明します また パフォーマンスを考慮した記述方法や正しい結果を取得するための記述方法などについても あわせて説明します 本コースでは 実践的な SQL の記述手法を広く浅く紹

Chapter Two

スライド 1

PowerPoint Presentation

改訂履歴 日付バージョン記載ページ改訂内容 V2.1 - 初版を発行しました V3.1 P5 ドキュメントラベルが新規追加された事を追記 P7 P8 新しくなったラベルのツリー表示説明を追記 新しくなったラベルの作成 削除操作を追記 P9 ラベルのグループ

アジェンダ ORACLE MASTER Oracle Database 11g 概要 11g SQL 基礎 Ⅰ 試験紹介 ポイント解説 Copyright 2011 Oracle. All rights reserved. 2

10th Developer Camp - B5

橡実践Oracle Objects for OLE

PowerPoint プレゼンテーション

今さら聞けない!? Oracle入門 ~前編~

内容 Visual Studio サーバーエクスプローラで学ぶ SQL とデータベース操作... 1 サーバーエクスプローラ... 4 データ接続... 4 データベース操作のサブメニューコンテキスト... 5 データベースのプロパティ... 6 SQL Server... 6 Microsoft

スライド 1

PowerPoint Presentation

…l…b…g…‘†[…N…v…“…O…›…~…fi…OfiÁŸ_

スライド 1

1 SQL Server SQL Oracle SQL SQL* Plus PL/SQL 2 SQL Server SQL Server SQL Oracle SQL SQL*Plus SQL Server GUI 1-1 osql 1-1 Transact- SQL SELECTFROM 058

Ruby 2.3 のてざわり新機能と使いどころ Kunihiko Ito ESM 富山合同勉強会

PostgreSQL 9.4 評価検証報告 SRA OSS, Inc. 日本支社高塚遙 :55 ~ 16:30 PostgreSQL 9.4 最新情報セミナー Copyright 2014 SRA OSS, Inc. Japan All rights reserved. 1

タイトル1

PowerPoint Template

Microsoft PowerPoint - 3-Forms-Others.ppt

3 - 正しい SQL ( 方言を排除した SQL 文の記述方法 )

Microsoft Word - sample_adv-programming.docx

memo

052-XML04/fiÁ1-part3-’ÓŠ¹

Oracle Database Connect 2017 JPOUG

PostgreSQL 11 新機能解説 オープンソースカンファレンス 2018 Tokyo/Fall SRA OSS, Inc. 日本支社近藤雄太 Copyright 2018 SRA OSS, Inc. Japan All rights reserved. 1

Slide 1

3. XML, DB, DB (AP). DB, DB, AP. RDB., XMLDB, XML,.,,.,, (XML / ), XML,,., AP. AP AP AP 検索キー //A=1 //A=2 //A=3 返却 XML 全体 XML 全体 XML 全体 XMLDB <root> <A

機械学習 ツール入門

データベースS

Wiki Wiki Wiki...

Microsoft PowerPoint - Lite10g_SyncArchitecture.ppt

1 ex01.sql ex01.sql ; user_id from (select user_id ;) user_id * select select (3+4)*7, SIN(PI()/2) ; (1) select < > from < > ; :, * user_id user_name

Microsoft Word - nvsi_050090jp_oracle10g_vlm.doc

まう不具合を解消 Windows10 バージョン1803で ディスプレイのサイズを125% 150% にすると STORM VのTOP 画面がズレてしまう不具合を解消しました 6. 動画 + 音声 コンテンツをインポートすると再編集出来なくなる不具合を解消 スライド+ 動画 + 音声 コンテンツをイ

Windows Powershell 入門

Transcription:

Explaining Explain 第3回 第21回しくみ分科会+アプリケーション分科会勉強会 2011年10月29日 PostgreSQLのしくみ分科会 田中 健一朗 1

本日のメニュー ExplainingExplainの第3回目 味付け 9.1対応 項目ごとにTips 2

本日の勉強会の目的 Explain Analyzeを使った 問題箇所の見つけ方と 対処方法を理解してもらう

アジェンダ 1.第1回 第2回の復習など 2.実際のデバッグ例1) 3.実際のデバッグ例2) 4.実際のデバッグ例3) 5.実際のデバッグ例4) 6.気をつけておくこと 7.まとめ 4

本日の主役は プランナー です 5

第1回 第2回の復習 プランナ/オプティマイザの役割は最適な実行計画を作ることです マニュアルより抜粋 http://www.postgresql.jp/document/9.0/html/planner-optimizer.html 6

第1回 第2回の復習 (一般的に) RDBMSは正規化して使うもの 7

第1回 第2回の復習 ざっくり正規化しても表は7つ 顧客マスタ 在住区分 受注ヘッダ 支払い方法 受注明細 配送方法 商品マスタ 8

第1回 第2回の復習 顧客マスタ 受注ヘッダ 受注明細 商品マスタ 在住区分 支払い方法 配送方法 ①どのようなアクセス方法が適切か ②どのような結合方法が適切か ③統計情報を元に実行計画を作成する 事がプランナの役目 ④どのような選択が行なわれたかを EXPLAINコマンドで確認できる 9

第1回 第2回の復習 顧客マスタ 受注ヘッダ 受注明細 商品マスタ 在住区分 支払い方法 配送方法 ①どのようなアクセス方法が適切か ②どのような結合方法が適切か ③統計情報を元に実行計画を作成する 事がプランナの役目 ④どのような選択が行なわれたかを EXPLAINコマンドで確認できる 10

Explaining EXPLAIN 第2回 p4 p6 and p11 第1回 第2回の復習 代表的なアクセスの方法 seq scan index scan 11

第1回 第2回の復習 補足seq scan と index scan のコストの違い index scan 各スキャンの1ブロックのアクセスに かかるコストのデフォルト値 seq scan COST = 1.0 index scan COST = 4.0 12

第1回 第2回の復習 顧客マスタ 受注ヘッダ 受注明細 商品マスタ 在住区分 支払い方法 配送方法 ①どのようなアクセス方法が適切か ②どのような結合方法が適切か ③統計情報を元に実行計画を作成する 事がプランナの役目 ④どのような選択が行なわれたかを EXPLAINコマンドで確認できる 13

第1回 第2回の復習 Explaining EXPLAIN 第2回 p16 表の結合方法 Nested Loop Join 14

第1回 第2回の復習 Explaining EXPLAIN 第2回 p18 表の結合方法 Sort Merge Join 15

第1回 第2回の復習 Explaining EXPLAIN 第2回 p20 表の結合方法 Hash Join 16

第1回 第2回の復習 顧客マスタ 受注ヘッダ 受注明細 商品マスタ 在住区分 支払い方法 配送方法 ①どのようなアクセス方法が適切か ②どのような結合方法が適切か ③統計情報を元に実行計画を作成する 事がプランナの役目 ④どのような選択が行なわれたかを EXPLAINコマンドで確認できる 17

第1回 第2回の復習 表のサイズは どのくらいだろう 統計情報とは 1つ1つの表の 行数 行サイズ平均 相関 ヒストグラム 顧客マスタ 在住区分 受注マスタ 支払い方法 受注明細 などを見積もったもの ANALYZE 表名; で取得 値の種類は 何種類 配送方法 行の平均長さは 商品明細 ヒストグラムを 見てみよう 18 頻出値は

第1回 第2回の復習 顧客マスタ 受注ヘッダ 受注明細 商品マスタ 在住区分 支払い方法 配送方法 ①どのようなアクセス方法が適切か ②どのような結合方法が適切か ③統計情報を元に実行計画を作成する 事がプランナの役目 ④どのような選択が行なわれたかを EXPLAINコマンドで確認できる 19

Explain Analyze見方 emp empno ename job : deptno [int] [CHAR(10)] [CHAR(9)] dept deptno dname loc [int] [int] [VARCHAR(10)] [VARCHAR(10)] SELECT d.dname,e.ename FROM emp e JOIN dept d USING (deptno); 20

Explain Analyze見方 EXPLAINコマンド Original Explain Plan の例 # EXPLAIN ANALYZE SELECT d.dname,e.ename FROM emp e JOIN dept d USING (deptno); QUERY PLAN --------------------------------------------------------------Hash Join (cost=1.23..4101.23 rows=100000 width=66) (actual time=0.045..161.248 rows=90000 loops=1) Hash Cond: (e.deptno = d.deptno) -> Seq Scan on emp e (cost=0.00..2725.00 rows=100000 width=41) (actual time=0.007..49.537 rows=100000 loops=1) -> Hash (cost=1.10..1.10 rows=10 width=37) ANALYZEオプションを付けることで (actual time=0.025..0.025 rows=10 loops=1) 実際にSQLが実行され actual timeの Buckets: 1024 Batches: 1 Memory Usage: 1kB -> Seq Scan on dept 情報が出力される d (cost=0.00..1.10 rows=10 width=37) (actual time=0.003..0.013 rows=10 loops=1) システムへの影響を考慮すること Total runtime: 196.524 ms (7 rows) 21

Explain Analyze見方 アクセス方法 Original Explain Plan の例 ①どのようなアクセス方法が適切か ②どのような結合方法が適切か # EXPLAIN ANALYZE SELECT d.dname,e.ename FROM emp e ③統計情報を元に実行計画を作成する JOIN dept d USING (deptno); 事がプランナの役目 QUERY PLAN ④どのような選択が行なわれたかを --------------------------------------------------------------EXPLAINコマンドで確認できる Hash Join (cost=1.23..4101.23 rows=100000 width=66) (actual time=0.045..161.248 rows=90000 loops=1) Hash Cond: (e.deptno = d.deptno) -> Seq Scan on emp e (cost=0.00..2725.00 rows=100000 width=41) (actual time=0.007..49.537 rows=100000 loops=1) Index Scan using emp_pkey on emp e -> Hash (cost=1.10..1.10 rows=10 width=37) (actual time=0.025..0.025 rows=10 loops=1) Buckets: 1024 Batches: 1 Memory Usage: 1kB -> Seq Scan on dept d (cost=0.00..1.10 rows=10 width=37) (actual time=0.003..0.013 rows=10 loops=1) Total runtime: 196.524 ms (7 rows) 22

Explain Analyze見方 結合方法 Original Explain Plan の例 ①どのようなアクセス方法が適切か ②どのような結合方法が適切か # EXPLAIN ANALYZE SELECT d.dname,e.ename FROM emp e ③統計情報を元に実行計画を作成する JOIN dept d USING (deptno); 事がプランナの役目 QUERY PLAN ④どのような選択が行なわれたかを --------------------------------------------------------------EXPLAINコマンドで確認できる Hash Join (cost=1.23..4101.23 rows=100000 width=66) (actual time=0.045..161.248 rows=90000 loops=1) Hash Cond: (e.deptno = d.deptno) -> Seq Scan on emp e (cost=0.00..2725.00 rows=100000 width=41) (actual time=0.007..49.537 rows=100000 loops=1) -> Hash (cost=1.10..1.10 rows=10 width=37) (actual time=0.025..0.025 rows=10 loops=1) Buckets: 1024 Batches: 1 Memory Usage: 1kB -> Seq Scan on dept d (cost=0.00..1.10 rows=10 width=37) (actual time=0.003..0.013 rows=10 loops=1) Total runtime: 196.524 ms (7 rows) 23

Explain Analyze見方 (統計情報) Original Explain Plan の例 ①どのようなアクセス方法が適切か ②どのような結合方法が適切か # EXPLAIN ANALYZE SELECT d.dname,e.ename FROM emp e ③統計情報を元に実行計画を作成する JOIN dept d USING (deptno); 事がプランナの役目 QUERY PLAN プランナが推定したコストと行数 ④どのような選択が行なわれたかを --------------------------------------------------------------EXPLAINコマンドで確認できる Hash Join (cost=1.23..4101.23 rows=100000 width=66) (actual time=0.045..161.248 rows=90000 loops=1) Hash Cond: (e.deptno = d.deptno) -> Seq Scan on emp e (cost=0.00..2725.00 rows=100000 width=41) (actual time=0.007..49.537 rows=100000 loops=1) -> Hash (cost=1.10..1.10 rows=10 width=37) (actual time=0.025..0.025 rows=10 loops=1) 実際にSQLを実行した時間と行数 Buckets: 1024 Batches: 1 Memory Usage: 1kB -> Seq Scan on dept d (cost=0.00..1.10 rows=10 width=37) (actual time=0.003..0.013 rows=10 loops=1) Total runtime: 196.524 ms (7 rows) 24

Explain Analyze見方 (統計情報) 見積もられた平均列長 (cost=0.00..2725.00 rows=100000 width=41) 取り出される行数の見積もり 表アクセスにかかるコストの見積もり ディスクからのデータ読み込み メモリ上のスキャン CPUを使用する処理 繰り返し実行された回数 (actual time=0.007..49.537 rows=100000 loops=1) 実際に取り出された行数 実際に表アクセスにかかった時間(ミリ秒) 25

Explain Analyze見方 (統計情報見方のコツ) Original Explain Plan の例 統計情報は 誤差 が最も少なくなるであろう # EXPLAIN ANALYZE 下(インデントが下のもの)から見ていくと良い SELECT d.dname,e.ename FROM emp e JOIN dept d USING (deptno); また より コストが大きいものから改善すると QUERY PLAN 効率が良い --------------------------------------------------------------Hash Join (cost=1.23..4101.23 rows=100000 width=66) (actual time=0.045..161.248 rows=90000 loops=1) Hash Cond: (e.deptno = d.deptno) -> Seq Scan on emp e (cost=0.00..2725.00 rows=100000 width=41) (actual time=0.007..49.537 rows=100000 loops=1) -> Hash (cost=1.10..1.10 rows=10 width=37) (actual time=0.025..0.025 rows=10 loops=1) Buckets: 1024 Batches: 1 Memory Usage: 1kB -> Seq Scan on dept d (cost=0.00..1.10 rows=10 width=37) (actual time=0.003..0.013 rows=10 loops=1) Total runtime: 196.524 ms (7 rows) 26

Explain Analyze見方 EXPLAINコマンド EXPLAIN 9.0 で追加されたオプション http://www.postgresql.jp/document/9.1/html/release-9-0.html EXPLAIN ANALYZE時に問い合わせバッファの活動を報告する 新しいBUFFERSオプションを追加しました (Itagaki Takahiro) Seq Scan on emp (cost=0.00..15.10 rows=510 width=128) (actual time=0.008..0.018 rows=14loops=1) Buffers: shared hit=1 EXPLAINの出力にハッシュ使用状況に関する情報を 追加しました (Robert Haas) -> Hash (cost=15.10..15.10 rows=510 width=52) (actual time=0.036..0.036 rows=14 loops=1) Buckets: 1024 Batches: 1 Memory Usage: 1kB 27

第1回 第2回の復習(7) まとめ ①どのようなアクセス方法が適切か ②どのような結合方法が適切か ③統計情報を元に計算を行なうのが プランナの役目 ④統計情報を元に実行計画を作成する 事がプランナの役目 28

第1回 第2回の復習(7) まとめ ①どのようなアクセス方法が適切か ②どのような結合方法が適切か ③統計情報を元に計算を行なうのが プランナの役目 ④統計情報を元に実行計画を作成する 事がプランナの役目 EXPLAINの出力のどこに着目すると良いか というのが今日のテーマです 29

実際のデバッグ 2.実際のデバッグ例1) 3.実際のデバッグ例2) 4.実際のデバッグ例3) 5.実際のデバッグ例4) 30

2.実際のデバッグ(例1) 表の構成 Analyzeをしよう プライマリキー exception_pkey exception_notice_map exception exception_id [int] complete [boolean] exception_notice_map_id exception_id notice_id [int] [int] [int] インデックス exception_id 部分インデックス complete=false 全体の0.25% active_exceptions SELECT exception_id FROM exception JOIN exception_notice_map USING (exception_id) WHERE complete IS FALSE AND notice_id = 3; 31

Tips1 部分インデックスとは 名前のとおり 部分的に張られたインデックス CREATE INDEX時にWHERE句を指定します SQL実行例 create index active_exceptions on exception(complete) where complete is false; 赤いデータのみにインデックスを作る 部分インデックスが有効なシチュエーション 値に偏りが有る場合 -逐次インデックスの挿入/更新がされない -インデックスサイズを小さくできる データ分布のイメージ 32

2.実際のデバッグ(例1) 表の構成 Analyzeをしよう プライマリキー exception_pkey exception_notice_map exception exception_id [int] complete [boolean] exception_notice_map_id exception_id notice_id [int] [int] [int] インデックス exception_id 部分インデックス complete=false 全体の0.25% active_exceptions SELECT exception_id FROM exception JOIN exception_notice_map USING (exception_id) WHERE complete IS FALSE AND notice_id = 3; 33

2.実際のデバッグ(例1) Analyzeをしよう Original =# EXPLAIN ANALYZE SELECT exception_id FROM exception -# JOIN exception_notice_map USING (exception_id) -# WHERE complete IS FALSE AND notice_id = 3; QUERY PLAN -----------------------------------------------------------------------Nested Loop (cost=0.00..2113.88 rows=217 width=4) (actual time=0.063..15.436 rows=124 loops=1) -> Seq Scan on exception_notice_map (cost=0.00..767.20 rows=217 width=4) (actual time=0.028..13.764 rows=248 loops=1) Filter: (notice_id = 3) -> Index Scan using exception_pkey on exception (cost=0.00..6.19 rows=1 width=4) (actual time=0.004..0.004 rows=0 loops=248) Index Cond: (exception.exception_id = exception_notice_map.exception_id) Filter: (exception.complete IS FALSE) Total runtime: 15.572 ms (7 rows) exception表に"where complete IS False"という 条件の部分インデックスがあり 条件を満たす行は 251行だけなのに使ってくれない 34

2.実際のデバッグ(例1) Analyzeをしよう Original =# ANALYZE exception; EXPLAIN ANALYZE SELECT exception_id FROM exception ANALYZE =# EXPLAIN ANALYZE SELECT exception_id FROM exception -# JOIN exception_notice_map USING (exception_id) -# WHERE complete IS FALSE AND notice_id = 3; QUERY PLAN ---------------------------------------------------------------------------Hash Join (cost=17.52..814.43 rows=263 width=4) (actual time=0.556..12.244 rows=124 loops=1) Hash Cond: (exception_notice_map.exception_id = exception.exception_id) -> Seq Scan on exception_notice_map (cost=0.00..793.29 rows=264 width=4) (actual time=0.013..11.390 rows=248 loops=1) Filter: (notice_id = 3) -> Hash (cost=14.23..14.23 rows=263 width=4) (actual time=0.505..0.505 rows=251 loops=1) Buckets: 1024 Batches: 1 Memory Usage: 6kB -> Index Scan using active_exceptions on exception (cost=0.00..14.23 rows=263 width=4) (actual time=0.021..0.280 rows=251 loops=1) 部分インデックスを使ってくれた Index Cond: (complete = false) Total runtime: 12.372 ms (9 rows) 35

例1)のまとめ ANALYZEをしよう 36

3.実際のデバッグ(例2) とにかくAnalyzeをしよう プライマリキー exception_pkey exception_notice_map exception exception_id [int] complete [boolean] 部分インデックス complete=false active_exceptions exception_notice_map_id [int] exception_id [int] notice_id [int] インデックス exception_id 表の構成/SQLは同じデータの分布が違う SELECT exception_id FROM exception JOIN exception_notice_map USING (exception_id) WHERE complete IS FALSE AND notice_id = 3; 37

3.実際のデバッグ(例2) とにかくAnalyzeをしよう Explaining EXPLAIN p36 38

3.実際のデバッグ(例2) とにかくAnalyzeをしよう Explaining EXPLAIN p37 39

3.実際のデバッグ(例2) とにかくAnalyzeをしよう Explaining EXPLAIN p38 Analyze前は 10898.57ms 40

3.実際のデバッグ(例2) とにかくAnalyzeをしよう 以前のバージョン( 7.4)ではキリがいい数字を疑う理由 統計情報が取得されていない場合は デフォルトで1000行のデータが入って いると仮定されている # create table a(); CREATE TABLE # explain analyze select * from a; QUERY PLAN ---------------------------------------------Seq Scan on a (cost=0.00..20.00 rows=1000 width=0) (actual time=0.002..0.002 rows=0 loops=1) Total runtime: 0.064 ms 41

3.実際のデバッグ(例2) とにかくAnalyzeをしよう キリがいい数字に関しては改善が進んでいます PostgreSQL8.0より 列の長さを元に計算され 固定値の1000ではなくなりました backend/optimizer/util/plancat.c" 239 240 241 242 243 244 327 328 475 /* * HACK: if the relation has never yet been vacuumed, use a * minimum estimate of 10 pages. This emulates a desirable * aspect of pre-8.0 behavior, which is that we wouldn't assume * a newly created relation is really small, which saves us from * making really bad plans during initial data loading. /* note: integer division is intentional here */ density = (BLCKSZ - sizeof(pageheaderdata)) / tuple_width; *tuples = rint(density * (double) curpages); 42

例2)のまとめ とにかく ANALYZEしよう 新しいバージョンを使おう 43

4.実際のデバッグ(例3) Seq Scanが遅い images host host_id host_name [int] [char(50)] images_id site_id host_id image_name [INT] [INT] [int] [text] site site_id name [int] [char(50)] SELECT s.site_id,s.name,i.image_name FROM images i JOIN host h USING (host_id) JOIN site s USING (site_id) WHERE images_id > 2212; 44

Tips2 追記型(MVCC)について SELECT * FROM foo; foo DEL id=1 v='aaa' update foo set v='aaa' where id=1; id=2 v='bbb' id=3 v='ccc' id=1 v='aaa' DEL id=1 v='aaa' 追記型のアーキテクチャ 45 update foo set v='aaa' where id=1;

Tips2 追記型(MVCC)について SELECT * FROM foo; VACUUM foo empty DEL id=1 v='aaa' update foo set v='aaa' where id=1; id=2 v='bbb' id=3 v='ccc' id=1 v='aaa' id=1 v='aaa' empty DEL update foo set v='aaa' where id=1; フルスキャンを行なう場合は削除(書き込み可能)フラグが 付いたデータも検索しなければならない 46

4.実際のデバッグ(例3) Seq Scanが遅い Original =#explain analyze SELECT s.site_id,s.name,i.image_name FROM images i -# JOIN host h USING (host_id) JOIN site s USING (site_id) -# WHERE images_id > 2212; Hash Join (cost=130.87..10680.75 rows=788 width=70) (actual time=1196.263..1290.620 rows=788 loops=1) host表のseq Scan時間が Hash Cond: (h.host_id = i.host_id) 他の表と比べて長すぎる(20倍) -> Seq Scan on host h (cost=0.00..10167.00 rows=100000 width=4) (actual time=1188.441..1236.629 rows=100000 loops=1) -> Hash (cost=121.02..121.02 rows=788 width=74) (actual time=5.481..5.481 rows=788 loops=1) Buckets: 1024 Batches: 1 Memory Usage: 75kB -> Hash Join (cost=46.89..121.02 rows=788 width=74) (actual time=3.589..4.928 rows=788 loops=1) Hash Cond: (s.site_id = i.site_id) -> Seq Scan on site s (cost=0.00..55.00 rows=3000 width=37) (actual time=0.025..1.685 rows=3000 loops=1) -> Hash (cost=37.04..37.04 rows=788 width=41) (actual time=1.254..1.254 rows=788 loops=1) Buckets: 1024 Batches: 1 Memory Usage: 50kB -> Index Scan using images_pkey on images i (cost=0.00..37.04 rows=788 width=41) (actual time=0.065..0.758 rows=788 loops=1) Index Cond: (images_id > 2212) Total runtime: 1290.995 ms host host_id host_name [int] [char(20)] site site_id name 47 [int] [char(20)]

4.実際のデバッグ(例3) Seq Scanが遅い Original =#explain analyze SELECT s.site_id,s.name,i.image_name FROM images i -# JOIN host h USING (host_id) JOIN site s USING (site_id) -# WHERE images_id > 2212; host host_id host_name [int] [char(20)] Hash Join (cost=130.87..10680.75 rows=788 width=70) (actual time=1196.263..1290.620 rows=788 loops=1) Hash Cond: (h.host_id = i.host_id) -> Seq Scan on host h (cost=0.00..10167.00 rows=100000 width=4) (actual time=1188.441..1236.629 rows=100000 loops=1) -> Hash (cost=121.02..121.02 rows=788 width=74) (actual time=5.481..5.481 rows=788 loops=1) デフォルトでは1ブロック8K Buckets: 1024 Batches: 1 Memory Usage: 75kB -> Hash Join (cost=46.89..121.02 rows=788 width=74) 10万行に対し1万ブロックは (actual time=3.589..4.928 rows=788 loops=1) 格納効率が悪すぎないか Hash Cond: (s.site_id = i.site_id) -> Seq Scan on site s (cost=0.00..55.00 rows=3000 width=37) (actual time=0.025..1.685 rows=3000 loops=1) -> Hash (cost=37.04..37.04 rows=788 width=41) (actual time=1.254..1.254 rows=788 loops=1) Buckets: 1024 Batches: 1 Memory Usage: 50kB -> Index Scan using images_pkey on images i (cost=0.00..37.04 rows=788 width=41) (actual time=0.065..0.758 rows=788 loops=1) Index Cond: (images_id > 2212) Total runtime: 1290.995 ms 不要ブロックが多数あるのではないか 48

4.実際のデバッグ(例3) Seq Scanが遅い Original =#vacuum full host; =#explain analyze SELECT s.site_id,s.name,i.image_name FROM images i -# JOIN host h USING (host_id) JOIN site s USING (site_id) -# WHERE images_id > 2212; Hash Join (cost=130.87..2360.32 rows=788 width=70) (actual time=11.701..112.387 rows=788 loops=1) Hash Cond: (h.host_id = i.host_id) -> Seq Scan on host h (cost=0.00..1843.14 rows=100914 width=4) (actual time=0.025..51.975 rows=100000 loops=1) -> Hash (cost=121.02..121.02 rows=788 width=74) (actual time=8.148..8.148 rows=788 loops=1) 1行あたりにかかる時間が Buckets: 1024 Batches: 1 Memory Usage: 75kB -> Hash Join (cost=46.89..121.02 rows=788 width=74) 大幅に改善 (actual time=5.123..7.252 rows=788 loops=1) Hash Cond: (s.site_id = i.site_id) -> Seq Scan on site s (cost=0.00..55.00 rows=3000 width=37) (actual time=0.005..2.274 rows=3000 loops=1) -> Hash (cost=37.04..37.04 rows=788 width=41) (actual time=1.701..1.701 rows=788 loops=1) Buckets: 1024 Batches: 1 Memory Usage: 50kB -> Index Scan using images_pkey on images i (cost=0.00..37.04 rows=788 width=41) (actual time=0.013..0.918 rows=788 loops=1) Index Cond: (images_id > 2212) Total runtime: 112.932 ms 対処前 (actual time=1188.441..1236.629 rows=100000 loops=1) 対処後 (actual time=0.025..51.975 rows=100000 loops=1) VACUUM前 0.01236629 VACUUM後 0.00051957 49

例3)のまとめ VACUUM FULLがいらない設計 運用を EXPLAINを見れば メンテナンスの必要性も分かる 50

Tips3 9.0よりVACUUM FULLの挙動が変わった Foo これまでのVACUUM FULLは空きを 見つけて 見つけた空きに入るタプルを 入れる作業 空 id=2 v='bbb' id=3 v='ccc' ① ①末尾にある行を空いて空きに移動する ②ファイルを縮小する ② 空 id=1 v='aaa' 51

Tips3 9.0よりVACUUM FULLの挙動が変わった VACUUM FULLが CLUSTER コマンドの ような再作成に近い挙動に仕様変更された ② 空 Foo id=2 v='bbb' Foo ① id=2 v='bbb' id=3 v='ccc' id=3 v='ccc' id=1 v='aaa' 空 id=1 v='aaa' ①削除されていないデータだけで 表を再構成 ②元の表を削除する 52

Tips3 9.0よりVACUUM FULLの挙動が変わった 使えなくなったテクニック VACUUM FULLを途中でキャンセルすると1からやり直し ディスクの管理にも注意が必要 一時的に2倍のディスクが必要 53

5.実際のデバッグ(例4) 結合 advertiser_contact advertiser_contact_id advertiser_id notice_id data1 [int] [int] [int] [text] advertiser advertiser_id [int] type [int] data1 [text] typeが1のadvertiserがcontactした数を知りたい SELECT count(*) FROM advertiser_contact JOIN advertiser USING (advertiser_id) WHERE type=1; 54

5.実際のデバッグ(例4) 結合 Explaining EXPLAIN p41 55

5.実際のデバッグ(例4) 結合 Explaining EXPLAIN p42 56

6.実際のデバッグ(例4) 結合 57 Explaining EXPLAIN p43 一部修正

6.実際のデバッグ(例4) 結合 EXPLAINING EXPLAINが作られたのは2005年 以降 プランナの改善 も進んでいます PostgreSQL8.4のリリースノート より http://www.postgresql.jp/document/9.1/html/release-8-4.html リリース日: 2009-07-01 半結合および反結合に関して明確な概念を作成しました (Tom) この作業により IN (SELECT...)句に関するこれまでのとってつけたような 扱いを形式化しました さらにこれをEXISTSおよびNOT EXISTS句にも 拡張しました これによりEXISTSおよびNOT EXISTS問い合わせの 計画作成が非常に改善されるはずです 一般的には 論理的には 同一であるINとEXISTS句が 同程度の性能を持つようになりました これまではよくINの方が勝っていました 今回紹介したIN EXISTSの書き換えによる差は減っている 58

5.実際のデバッグ(例4) 結合 通常の結合(JOINを使った結合) advatizer_contact advatizer advertiser_contact_id=1 data=piyo type=0 data=hoge advertiser_contact_id=2 data=hoge type=1 data=piyo advertiser_contact_id=3 data=huga type=0 data=huga advertiser_contact_id=4 data=piyo type=1 data=hoge advertiser_contact_id=5 data=hoge type=1 data=piyo 該当行を全てスキャンする必要がある 59

5.実際のデバッグ(例4) 結合 半結合(IN,EXISTSを使った場合) advatizer_contact advatizer advertiser_contact_id=1 data=piyo type=0 data=hoge advertiser_contact_id=2 data=hoge type=1 data=piyo advertiser_contact_id=3 data=huga type=0 data=huga advertiser_contact_id=4 data=piyo type=1 data=hoge advertiser_contact_id=5 data=hoge type=1 data=piyo データが見つかった時点で走査を中止 =走査範囲が狭まる可能性あり 60

6.実際のデバッグ(例4) 結合 Original 通常のJOINで結合した場合 =# SELECT count(*) FROM advertiser_contact -# JOIN advertiser USING (advertiser_id) WHERE type=1; Time: 5776.337 ms INを使った半結合 =# SELECT count(*) FROM advertiser_contact WHERE advertiser_id -# IN (SELECT advertiser_id FROM advertiser WHERE type = 1); Time: 3048.365 ms EXISTSを使った半結合 =# SELECT count(*) FROM advertiser_contact WHERE -# EXISTS (SELECT 1 FROM advertiser (# WHERE advertiser_id=advertiser_contact.advertiser_id AND type = 1); Time: 3052.906 ms 61

6.実際のデバッグ(例4) 結合 Original =# EXPLAIN ANALYZE SELECT count(*) FROM advertiser_contact WHERE -# EXISTS (SELECT 1 FROM advertiser (# WHERE advertiser_id=advertiser_contact.advertiser_id AND type = 1); QUERY PLAN 常のJOINで結合した場合以下の1行のみ違う結果に ----------------------------------------------------------------------------------> Nested Loop (cost=0.00..751969.75 rows=100000 width=0) Aggregate (cost=752219.75..752219.76 rows=1 width=0) (actual time=0.015..46404.480 rows=50000 loops=1) (actual time=24385.542..24385.543 rows=1 loops=1) -> Nested Loop Semi Join (cost=0.00..751969.75 rows=100000 width=0) (actual time=0.015..24361.835 rows=50000 loops=1) Join Filter: (advertiser_contact.advertiser_id = advertiser.advertiser_id) -> Seq Scan on advertiser_contact (cost=0.00..1935.00 rows=100000 width=4) (actual time=0.004..53.075 rows=100000 loops=1) -> Materialize (cost=0.00..36.00 rows=500 width=4) (actual time=0.000..0.111 rows=263 loops=100000) -> Seq Scan on advertiser (cost=0.00..33.50 rows=500 width=4) (actual time=0.005..0.543 rows=500 loops=1) Filter: (type = 1) Total runtime: 24385.612 ms (8 rows) 62

例4)のまとめ より速いSQLが無いか考えよう 新しいバージョンを使おう 63

7.まとめ Explaining EXPLAIN p44 等 64

7.まとめ Explaining EXPLAIN p45 65

ご静聴ありがとうございました 参考資料 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://www.sxc.hu/ Special Thanks(random order) 板垣 貴裕さん 高塚 遙さん 笠原 辰仁さん 66