-
Notifications
You must be signed in to change notification settings - Fork 0
MS_SQLServerJoinMethodMonitoring
- 戻る(SQL Server)(SQL Server 問題の分析方法)
- SQL Server 結合方式の問題を監視する
- SQL Server の障害復旧
- DBMSのロック・分離戦略と同時実行制御 / SQL Server でのロック・タイムアウト / SQL Server のロックのエスカレーション / SQL Server でのデッドロック
- SQL Server 大量データ処理時の性能問題 / SQL Server アドホック クエリ問題の監視
SQL Server では、結合方法を
- ネスト化ループ結合
- マージ結合
- ハッシュ結合
から選択できる。
三つのアルゴリズムは、一般的に
ネスト・ループ結合 < マージ結合 < ハッシュ結合
の順で高速(ハッシュ結合が最速)。
ただし、以下のケースでは、必ずしもこの順番にならない。
- 二つのテーブルのレコードの数が極端に違う場合
- 両方のレコードの数が十分小さいとき
- 検索条件に合致した 1 レコードを早く返したい
補足(速さは件数で逆転する): 上の順序は
大量データ同士を結合する場合の一般論であり、
実際にはデータ量によって最適な方式が入れ替わる。
「ハッシュ結合が最速」と覚えるのではなく、
オプティマイザが件数の見積りから選び分けていると理解するのが正しい。
方式 得意な状況 計算量の目安 事前処理 ネスト ループ 外側が少数 + 内側にインデックス O(N × logM) 不要 マージ 両方が結合キー順に整列済み O(N + M) ソートが必要な場合あり ハッシュ 大量 × 大量、インデックスなし O(N + M) ハッシュ テーブル構築(メモリ) このため、実行プランで「不適切な結合方式が選ばれている」場合、
真因は結合方式ではなく件数の見積り誤りであることがほとんどである。
統計情報の鮮度を先に確認すること
(SQL Server のオプティマイザ)。
- 単純に二重ループを回してテーブルを結合する方法。
- インデックスが設定されていない小さなテーブルと
インデックスが設定されている大きなテーブルの二つを結合する場合に効果的。
-
ネスト・ループ結合の改良版。
-
二つのテーブルの結合フィールドをあらかじめソート。
-
ソート結果の結合フィールドのポインタを上から下へと順に走査。
-
これによって、レコードの走査が 1 回で済む。
-
ネスト・ループ結合の改良版。
-
ハッシュ結合は高速だが、
- ハッシュ テーブルを作成するため、
- 元のテーブルのサイズが大きい場合、
ハッシュ テーブルがメモリを大量に消費することがある。
補足(ハッシュのスピル): ハッシュ テーブルが
クエリに割り当てられたメモリ グラントに収まらない場合、
tempdb にあふれる(spill)。
実行プランでは Hash Match 演算子に警告アイコンが付き、
「Hash Warning」として現れる。
この状態になると、メモリ内処理を前提にした速度は出ない
(SQL Server のファイルの配置の tempdb の項も参照)。スピルが起きる主因も、やはり件数の見積り誤りである。
この場合、パフォーマンス カウンタを使用して監視を行う。
この場合、
- SQL Server:Buffer Manager:Free pages
のカウンタ値が低く、
- SQL Server:Buffer Manager:Stolen Page Count
- SQL Server:Buffer Manager:Memory Grants Pending
のカウンタ値が高いという状態になる。
移行メモ(正誤):
Memory Grants Pendingは
Memory Manager オブジェクトのカウンタである
(SQLServer:Memory Manager\Memory Grants Pending)。
SQL Server アドホック クエリ問題の監視と
ちょうど逆の兆候を見ている点に注目すると、両ページの対比が理解しやすい。
補足(現在の調べ方): メモリ グラント待ちは DMV で直接見える。
-- メモリ グラントを待っている/確保している要求 SELECT session_id, request_time, grant_time, requested_memory_kb, granted_memory_kb, used_memory_kb, wait_order, is_next_candidate, queue_id, dop FROM sys.dm_exec_query_memory_grants ORDER BY requested_memory_kb DESC;
grant_timeがNULLの行はメモリ待ち(待ち事象RESOURCE_SEMAPHORE)。
また、requested_memory_kbに対してused_memory_kbが
極端に小さい場合は過大なメモリ グラントで、
他のクエリを待たせている。
SQL Server 2017 以降のバッチ モード メモリ許可フィードバック、
2019 以降の行モード メモリ許可フィードバックは、
この過大/過小を実行結果から自動補正する機能である。
この状態では、SQL Server のメモリ不足が発生する可能性がある。
この場合、
- 「ネスト化ループ結合」に変更できる
- 「ハッシュ結合」を使用している
クエリを探すことに重点を置く。
結合方法を見分けるには、実行プランを確認する
(実行プランのグラフィカル表示)。
補足(結合ヒントは最後の手段):
OPTION (LOOP JOIN)や
INNER LOOP JOINといったヒントで結合方式を固定できるが、
データ量が変われば最適解も変わるため、恒久的な指定は避ける。
対処の優先順位は以下。
- 統計情報を更新して見積りを正す
- 結合キーにインデックスを作る(ネスト ループが選べるようになる)
- 不要な行を先に絞る(
WHEREの見直し、中間結果の削減)- パラメータ スニッフィングが原因なら
OPTIMIZE FOR/RECOMPILE- どうしても直らない場合にヒント、またはクエリ ストアでプラン強制
なお、ヒントを付けるとそのヒントを満たすプランしか作れなくなり、
場合によってはクエリ自体が失敗する(FORCE ORDERとの併用時など)。
詳細は、以下の URL を参照のこと。
-
PASSJ & SQL Server Developer Center ジョイントコラム
第 2 回 「クエリの実行方法を理解する」~ システム構築 ~
https://learn.microsoft.com/ja-jp/sql/relational-databases/performance/joins -
特集:基礎から理解するデータベースのしくみ(4):ITpro
http://itpro.nikkeibp.co.jp/article/COLUMN/20060111/227102/ -
結合 | Microsoft Learn
https://learn.microsoft.com/ja-jp/sql/relational-databases/performance/joins
Tags: 移行, データアクセス, SQL Server, 障害対応, 性能
このWikiは「Open棟梁Project」,「OSSコンソーシアム 開発基盤部会」によって運営されています。