O slideshow foi denunciado.
Utilizamos seu perfil e dados de atividades no LinkedIn para personalizar e exibir anúncios mais relevantes. Altere suas preferências de anúncios quando desejar.

[JSSUG(2019-10-26)]SQL Serverのインデックス設計

[JSSUG(2019-10-26)]SQL Serverのインデックス設計

SQL Server でのインデックス設計の基本的な考え方
# 対象者
- 正規化を含めたテーブル設計は理解しているが、インデックス設計に悩んでいる方

# 備考
- JSSUG主催「第23回 SQL Server 2019勉強会」での発表資料です。
- https://sqlserver.connpass.com/event/169455/

  • Seja o primeiro a comentar

[JSSUG(2019-10-26)]SQL Serverのインデックス設計

  1. 1. SQL Serverのインデックス設計 インデックス設計の基本的な考え方 山田公次 2019/10/26
  2. 2. /36 自己紹介 山田 公次(Yamada Koji) • 名古屋在住の C#per(JavaはJava6まで経験) • 現在は市販のWebアプリの開発に携わっており、主にドメイン分 析やサーバー開発(モデル・WebAPI・DB)を担当しています。 • また、Scrumを導入しており、Scrum inc.認定Scrum Masterも取得しました。 2 @hamu502 製品開発部署(現在) 市販アプリの開発だけで なく、企画からサポートま で幅広く対応 フリーランス時代 業務アプリ開発、 クラウドのセールスSE、 市販アプリの開発 中小SIer時代 金融や流通、 不動産業界などの 業務アプリ開発 主に扱ったDB製品 Oracle8~11g,SQL Server2000~2005,etc 主に扱ったDB製品 Oracle11g,SQL Server2008~ 1998~ 2008~ 2018~
  3. 3. /36 目的と対象者 本資料の目的 • 以下のような方が、「何となく」ではなく、根拠 を持ってインデックス設計できること。 • テーブルの正規化は分かるが、インデックスの 理解度が低いと感じている方 • テーブル設計はできるが、インデックス設計に 自信がない方 3
  4. 4. /36 アジェンダ 4 1.インデックスの概要 2.インデックスの種類 3.インデックスの設計基準 4.さいごに
  5. 5. 1. インデックスの概要 5
  6. 6. /36 リレーショナルデータベース(RDB)とは • 関係モデルを扱えるようにしたデータベース。表形式のドメインとドメイン同士 の関係を定義することで、複雑なデータの関係性を管理する。 • データベースの定義や操作には、SQL (構造化クエリ言語)を使用する。 部品名 取引先名 単価 部品A B社 … 部品A C社 … 部品C A社 … … … … RDBとのデータのやり取りのイメージ リレーショナルデータベース(RDB) 取引先名 連絡先 担当者 … A社 … … … B社 … … … C社 … … … … … … … 部品名 部品コード 分類 … 部品A P0001 共通 … 部品B P0002 XX機器 … 部品C P0003 YY製品 … … … … … 関係 関係 6 部品単価 オプティマイザ SQL 実際のアクセス処理 (実行計画) 1.インデックスの概要(の前に…) ・データベース スキーマ (テーブルやインデックスの定義) ・データベース統計情報 SELECT 部品名,取引先名,・・・ FROM ・・・ JOIN ・・・ WHERE ・・・ インデックスも入力情報の一つ
  7. 7. /36 1.インデックスの概要 7 インデックスとは、DBデータの検索を高速に行うための索引のようなもの インデックスを使うと、テーブルのすべての行を検索せずに目的のデータを特定す ることができる便利なしくみ • SQL ServerのインデックスはB-Tree構造で実現されている 参考:MS TechNet 「インデックスの基礎」 (https://technet.microsoft.com/ja-jp/library/ms190457(v=sql.105).aspx) ルートノード 中間ノード リーフノード ・・・ ・・・・・・・・・・・ B-Tree構造のイメージ
  8. 8. /36 1.インデックスの概要 8 インデックスが存在しない場合 • 2020年3月計上のデータを検索する際、実テーブルの先頭から検索する 処理を行う(Table Scan) 受注ID 計上年月 受注日 顧客ID 担当ID 金額 ・・・ 1 2017/4 2017/4/3 10 5 ・・・ ・・・ 2 2017/4 2017/4/3 2 7 ・・・ ・・・ 3 2017/4 2017/4/3 10 7 ・・・ ・・・ ・・・ 9000 2019/10 2019/9/30 10 5 ・・・ ・・・ 9001 2019/10 2019/10/2 2 13 ・・・ ・・・ ・・・ 10001 2020/3 2020/3/1 10 13 ・・・ ・・・ 10002 2020/3 2020/3/1 8 7 ・・・ ・・・ ・・・ 10123 2020/5 2020/5/30 2 7 ・・・ ・・・ 実テーブル(ヒープ) Table Scan テーブルスキャンのイメージ 実テーブルの先頭から最後まで順番に 探し続けるため、検索が遅い
  9. 9. /36 1.インデックスの概要 9 インデックスが存在する場合 • 2020年3月計上のデータを検索する場合、インデックを検索し実テーブル の場所を特定してから実データにアクセスする処理を行う(Index Seek) 受注ID 計上年月 受注日 ・・・ 1 2017/4 2017/4/3 ・・・ 2 2017/4 2017/4/3 ・・・ 3 2017/4 2017/4/3 ・・・ ・・・ 9000 2019/9 2019/9/30 ・・・ 9001 2019/10 2019/10/2 ・・・ ・・・ 10001 2020/3 2020/3/1 ・・・ 10002 2020/3 2020/3/1 ・・・ ・・・ 計上年月 2017/4 2017/5 2017/6 計上年月 2017/1~12 2018/1~12 ・・・ 2020/1~12 計上年月 2020/1 2020/2 2020/3 計上年月 データ行への ポインタ(RID) 2017/4 ● 2017/4 ● 2017/4 ● ・・・ 計上年月 データ行への ポインタ(RID) 2020/3 ● 2020/3 ● ・・・ ルートノード 中間ノード リーフノード 実テーブル(ヒープ) 「計上年月」をキーとしたインデックスをSeekするイメージ … … テーブルスキャンと異なり、実テーブルの 先頭から最後まで検索する処理を省け るため、検索が速い Index Seek RID Lookup
  10. 10. /3610 適切なインデックスを適用することで、データ取得のパ フォーマンスを向上するだけでなく、経年によるデータ増加 後のパフォーマンス劣化を抑えることが可能。 インデックスなし インデックスあり テーブルA テーブルB 外部表 (駆動表) 内部表 テーブルA テーブルB 外部表 (駆動表) 内部表 全行アクセスが 必要 インデックスをたどることで 特定行のみアクセス テーブルBの結合キーの 列に対するインデックス 1.インデックスの概要 ※参考:USE THE INDEX, LUKE! 「データ量がパフォーマンスに与える影響」 (https://use-the-index-luke.com/ja/sql/performance-scalability/data-volume)
  11. 11. 2. インデックスの種類 11
  12. 12. /36 2.インデックスの種類 12 SQL Server の主要なインデックスの種類 • 非クラスタ化インデックス • データ行とは独立したB-Tree構造のインデックス • クラスター化インデックスが設定されたテーブル、またはヒープ上に 定義 • 1テーブルに複数設定可能 三省堂編修所 『日本語キーワード 英語表現辞典(形容詞編)』より 辞書の索引ページのイメージ。 索引ページ(インデックス)には、該当の 情報(データ)が存在するページ番号が 記載されており、情報を参照するには実際 のページを開く必要がある。 また、索引ページ内の見出しはキー順序で 並んでおり、キー自体も索引の目的に合わ せて、複数種類が存在可能。 (漢字辞典であれば「読み仮名」「部首」 「画数」など複数の索引が存在する)
  13. 13. /36 2.インデックスの種類 13 SQL Server の主要なインデックスの種類 • 付加列インデックス • 非クラスター化インデックスでのみ設定可能 • 非クラスター化インデックスのキー列に加えて非キー列を付加できるよう に拡張 高知大学 学術情報基盤図書館『カード目録について』より 図書館のカード目録のイメージ。 カード目録(インデックス)には、該当の書籍の著 者名や書籍名などの書籍に関する情報(デー タ)と所蔵場所を示す分類番号などの情報が記 載されており、目的の書籍の所蔵場所を探すため に、例えば著者目録であれば著者名順に並んで いる。 著者名や書籍名など索引キーとなる項目を変更 する場合はカードの情報と並び順の変更が必要だ が、価格など非キーとなる項目を変更する場合は カードの情報のみ変更するだけで良い。
  14. 14. /36 2.インデックスの種類 14 SQL Server の主要なインデックスの種類 • クラスタ化インデックス • リーフノードがデータ行となるB-Tree構造のインデックス • テーブルのデータ行を、インデックスに設定したキー値に基づいて並 べ替えて格納 • 1テーブルに1つのみ設定可能 『babel‘s artworksさんによる写真ACからの写真』より 辞書の側面(小口)に印刷された 索引のイメージ。 小口の索引(インデックス)を開けば、 該当の情報(データ)が存在する。 また、情報自体は索引のキー順序で 並んでおり、キー順序は1種類のみ。
  15. 15. /36 2.インデックスの種類 15 インデックスの目的による分類 • 一意インデックス • キーの値が重複することがなく、テーブル行を一意に特定するインデックス • SQL Serverでは、UNIQUE制約やPRIMARY KEY制約を作成す ると自動的に作成される • 複合インデックス • 複数のキー値を指定したインデックス • 検索条件や取得列をインデックスのみで賄う目的で作成した複合イン デックスを「カバーリングインデックス」と言う
  16. 16. /36 2.インデックスの種類 - 非クラスタ化インデックス 16 ヒープのテーブルに非クラスタ化インデックスを設定した場合の動作 「計上年月」をキーとした非クラスタ化インデックスのイメージ 受注ID 計上年月 受注日 ・・・ 1 2017/4 2017/4/3 ・・・ 2 2017/4 2017/4/3 ・・・ 3 2017/4 2017/4/3 ・・・ ・・・ 9000 2019/9 2019/9/30 ・・・ 9001 2019/10 2019/10/2 ・・・ ・・・ 10001 2020/3 2020/3/1 ・・・ 10002 2020/3 2020/3/1 ・・・ ・・・ 10022 2020/4 2020/4/2 ・・・ ・・・ 計上年月 2017/4 2017/5 2017/6 計上年月 2017/1~12 2018/1~12 ・・・ 2020/1~12 計上年月 2020/1 2020/2 2020/3 計上年月 データ行への ポインタ(RID) 2017/4 ● 2017/4 ● 2017/4 ● ・・・ ● 計上年月 データ行への ポインタ(RID) 2020/3 ● 2020/3 ● ・・・ ● ルートノード 中間ノード リーフノード 実テーブル(ヒープ) … … ・・・ WHERE 計上年月=2020/3 データ行とは独立したB-Tree構造の ため、複数のインデックスを設定可能 (1/3)
  17. 17. /36 2.インデックスの種類 - 非クラスタ化インデックス 17 クラスタ化インデックスに非クラスタ化インデックスを設定した場合の動作 「計上年月」をキーとした非クラスタ化インデックスのイメージ 受注ID 計上年月 受注日 ・・・ 1 2017/4 2017/4/3 ・・・ 2 2017/4 2017/4/3 ・・・ 3 2017/4 2017/4/3 ・・・ ・・・ 計上年月 2017/4 2017/5 2017/6 計上年月 2017/1~12 2018/1~12 ・・・ 2020/1~12 計上年月 2020/1 2020/2 2020/3 計上年月 受注ID 2017/4 1 2017/4 2 2017/4 3 ・・・ 計上年月 受注ID 2020/3 10001 2020/3 10002 ・・・ ルートノード 中間ノード リーフノード クラスタ化インデックス(受注IDがキー) … …… ルートノード 中間ノード 中間ノード 受注ID 計上年月 受注日 ・・・ 10001 2020/3 2020/3/1 ・・・ 10002 2020/3 2020/3/1 ・・・ ・・・ 10022 2020/4 2020/4/2 ・・・ ・・・データ行へのポインタ(RID)ではなく、 クラスタ化インデックスのキーの値が格 納される (2/3) ・・・ WHERE 計上年月=2020/3
  18. 18. /36 2.インデックスの種類 - 非クラスタ化インデックス 18 「計上年月」「担当ID」をキーとしたカバーリングインデックスのイメージ 受注ID 計上年月 担当ID ・・・ 1 2019/4 5 ・・・ 2 2019/4 7 ・・・ 3 2019/4 7 ・・・ ・・・ 16 2019/4 5 ・・・ ・・・ カバーリングインデックスとしての非クラスタ化インデックスの動作 • 取得や条件に必要な列がインデックスのキーのみの場合、実テーブルを参照せずに 検索結果を返すため、I/Oコストが低く、検索パフォーマンスが良くなる。 • ただし、インデックスに指定するキーが多くなる傾向があるため、更新パフォーマンス劣 化のリスクを踏まえ、付加列インデックスとの比較検討を推奨。 実テーブル(ヒープ) ・・・ ・・・ ・・・ ・・・ 計上年月 担当ID 2019/4~6 1~10 2019/7~9 1~10 ・・・ 計上年月 担当ID RID ・・・ ● 2019/4 5 ● 2019/4 5 ● ・・・ ● 中間ノード リーフノード SELECT 計上年月, 担当ID FROM ・・・ WHERE 計上年月=2019/4 AND 担当ID=5 ルートノード 実テーブルは参照 しない 実テーブルを参照せずにインデックス のみで検索結果を返す (3/3)
  19. 19. /36 2.インデックスの種類 - 付加列インデックス 19 付加列インデックスを設定した場合の動作 • インデックスのキーとは別の列の値を、インデックスのキーとは別に付加列とし てリーフノードに保持する。 • 取得する列がインデックスのキーと付加列のみ、かつ、条件に必要な列がインデックス のキーのみの場合、 実テーブルを参照せずに検索結果を返すため、I/Oコストが低く、 検索パフォーマンスが良くなる。 「計上年月」をキー、金額を付加列とした付加列インデックスのイメージ 受注ID 計上年月 金額 ・・・ 1 2019/4 ・・・ ・・・ 2 2019/4 ・・・ ・・・ 3 2019/4 ・・・ ・・・ ・・・ 16 2019/4 ・・・ ・・・ ・・・ 実テーブル(ヒープ) ・・・ ・・・ ・・・ ・・・ 計上年月 2019/4~6 2019/7~9 ・・・ 計上年月 金額(付加列) RID ・・・ ● 2019/4 ・・・ ● 2019/4 ・・・ ● ・・・ ● 中間ノード リーフノード SELECT 計上年月, SUM(金額) FROM ・・・ WHERE 計上年月=2019/4 GROUP BY 計上年月 ルートノード 実テーブルは参照 しない 実テーブルを参照せずにインデックス のみで検索結果を返す 付加列はリーフノードのみ 存在する (1/2)
  20. 20. /36 2.インデックスの種類 - 付加列インデックス 20 付加列インデックス vs カバーリングインデックス • SQL Serverのデータストレージの基本単位はページであり、カバーリングインデックス で2つ目以降へ指定した列データは、正確には、ルートノードと中間ノードのページに も格納する。また、付加列インデックスの付加列データはリーフノードのページのみに 格納する。 • よって、付加列インデックスのサイズはカバーリングインデックスより小さくなり、インデック ス使用時のI/Oコスト減少が見込まれる。また、付加列に指定した列データの更新 ではリーフノードの付加列のみ更新することなり、更新パフォーマンスも優れる。 計上年月 担当ID 2019/4 5 ・・・ ・・・ 計上年月 担当ID RID 2019/4 5 ● 2019/4 7 ● ・・・ ● 中間ノードのページ リーフノードのページ ルートノードのページ (2/2) カバーリングインデックスの内部構造イメージ 計上年月 担当ID 2019/4 5 2019/4 7 ・・・ ・・・ 計上年月 2019/4 ・・・ 中間ノードのページ リーフノードのページ ルートノードのページ 付加列インデックスの内部構造イメージ 計上年月 2019/4 2019/4 ・・・ 計上年月 担当ID (付加列) RID 2019/4 5 ● 2019/4 7 ● ・・・ ● 「担当ID」の変更時、 各ノードの更新が発生 「担当ID」の変更時、 リーフノードの付加列 の値のみ更新が発生
  21. 21. /36 2.インデックスの種類 - クラスタ化インデックス 21 クラスタ化インデックスを一意インデックスで設定した場合の動作 「受注ID」をキーとしたクラスタ化インデックスのイメージ 受注ID 計上年月 受注日 顧客ID 担当ID 金額 ・・・ 1 2017/4 2017/4/3 10 5 ・・・ ・・・ 2 2017/4 2017/4/3 2 7 ・・・ ・・・ 3 2017/4 2017/4/3 10 7 ・・・ ・・・ ・・・ 受注ID 計上年月 受注日 顧客ID 担当ID 金額 ・・・ 10001 2020/3 2020/3/1 10 13 ・・・ ・・・ 10002 2020/3 2020/3/1 8 7 ・・・ ・・・ ・・・ 受注ID 1~10 10~20 ・・・ 受注ID 1~100 101~200 ・・・ 10001~ 10100 受注ID 10001~ 10010 10011~ 10020 ・・・ ルートノード 中間ノード リーフノード(データ行) … …… ・・・ WHERE 受注ID=10002 ・リーフノード自体がデータ行 ・キーの順序で格納 (1/2)
  22. 22. /36 2.インデックスの種類 - クラスタ化インデックス 22 クラスタ化インデックスを複合インデックスで設定した場合の動作 「受注日」「顧客ID」をキーとしたクラスタ化インデックスのイメージ 受注日 顧客ID 2017/4/1 ~6/30 1~10 2017/4/1 ~6/30 11~20 ・・・ 2020/1/1~ 3/31 1~10 2020/1/1~ 3/31 11~20 ・・・ ルートノード … 受注日 顧客ID 計上年月 金額 ・・・ 2017/4/1 1 2017/4 ・・・ ・・・ ・・・ 2017/4/1 8 2017/4 ・・・ ・・・ 2017/4/1 9 2017/4 ・・・ ・・・ 2017/4/1 10 2017/4 ・・・ ・・・ 受注日 顧客ID 2017/4/1 1~10 ・・・ ・・・ 2017/4/1 11~20 ・・・ ・・・ 中間ノード 受注日 顧客ID 2020/3/1 1~10 ・・・ ・・・ 2020/3/1 11~20 ・・・ ・・・ 受注日 顧客ID 計上年月 金額 ・・・ 2020/3/1 1 2020/3 ・・・ ・・・ ・・・ 2020/3/1 8 2020/3 ・・・ ・・・ 2020/3/1 9 2020/3 ・・・ ・・・ 2020/3/1 10 2020/3 … リーフノード(データ行) ・・・ WHERE 受注日=2020/3/1 AND 顧客ID=18 複数のキーも 設定可能 インデックスの先頭のキー(受注日)が条件に 含まれていないと、テーブルスキャンと似た動 作となる(Clustered Index Scan) 顧客ID=10 (2/2)
  23. 23. 3. インデックスの設計基準 23
  24. 24. /36 3.インデックスの設計基準 - インデックス全般 Microsoftのガイドラインで重要な点(1/2) • テーブル内のデータが変更された場合にインデックスをすべて調整するため、 INSERT、UPDATE、DELETE、および MERGE のパフォーマンスに影響 することを考慮する。 • 頻繁に更新するテーブルにはインデックスを設定しすぎないようにし、イン デックスの幅を狭く、つまり列数を可能な限り少なくする。 • 更新の必要が少なく、容量の大きいテーブルの場合、クエリのパフォーマ ンスを向上させるにはインデックスを多数使用する。 • 小さなテーブルではインデックスを作成しない方がよい場合もある。 • クエリの種類とクエリ内での列の使用方法を評価する。 • 完全一致検索クエリで使用される列は、非クラスター化インデックス、ま たは、クラスター化インデックスにする適切な候補になる。 ※参考:MS TechNet「インデックスの設計の全般的なガイドライン」 (https://technet.microsoft.com/ja-jp/library/ms191195(v=sql.105).aspx) 24
  25. 25. /36 Microsoftのガイドラインで重要な点(2/2) • 列内のデータの分布を調べる • インデックスを設定した列にほとんど一意の値がない場合や、このような 列を結合する場合、クエリに時間がかかることがよくある。 • インデックスに複数の列が含まれる場合は、列の順序を考慮する。 • 等しい (=)、より大きい (>)、より小さい (<)、BETWEEN などの検 索条件の WHERE 句で使用されるか、結合に含まれる列は、先頭に 配置する。 • その他の列は、差異の程度、つまり最も差異の大きいものから最も差 異の小さい順に配置する。 ※参考:MS TechNet「インデックスの設計の全般的なガイドライン」 (https://technet.microsoft.com/ja-jp/library/ms191195(v=sql.105).aspx) 25 3.インデックスの設計基準 - インデックス全般
  26. 26. /36 インデックス全般の設計ポイント(1/2) • インデックスの基準は「選択度」 • 選択度が高い場合は非クラスタ化インデックスを、低い場合はカバリングインデックスや付 加列インデックスを作成する。 • 選択度が低く、最も重要なデータの順番をクラスタ化インデックスとする。 ※参考:SQL Server Indexes (https://www.linkedin.com/pulse/sql-server-indexes-davide-mauri/) YET ANOTHER BRAIN「SQL Serverのインデックス設計基準」 (http://takumayokoo.blogspot.com/2011/02/sql-server_26.html) 「選択度」「必要とする列」を大雑把に分類した場合に、どのインデックスが向いているかのイメージ クラスタ化インデックス向き … データ全体を 100分割する ようなキー 列のほぼすべてを必要とするクエリ カバーリングor付加列インデックス向き … データ全体を 100分割する ようなキー 列の一部を必要とするクエリ 通常の非クラスタ化インデックス向き … 10000行データを 完全一意に分割 するようなキー または、 テーブル内の行の 1%以下に分割す るようなキー 列のほぼすべてを必要とするクエリ 選択度 必要とする列 26 「選択度」・・・カーディナリティとも言い、列の値のレコード数に対する 度合い(多い・少ない)のこと。例えば、健康診断データでは、性 別や血液型は選択度が低く、身長や体重は選択度が高い。 3.インデックスの設計基準 - インデックス全般
  27. 27. /36 インデックス全般の設計ポイント(1/2) • 条件や集計のキーになる列でも、更新頻度の高い列は安易にインデックスのキーに しない。 • データ変更時のパフォーマンスも考慮し、インデックスのキーを選定する。 ※参考:SQL Server Indexes (https://www.linkedin.com/pulse/sql-server-indexes-davide-mauri/) YET ANOTHER BRAIN「SQL Serverのインデックス設計基準」 (http://takumayokoo.blogspot.com/2011/02/sql-server_26.html) 27 O‘Reilly Japan, Inc. 『SQLアンチパターン 目次』より 3.インデックスの設計基準 - インデックス全般
  28. 28. /36 Microsoftのガイドラインで重要な点(1/2) • クエリの述語や結合条件で頻繁に使用される列に対して非クラスター化イン デックスを作成する。 • ただし、不要な列を追加しないようにする。 • インデックス列を追加しすぎると、必要なディスク領域が増え、インデック スのメンテナンスのパフォーマンスも低下する可能性があるため、インデック スの列数はできる限り抑える。 • 更新の必要が少なく、容量の大きいデータベースまたはテーブルの場合、ク エリのパフォーマンスを向上させるには非クラスター化インデックスを多数作成 するのが適している。 • 適切に定義されたデータのサブセットに対してフィルター選択されたイン デックスを作成することを検討 • テーブルの更新頻度が高いOLTPアプリケーションでは、インデックスを過度に 作成することは勧めない。 ※参考:MS TechNet「非クラスタ化インデックスの設計ガイドライン」 (https://technet.microsoft.com/ja-jp/library/ms179325(v=sql.105).aspx) 28 3.インデックスの設計基準 - 非クラスタ化インデックス
  29. 29. /36 Microsoftのガイドラインで重要な点(2/2) • データがどのようにアクセスされるかを理解し、次に示す特徴があるクエリには 非クラスター化インデックスを使用することを検討する。 • JOIN 句または GROUP BY 句を使用している。 • 大きな結果セットを返さないクエリ。 • 完全一致を返すクエリの検索条件 (WHERE 句など) に頻繁に使用 される列を含んでいる。 • 次に示す特徴に 1 つ以上該当する列を考慮する。 • クエリを包括している。 • 姓と名の組み合わせなど、多数の異なる値が格納されている。(他の列 にクラスター化インデックスが使用されている場合) ※参考:MS TechNet「非クラスタ化インデックスの設計ガイドライン」 (https://technet.microsoft.com/ja-jp/library/ms179325(v=sql.105).aspx) 29 3.インデックスの設計基準 - 非クラスタ化インデックス
  30. 30. /36 患者ID 性別 ・・・ 1 男性 ・・・ 2 女性 ・・・ ・・・ 患者ID 性別 ・・・ 10000 女性 ・・・ 10001 男性 ・・・ ・・・ 非クラスタ化インデックスの設計ポイント • 安易に非クラスタ化インデックスを作成しない。 • 選択度が低い列をキーにすると、インデックスで絞り込んだ結果のデータ行が多くなり、場 合によってはインデックスを経由するよりテーブルスキャンの方が速くなる。 • カバーリングインデックス、付加列インデックスを使い分ける。 • 取得する列と条件に必要な列のみで範囲検索できる、かつ、更新頻度が低い場合は、カ バーリングインデックスを検討する。 • 条件に必要な列のみで範囲検索できる、かつ、更新頻度が低い場合は、条件に必要な 列をキー、取得する列を付加列とした付加列インデックスを検討する。 ※参考:YET ANOTHER BRAIN「SQL Serverのインデックス設計基準」 (http://takumayokoo.blogspot.com/2011/02/sql-server_26.html) 30 ルートノード 中間ノード 中間ノード リーフノード リーフノード リーフノード … … インデックスの絞り込み結果が 全行に渡る範囲で散らばって いると、ほぼ全データファイルを 参照するため、テーブルスキャ ンの方が速い場合もある。 3.インデックスの設計基準 - 非クラスタ化インデックス
  31. 31. /36 Microsoftのガイドラインで重要な点(1/2) • ほとんどの場合、各テーブルには、次の条件を満たす単一または複数の列に 基づいて定義されたクラスタ化インデックスを作成することを推奨。 • 頻繁に使用されるクエリに使用可能。 • 一意性が高い。 • 範囲クエリで使用可能。 • データがどのようにアクセスされるかを理解し、次の処理を行うクエリには、クラ スタ化インデックスを使用することを検討する。 • BETWEEN、>、>=、<、および <= などの演算子を使用して、ある 範囲の値を返す。 • 大きな結果セットを返す。 • JOIN 句を使用する。通常、これらは外部キー列になる。 • ORDER BY 句または GROUP BY 句を使用する。 ※参考:MS TechNet「クラスタ化インデックスの設計ガイドライン」 (https://technet.microsoft.com/ja-jp/library/ms190639(v=sql.105).aspx) 31 3.インデックスの設計基準 - クラスタ化インデックス
  32. 32. /36 Microsoftのガイドラインで重要な点(2/2) • キーの定義に使用する列はできるだけ少なくする必要があるため、次の 1 つ 以上の条件を満たす列を使用する。 • 一意な値または多数の異なる値を含む。 • 順次アクセスされる。 • テーブル内で一意であることが確実なため、IDENTITY として定義さ れている。 • テーブルから取得したデータの並べ替えに頻繁に使用される。 ※参考:MS TechNet「クラスタ化インデックスの設計ガイドライン」 (https://technet.microsoft.com/ja-jp/library/ms190639(v=sql.105).aspx) 32 3.インデックスの設計基準 - クラスタ化インデックス
  33. 33. /36 クラスタ化インデックスの設計ポイント(1/2) • データが物理的にかたまっていてほしい単位を表す列をキーとする。 • 「日付」「顧客」「商品カテゴリ」など『データが物理的にかたまっていてほしい単位を表す 列』から全ての仕様を考慮して、最重要なデータの順番をクラスタ化インデックスにすべき。 ※参考:YET ANOTHER BRAIN「SQL Serverのインデックス設計基準」 (http://takumayokoo.blogspot.com/2011/02/sql-server_26.html) 33 受注ID 計上年月 受注日 顧客ID ・・・ ・・・ 10001 2019/4 2019/4/19 10 ・・・ 10002 2019/5 2019/4/26 2 ・・・ 10003 2019/4 2019/4/25 10 ・・・ 10004 2019/4 2019/4/25 8 10005 2019/5 2019/4/26 13 10006 2019/4 2019/4/27 4 10007 2019/4 2019/4/30 1 10008 2019/5 2019/4/30 17 ・・・ 「受注ID」がキーのクラスタ化インデックのスリーフノード(データ行) 計上月での集計では、 日付でかたまっていること が望ましい 顧客ごとでの集計では、 顧客IDでかたまっている ことが望ましい 3.インデックスの設計基準 - クラスタ化インデックス
  34. 34. /36 クラスタ化インデックスの設計ポイント(2/2) • 安易にテーブルの主キーをクラスタ化インデックスのキーにしない。 • 主キーは代理キー(サロゲートキー)であることも多く、主キーを範囲検索で使うことは、 殆ど(もしくは全く)無い。 • 主キーでクラスタ化インデックスを設定してしまうと、範囲検索に殆ど使われないにもかかわ らず、データが主キーの順番で並ぶことになり、範囲検索ではパフォーマンスが悪くなる。 • 仕様理解が深まったタイミングなどで、再検討することを推奨。 ※参考:YET ANOTHER BRAIN「SQL Serverのインデックス設計基準」 (http://takumayokoo.blogspot.com/2011/02/sql-server_26.html) 34 3.インデックスの設計基準 - クラスタ化インデックス O‘Reilly Japan, Inc. 『SQLアンチパターン 目次』より そもそも、すべてのテーブルに代 理キー(サロゲートキー)を用 いる設計はアンチパターンの可 能性があります。
  35. 35. 4. さいごに 35
  36. 36. /36 3.インデックスの設計基準 - 実際に有効か確認する 36 SQL Serverは、インデックスの定義などのスキーマ情報だけでなく、各テーブル のデータ量やテーブル内のキーの値の偏りなどの統計情報も考慮して、オプティマ イザがインデックスの使用有無を含む「実行計画」を作成し、DBにアクセスします。 よって、想定するデータ量や値の偏りのあるテストデータを用いて、使用するクエリ の「実行時間」と「実行計画」を取得し、設計したインデックスが有効に機能する か確認することが大切です。 ※「実行計画」の取得方法の参考 Markus Winand氏「開発者のためのSQLパフォーマンスの全て」の「実行計画」-「SQL Server」 • https://use-the-index-luke.com/ja/sql/explain-plan/sql-server
  37. 37. ご清聴ありがとうございました
  38. 38. /36 ちなみに。。。 現在、デンソークリエイトでは二つのツールを市販化しており、 クラウドやインフラ系に強い技術者も募集しております! 38 www.timetracker.jp www.lightning-review.com 容易な工数入力+柔軟なプロジェクト管理 =データをカイゼンに活用 指摘箇所は画面キャプチャー で登録するだけ!

×