Mais conteúdo relacionado Semelhante a SQL Server チューニング基礎 (20) SQL Server チューニング基礎13. オプティマイザー 論理プラン
選手番号 選手名 利き腕 チーム番号
1 AAA 右 1
2 BBB 左 1
3 CCC 右 3
4 DDD 右 2
5 EEE 右 1
6 FFF 左 2
チーム番号 チーム名
1 XXX
2 YYY
3 ZZZ
選手表とチーム表で「直積」
チーム番号が等しく
利き腕が”左”の行を「選択」
選手名とチーム名を「射影」
SELECT 選手名, チーム名 FROM 選手, チーム
WHERE 選手.チーム番号 = チーム.チーム番号 AND 利き腕 = ‘左’
選手表とチーム表を
チーム番号で「結合」
利き腕が”左”の行を「選択」
選手名とチーム名を「射影」
選手表から
利き腕が”左”の行を「選択」
上の結果とチーム表を
チーム番号で「結合」
選手名とチーム名を「射影」
6×18
6×2
2×2 2×2
6×2
6×6
4×2
6×2
2×2
選
手
表
チ
ー
ム
表
クエリトランスフォーム
エスティメート
プランジェネレート
統計情報
時間余
エクゼキューター
パーサー
構文ツリー
論理プラン
カタログ
物理プラン
物理プラン
14. オプティマイザー 物理プラン
選手番号 選手名 利き腕 チーム番号
1 AAA 右 1
2 BBB 左 1
3 CCC 右 3
4 DDD 右 2
5 EEE 右 1
6 FFF 左 2
チーム番号 チーム名
1 XXX
2 YYY
3 ZZZ
SELECT 選手名, チーム名 FROM 選手, チーム
WHERE 選手.チーム番号 = チーム.チーム番号 AND 利き腕 = ‘左’
選手表から
利き腕が”左”の行を「選択」
上の結果とチーム表を
チーム番号で「結合」
選手名とチーム名を「射影」
4×2
6×2
2×2
選
手
表
チ
ー
ム
表
論理プラン 物理プラン
2×2
Index Seek Table Scan
Nested Loop Join Hash Join
Filter
Merge Join
クエリトランスフォーム
エスティメート
プランジェネレート
統計情報
時間余
エクゼキューター
パーサー
構文ツリー
論理プラン
カタログ
物理プラン
物理プラン
15. オプティマイザー 物理プラン
選手番号 選手名 利き腕 チーム番号
1 AAA 右 1
2 BBB 左 1
3 CCC 右 3
4 DDD 右 2
5 EEE 右 1
6 FFF 左 2
チーム番号 チーム名
1 XXX
2 YYY
3 ZZZ
SELECT 選手名, チーム名 FROM 選手, チーム
WHERE 選手.チーム番号 = チーム.チーム番号 AND 利き腕 = ‘左’
選手表から
利き腕が”左”の行を「選択」
上の結果とチーム表を
チーム番号で「結合」
選手名とチーム名を「射影」
4×2
6×2
2×2
選
手
表
チ
ー
ム
表
論理プラン 物理プラン
2×2
Index Seek Table Scan
Nested Loop Join Hash Join
Filter
Merge Join
クエリトランスフォーム
エスティメート
プランジェネレート
統計情報
時間余
エクゼキューター
パーサー
構文ツリー
論理プラン
カタログ
物理プラン
物理プラン
17. オプティマイザー
番号 氏名 誕生 性別
1 ・・・ ・・・ ・・・
2 ・・・ ・・・ ・・・
~ ・・・ ・・・ ・・・
50 ・・・ ・・・ ・・・
番号 氏名 名 性別
51 ・・・ ・・・ ・・・
52 ・・・ ・・・ ・・・
~ ・・・ ・・・ ・・・
100 ・・・ ・・・ ・・・
番号 氏名 誕生 性別
1 ・・・ ・・・ ・・・
102 ・・・ ・・・ ・・・
52 ・・・ ・・・ ・・・
~ ・・・ ・・・ ・・・
50 ・・・ ・・・ ・・・
51 ・・・ ・・・ ・・・
101 ・・・ ・・・ ・・・
~ ・・・ ・・・ ・・・
100 ・・・ ・・・ ・・・
2 ・・・ ・・・ ・・・
51 ・・・ ・・・ ・・・
番号
1
番号
51
番号
1
番号
101
番号 氏名 名 性別
101 ・・・ ・・・ ・・・
102 ・・・ ・・・ ・・・
~ ・・・ ・・・ ・・・
150 ・・・ ・・・ ・・・
番号
101
番号
151
番号 氏名 名 性別
151 ・・・ ・・・ ・・・
152 ・・・ ・・・ ・・・
~ ・・・ ・・・ ・・・
200 ・・・ ・・・ ・・・
番号
root
ヒープ クラスタ化インデックス
18. オプティマイザー
誕生 番号
2000/01/01 ・・・
~ ・・・
2000/12/28
誕生
2000/01/01
非クラスタ化インデックス
誕生
2001/01/03
誕生
2000/01/01
誕生 番号
2001/01/03 ・・・
~ ・・・
2001/11/14 ・・・
誕生 番号
2002/01/05 ・・・
~ ・・・
2002/12/31 ・・・
誕生
2002/01/05
誕生
2003/01/01
誕生
2002/01/05
誕生 番号
2003/01/01 ・・・
~ ・・・
2003/12/24 ・・・
102
誕生 RID
2000/01/01 ・・・
~ ・・・
2000/12/28
誕生
2000/01/01
誕生
2001/01/03
誕生
2000/01/01
誕生 RID
2001/01/03 ・・・
~ ・・・
2001/11/14 ・・・
誕生 RID
2002/01/05 ・・・
~ ・・・
2002/12/31 ・・・
誕生
2002/01/05
誕生
2003/01/01
誕生
2002/01/05
誕生 RID
2003/01/01 ・・・
~ ・・・
2003/12/24 ・・・
X:Y:Z
データ部がヒープの場合:
ブックマークとしてヒープの
RIDを保持し、RIDを利用
してヒープにアクセスする。
データ部がクラスタ化インデックスの場合:
ブックマークとしてクラスタ化インデックスの
キー値を保持し、キー値以外の列値が必要
なケースはキー値を利用してクラスタ化イン
デックスにアクセスする
クラスタ化インデックス
非クラスタ化インデックス
ヒープ
19. オプティマイザー
例)SELECT c1, c2 FROM t1 WHERE c1 = 1
c1
1
c1
・・・
c1
・・・
c1
1
c1
・・・
c1 c2 c3 c4 c5 c6 c7
1 hoge ・・・ ・・・ ・・・ ・・・ ・・・
・・・ ・・・ ・・・ ・・・ ・・・ ・・・ ・・・
・・・ ・・・ ・・・ ・・・ ・・・ ・・・ ・・・
c1 c2
1 hoge
c1 c2
・・・ ・・・
c1 c2
・・・ ・・・
c1 c2
1 hoge
c1 c2
・・・ ・・・
c1 c2 c3 c4 c5 c6 c7
1 hoge ・・・ ・・・ ・・・ ・・・ ・・・
・・・ ・・・ ・・・ ・・・ ・・・ ・・・ ・・・
・・・ ・・・ ・・・ ・・・ ・・・ ・・・ ・・・
c1 c2 c3 c4 c5 c6 c7
1 hoge ・・・ ・・・ ・・・ ・・・ ・・・
・・・ ・・・ ・・・ ・・・ ・・・ ・・・ ・・・
・・・ ・・・ ・・・ ・・・ ・・・ ・・・ ・・・
c1 c2
1 hoge
c1 c2
・・・ ・・・
c1 c2
・・・ ・・・
c1
1
c1
・・・
カバリング
インデックス
付加列
インデックス
21. オプティマイザー
例)シーク可能 例)シーク不可
• c1 = 1
• c1 < 1
• c1 > 1
• c1 <> 1
• c1 + 1 = 2
• AVG(c1) > 1
• c1 IN (1, 2, 3)
• BETWEEN c1 1 AND 3
• c1 NOT IN (1, 2, 3)
• c1 = ‘hoge’ • c1 != ‘hoge’
• c1 like ‘ho%’ • c1 like ‘%ge’
• c1 like ‘%og%’
例)シーク可能 例)シーク不可
• c1 = 1 AND c2 = ‘hoge’ • c1 <> 1 AND c2 = ‘hoge’
• c1 = 1 • c2 = 1
• c1 = 1 OR c2 = ‘hoge’
<複合インデックス>
CREATE INDEX idx_c1_c2 ON t1(c1, c2)
<単一列インデックス>
CREATE INDEX idx_c1 ON t1(c1)
複合インデックスは列指定順序が重要
→インデックスの並び順は一番最初に指定した列の順に配置
idx_c1_c2 ON t1(c1, c2)
c1 c2
1 hoge
c1 c2
5 aaa
c1 c2
19 sss
c1 c2
13 zzz
idx_c2_c1 ON t1(c2, c1)
c2 c1
aaa 5
c2 c1
hoge 1
c2 c1
zzz 13
c2 c1
sss 19
22. オプティマイザー
注文ID 商品ID 日付 売上
101 52 201801 100
・・・ ・・・ ・・・ ・・・
110 23 201812 300
集
計
処
理
101 52 201801 100
・・・ ・・・ ・・・ ・・・
110 23 201212 300
バッファプール
101 52 201801 100
・・・ ・・・ ・・・ ・・・
110 23 201212 300
集計に不要な列
もI/Oされる
集計に不要な列
もキャッシュされる
注文ID 商品ID 日付 売上
101 52 201801 100
・・・ ・・・ ・・・ ・・・
110 23 201812 300
集
計
処
理
100
・・・
300
バッファプール
100
・・・
300
行ストア
列ストア
集計に不要
な列はキャッ
シュされない
同じ属性なので
圧縮効果が高く
I/O負荷軽減
列ストア インデックス: 概要 - SQL Server | Microsoft Docs
VS 集計に不要な列
はI/Oされない
23. オプティマイザー 物理プラン
選手番号 選手名 利き腕 チーム番号
1 AAA 右 1
2 BBB 左 1
3 CCC 右 3
4 DDD 右 2
5 EEE 右 1
6 FFF 左 2
チーム番号 チーム名
1 XXX
2 YYY
3 ZZZ
SELECT 選手名, チーム名 FROM 選手, チーム
WHERE 選手.チーム番号 = チーム.チーム番号 AND 利き腕 = ‘左’
選手表から
利き腕が”左”の行を「選択」
上の結果とチーム表を
チーム番号で「結合」
選手名とチーム名を「射影」
4×2
6×2
2×2
選
手
表
チ
ー
ム
表
論理プラン 物理プラン
2×2
Index Seek Table Scan
Nested Loop Join Hash Join
Filter
Merge Join
クエリトランスフォーム
エスティメート
プランジェネレート
統計情報
時間余
エクゼキューター
パーサー
構文ツリー
論理プラン
カタログ
物理プラン
物理プラン
24. オプティマイザー
Nested Loop Join Hash Join
Merge Join
一方のテーブルの対象データ量が少
ない場合やインデックスで絞り込め
る場合に最適(主としてOLTP)
結合列が並び替えられている
大量の入力を処理する場合
に最適(主としてOLAP)
結合 (SQL Server) - SQL Server | Microsoft Docs
結合列が並び替えられていない
大量の入力を処理する場合に
最適(主としてOLAP)
25. オプティマイザー 物理プラン
選手番号 選手名 利き腕 チーム番号
1 AAA 右 1
2 BBB 左 1
3 CCC 右 3
4 DDD 右 2
5 EEE 右 1
6 FFF 左 2
チーム番号 チーム名
1 XXX
2 YYY
3 ZZZ
SELECT 選手名, チーム名 FROM 選手, チーム
WHERE 選手.チーム番号 = チーム.チーム番号 AND 利き腕 = ‘左’
選手表から
利き腕が”左”の行を「選択」
上の結果とチーム表を
チーム番号で「結合」
選手名とチーム名を「射影」
4×2
6×2
2×2
選
手
表
チ
ー
ム
表
論理プラン 物理プラン
2×2
Index Seek Table Scan
Nested Loop Join Hash Join
Filter
Merge Join
クエリトランスフォーム
エスティメート
プランジェネレート
統計情報
時間余
エクゼキューター
パーサー
構文ツリー
論理プラン
カタログ
物理プラン
物理プラン
26. オプティマイザー
密度
ヒストグラム
行数、ページ数
カーディナリティ
カーディナリティ推定値
推定コスト
物理プランA 物理プランB
物理プランA 物理プランB
統計 - SQL Server | Microsoft Docs
カーディナリティが高いほどインデックスの利用効果が高い
逆に低い場合はフルスキャンが効率的
カーディナリティが高い例:性別、都道府県 etc…
カーディナリティが低い例:会員番号、更新日時 etc…
コストの大小=プランの良し悪し
処理される推定行(カーディナリティ×行数やページ数)
統計情報
コスト=10 コスト=25
カーディナリティ推定 (SQL Server) - SQL Server | Microsoft Docs
※. SQLDBはクエリ実行の中で統計情報の鮮度
を確認し古いと判断した場合は統計情報を更
新したのちクエリ処理を再開する(クエリ処理と
同期せず非同期に更新させることもパラメータ設
定で可能)。
27. オプティマイザー
ヒント (Transact-SQL) - SQL Server | Microsoft Docs
例)結合順序の指定
SELECT * FROM A
JOIN B on A.ID = B.ID
JOIN C on A.ID = C.ID
OPTION (FORCE ORDER)
例)利用したい結合方式の指定
SELECT * FROM A
JOIN B on A.ID = B.ID
OPTION (MERGE JOIN)
例)実行プランを直指定
SELECT * FROM A
JOIN B on A.ID = B.ID
OPTION (USE PLAN N’XMLフォーマットのプラン’)
例)利用したいインデックスの指定
SELECT * FROM A
WHERE IDX_A_COL = 1
OPTION (TABLE HINT(A, INDEX(IDX_A_COL)))
28. オプティマイザー 物理プラン
選手番号 選手名 利き腕 チーム番号
1 AAA 右 1
2 BBB 左 1
3 CCC 右 3
4 DDD 右 2
5 EEE 右 1
6 FFF 左 2
チーム番号 チーム名
1 XXX
2 YYY
3 ZZZ
SELECT 選手名, チーム名 FROM 選手, チーム
WHERE 選手.チーム番号 = チーム.チーム番号 AND 利き腕 = ‘左’
選手表から
利き腕が”左”の行を「選択」
上の結果とチーム表を
チーム番号で「結合」
選手名とチーム名を「射影」
4×2
6×2
2×2
選
手
表
チ
ー
ム
表
論理プラン 物理プラン
2×2
Index Seek Table Scan
Nested Loop Join Hash Join
Filter
Merge Join
クエリトランスフォーム
エスティメート
プランジェネレート
統計情報
時間余
エクゼキューター
パーサー
構文ツリー
論理プラン
カタログ
物理プラン
物理プラン
33. クエリストアの設定
ALTER DATABASE の SET オプション (Transact-SQL) - SQL Server | Microsoft Docs
クエリ ストアを使用する際のベスト プラクティス - SQL Server | Microsoft Docs
41. インデックスの定期メンテナンス
⚫ 外部断片化
➢ インデックス論理順とファイル内物理順の不一致度合いを示す
➢ データ順が不連続状態になることでのアクセス効率低下
断片化の種類とその影響
10
- 11
index
record
11
10 20
index
record
12
p n
index
record
13
p n
index
record
14
p n
index
record
15
26 16
index
record
16
15 17
index
record
17
16 18
index
record
18
p n
index
record
19
p n
index
record
20
11 23
index
record
21
p n
index
record
22
p n
index
record
23
20 24
index
record
24
23 15
index
record
25
p n
index
record
~
ファイル内の物理番地 →
インデックスの論理順 →
インデックスAの断片
(大きさ=2)
インデックスAの断片
(大きさ=3)
インデックスAの断片
(大きさ=1)
インデックスAの断片化率 = =37.5%
3(赤線ホップ数)
8(総ページ数)
インデックスAの断片
(大きさ=2)
42. インデックスの定期メンテナンス
⚫ 再構成( ALTER INDEX REORGANIZE )
➢ すでに確保したエクステントの中で断片化を解消する(内部断片化と論理断片化を解消する)。
⚫ 再構築( ALTER INDEX REBUILD )
➢ 新たなエクステントを確保して断片化を解消する(エクステントの断片化を含むすべての断片化を解消する。ただし、エクス
テントの断片化解消はどれだけ連続領域が確保できたかに依存する) 。
➢ 再構築は最大精度(サンプリング100%)での統計情報の更新を伴う。よって再構築直後の統計情報更新は不要。
※. 使い分けの目安(参考)
➢ 再構成:外部断片化率(avg_fragmentation_in_percent)が5~30%
➢ 再構築:外部断片化率(avg_fragmentation_in_percent)30%~ または エクステントごとの平均ページ数
(avg_fragment_size_in_pages)が8未満
断片化解消の2つのモード
50. © 2022 Microsoft Corporation. All rights reserved.
本情報の内容(添付文書、リンク先などを含む)は、作成日時点でのものであり、予告なく変更される場合があります。