Upgrade to Pro — share decks privately, control downloads, hide ads and more …

SQL Server ボトルネック箇所特定とチューニングの実演 / SQL Server an...

Avatar for it-ito it-ito
April 20, 2019

SQL Server ボトルネック箇所特定とチューニングの実演 / SQL Server analyze bottleneck and tuning

第17回 SQL Server 2019勉強会
https://sqlserver.connpass.com/event/125485/

Avatar for it-ito

it-ito

April 20, 2019

Other Decks in Programming

Transcript

  1. 今回の調べ方 • とりあえずクエリストアを見てみよう • クエリストア – SQL Server 2016から使える機能 –

    パフォーマンスチェックやクエリプランの矯正が可能 – 事前に有効化しておく必要あり
  2. パフォーマンスに違いのあるクエリ -- 8月31日に登録した人のコメントを抽出するクエリ SELECT c.* FROM [Users] AS u INNER

    JOIN [Comments] AS c ON c.[UserId] = u.[Id] WHERE u.[CreationDate] >= '2008/08/31' AND u.[CreationDate] < '2008/09/01' ;
  3. 実行計画見るときに使えるツール • ApexSQL Plan – https://www.apexsql.com/sql-tools-plan.aspx – 第15回 SQL Server

    2019勉強会で紹介されていました • SentryOne Plan Explorer – https://www.sentryone.com/plan-explorer – 第16回 SQL Server 2019勉強会で紹介されていました – 私が今日使っているのはこっち
  4. NESTED LOOP JOIN (インデックスがない場合) UserId 主キー UserId 3 1 3

    2 2 3 1 1 内部表 外部表(駆動表) 動きとしてはプログラムのfor文の動き 非常に効率が悪い
  5. NESTED LOOP JOIN (インデックスがある場合) UserId 主キー UserId 3 1 3

    2 2 3 1 1 内部表 外部表(駆動表) インデックスを辿って結合処理が行われる
  6. MERGE JOIN UserId 主キー UserId 1 1 1 2 2

    3 3 3 1. IDでソートする UserId 主キー UserId 1 1 1 2 2 3 3 3 2. 上から突き合わせていく
  7. HASH JOIN UserId 主キー UserId 3 1 3 2 2

    3 1 1 1. Hashテーブルを作成 0xB6589FC 0x356A192 0xDA4B923 2. Hash値と突き合わせる
  8. 読み込む行数だけに注目してみると NESTED LOOP JOIN(インデックスなし) NESTED LOOP JOIN(インデックスあり) MERGE JOIN HASH

    JOIN m行 m行 m行 m行 n行 m×n行 外部表は全行、内部表はインデックスによる m+am行 最低m+n行 最低m+n行 n行 n行 n行 各表を上から突き合わせる、場合によってソートあり 各表を上から突き合わせる
  9. 読み込む行数だけに注目してみると NESTED LOOP JOIN(インデックスなし) NESTED LOOP JOIN(インデックスあり) MERGE JOIN HASH

    JOIN m行 m行 m行 m行 n行 m×n行 外部表は全行、内部表はインデックスによる m+am行 最低m+n行 最低m+n行 n行 n行 n行 各表を上から突き合わせる、場合によってソートあり 各表を上から突き合わせる もしも外部表が内部表と比べて小さく、インデッ クスで大きく絞ることができる状況であれば、 内部表の量に影響されない NESTED LOOP JOINが大きな効果を発揮する
  10. • RANGE_HI_KEY = 3043に注目して見てみると – RANGE_ROWSはユーザーIDが2509より上で3043未満のレコード数が 19336行であることを表す – EQ_ROWSはユーザーID3043と一致するレコード数を表す –

    DISTINCT_RANGE_ROWSはユーザーIDが2509より上で3043未満でレ コードが存在しているIDの行数を表す – AVG_RANGE_ROWSは(RANGE_ROWS / DISTINCT_RANGE_ROWS) 問題ないDBのCommentsテーブルのユーザーIDインデックスの統計情報
  11. 統計情報の更新 • コマンド – UPDATE STATISTICS • https://docs.microsoft.com/ja-jp/sql/t- sql/statements/update-statistics-transact-sql?view=sql- server-2017

    – sp_updatestats • 経験則としては、UPDATE STATISTICSのほうが、サ ンプリング率を明示的にFULLにできるので、問題 が起きにくい
  12. パフォーマンスの 悪い部分を探す クエリストア 実行計画 拡張イベント パフォーマンスモニタ 動的管理ビュー … 原因を探す 実行計画が想定

    と異なる IOでwaitが発生している ロックされている n+1問題 … 修正する クエリを 書き換える 統計情報を更新する SQL Serverの設定を 変更する インデックスを 追加する …
  13. パフォーマンスの 悪い部分を探す クエリストア 実行計画 拡張イベント パフォーマンスモニタ 動的管理ビュー … 原因を探す 実行計画が想定

    と異なる IOでwaitが発生している ロックされている n+1問題 … 修正する クエリを 書き換える 統計情報を更新する SQL Serverの設定を 変更する インデックスを 追加する … パフォーマンスが悪くなる多種多様の原因がありますが、 SQL Serverでは原因を探すための様々な機能がデフォルトで用意されています。 基本的なものはそこから順を追っていけば解決することが可能です。