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

Similar documents
Microsoft Word - Circular-Memory-Leak_Mitigation

Microsoft Word - Manage_Add-ons

Microsoft Word - Per-Site_ActiveX_Controls

Office 365監査ログ連携機能アクティブ化手順書

Microsoft Word - Improved_Protected-Mode_API_Support

Microsoft Word - W3C's_ARIA_Support

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

Microsoft Word - User-Agent_String_and_Version_Vector

Microsoft Word - Outlook 2003 Senario.doc

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

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

Microsoft Word - Outlook Web Access _IE7_ Scenario.doc

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

著作権 このドキュメントに記載されている情報は このドキュメントの発行時点におけるマクロソフトの見解を反映したものです マクロソフトは市場の変化に対応する必要があるため このドキュメントの内容に関する責任を問われないものとします また 発行日以降に発表される情報の正確性を保証できません このホワトペ

2 マイクロソフトサーバー製品のログ監査ガイド 注意事項 : マイクロソフト ( 米国 Microsoft Corporation 及び同社が直接または間接に所有する法人を含みます 以下同じ ) は 本書の内容及び本書を使用した結果について明示的にも黙示的にも一切の保証を行いません また マイクロソ

PA4

Polycom RealConnect for Microsoft Office 365

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

Project Professional 2013 プレビュー

( 目次 ) 1. はじめに 開発環境の準備 仮想ディレクトリーの作成 ASP.NET のWeb アプリケーション開発環境準備 データベースの作成 データベースの追加 テーブルの作成

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

Chapter Two

Caché SQL に関するよくある質問

著作権 このドキュメントに記載されている情報 (URL 等のインターネット Web サイトに関する情報を含む ) は 将来予告なしに変 更することがあります 別途記載されていない場合 このソフトウェアおよび関連するドキュメントで使用している会社 組 織 製品 ドメイン名 電子メールアドレス ロゴ 人

PowerPoint Presentation

Microsoft Word - Versioning_and_Internet_Explorer_Modes

Visual Studio 2017 RC インストール & ファーストステップガイド 2016 年 11 月 16 日 (V1.0)

プレポスト【問題】

Microsoft Word - Outlook 2007 Senario.doc

データベース暗号化ツール「D’Amo」性能検証

Microsoft Word - Data_URI_Support

PSQL v12 新機能のご紹介 ~ 認証要件変更に伴う運用の見直し ~ 株式会社エージーテック 2015 年 1 月 13 日

本書はクラウド型 Dynamics CRM Online に基づいておりますが 設置型の Dynamics CRM 2013 についてもほぼすべての内容が適用できます 本書は 2013 年 10 月執筆時点での Dynamics CRM Online 製品リリース版に基づ いており 機能強化などによ

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

Microsoft Word - tutorial3-dbreverse.docx

著作権 このドキュメントに記載されている情報 URL 等のインターネット Web サイトに関する情報を含む は 将来予告なしに変 更することがあります 別途記載されていない場合 このソフトウェアおよび関連するドキュメントで使用している会社 組 織 製品 ドメイン名 電子メール アドレス ロゴ 人物

1

Microsoft Partner Network Yammer モバイル利用ガイド 2015 年 8 月

アーカイブ機能インストールマニュアル

Silk Central Connect 15.5 リリースノート

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

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

Oracle Enterprise Linux 5における認証

Microsoft PowerPoint pptx

PowerPoint プレゼンテーション

OpenLAB Data Store Release Notes

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

InfiniDB最小推奨仕様ガイド

Microsoft Word - JDBC検証 docx

この文書が翻訳版の場合 オリジナル版と内容に違いが認められた場合にはオリジナル版に従うものとします 記載された情報は発行日時点のものです この文書に記載されている URL や参照しているウェブサイトを含む情報や見解は 予告なく変更される場合があます 断りがない限り 例として記載されている企業 組織

システム管理者ガイド GIGAPOD 3 システム管理者ガイド - 負荷分散構成 第 1.01 版 2013 年 3 月 改訂履歴 No バージョン 日付 作成者 改訂者 補足 /09 トライポッドワークス 初稿 /03 トライポッドワークス cr

Microsoft Word - gtoss_e-Learning_system_operating_manual_ja_ver1.2.docx

テキスト中の表記について 画面中に表示される文字の表記ウィンドウ ボタン メニューなど 画面に表示される文字は [] で囲んで表記しています 画面上に表示される選択肢や 入力する文字については で囲んで表記しています ディレクトリの表記本テキストではファイルのパスを表す際 すべてデフォルトのインスト

目次 更新履歴... 1 はじめに... 3 レコードセット?... 3 準備... 5 SQL でデータを取得する... 6 データのループ処理... 7 列の値を取得する... 7 対象行を変更する (MoveFirst, MoveNext, MovePrevious, MoveLast)...

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

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

アーカイブ機能インストールマニュアル

CLUSTERPRO X for Windows PPガイド

Chapter Two

目次 Discoveries InSite について InSite ポータルの特徴と搭載される機能 社内ポータルサイトを作成する InSite にサインインする 社内ポータルサイトを作成する 社内ポータルサイトを変更す

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

はじめにお読みください

導入設定ガイド

ホームページ・ビルダー サービス「ライトプラン」

PowerPoint プレゼンテーション

AIP2016R2 DC backup_restore

Oracle Cloud Adapter for Oracle RightNow Cloud Service

セットアップの流れ Graphtec Pro Studio を使用する SAi Cloud へのユーザー登録 1-1 SAi Cloud へのユーザー登録 Graphtec Pro Studio のインストール 1-2 Graphtec Pro Studio のインストール Cutting Mast

クエリの作成が楽になるUDF

iNFUSE インフューズ

CONTENTS マニュアルの表記... S01-02_01 1.DataNature Smart 全体概要図... S01-02_11 2. 基本操作... S01-02_ ジョブの作成... S01-02_21 加工条件設定... S01-02_21 Step1: 処理対象データの指

Compliance Guardian 3 SP3 Release Notes

Oracle Web CacheによるOracle WebCenter Spacesパフォーマンスの向上

TRENDフォトビューアの起動方法と使い方

Microsoft PowerPoint - db03-5.ppt

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

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

DataSpider JDBC Proxy Server インストールガイド (DataSpider JDBC Proxy Server Install Guide) ドキュメント リリース日 :2017 年 6 月 30 日 ( 第 1 版 ) Copyright 2017 APPRESSO K.

<4D F736F F D D836A B ED28CFC82AF814593FA967B8CEA816A817A2E646F63>

アプリケーション補足説明書(Office2003)

Enterprise Cloud + 紹介資料

ファクス送信用変換ソフト 操作説明書_UA

Oracle Database 10g Release 2を使用したデータベース・パフォーマンス

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

Slide 1

iStorage ソフトウェア VMware vCenter Plug-in インストールガイド

ホームページ・ビルダー サービス「ライトプラン」

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

1 はじめに 概要 特徴 動作環境 本マニュアルの見かた 用語集 プロファイルについて 制約事項 ライセンス認証 ( プロファイルのインストール ) を行う..

PDF Convertor for mac スタートアップガイド

データベースアクセス

TRENDフォトビューアの起動方法と使い方

アプリケーション補足説明書(Office2003)Microsoft(R) Office 2003 Editions

開発・運用時のガイド JDK8への移行に伴う留意点 [UNIX]

書類閲覧用 端末要件 令和元年 5 月 金融庁企画市場局企業開示課

アプリケーション補足説明書Microsoft(R) Office 2003 Editions

インテル® Parallel Studio XE 2019 Composer Edition for Fortran Windows 日本語版 : インストール・ガイド


今さら聞けない!?大規模テーブルのパフォーマンスチューニング ~パーティショニング~

NEC COBOL SQL アクセス Server Runtime V1.0 COBOL SQL アクセス Server Runtime V1.0 (1 年間保守付 ) COBOL SQL アクセス Server Runtime V1.0 (1 年間時間延長保守付 ) セットアップカード SL438

Transcription:

2 - SQL の最適化

このドキュメントに記載されている情報 (URL 等のインターネット Web サイトに関する情報を含む ) は 将来予告なしに変更することがあります このドキュメントに記載された内容は情報提供のみを目的としており 明示または黙示に関わらず これらの情報についてマイクロソフトはいかなる責任も負わないものとします お客様が本製品を運用した結果の影響については お客様が負うものとします お客様ご自身の責任において 適用されるすべての著作権関連法規に従ったご使用を願います このドキュメントのいかなる部分も 米国 Microsoft Corporation の書面による許諾を受けることなく その目的を問わず どのような形態であっても 複製または譲渡することは禁じられています ここでいう形態とは 複写や記録など 電子的な または物理的なすべての手段を含みます マイクロソフトは このドキュメントに記載されている内容に関し 特許 特許申請 商標 著作権 またはその他の無体財産権を有する場合があります 別途マイクロソフトのライセンス契約上に明示の規定のない限り このドキュメントはこれらの特許 商標 著作権 またはその他の無体財産権に関する権利をお客様に許諾するものではありません 別途記載されていない場合 このソフトウェアおよび関連するドキュメントで使用している会社 組織 製品 ドメイン名 電子メールアドレス ロゴ 人物 出来事などの名称は架空のものです 実在する会社名 組織名 商品名 個人名などとは一切関係ありません 2010 Microsoft Corporation. All rights reserved. Microsoft SQL Server は 米国 Microsoft Corporation の米国およびその他の国における登録商標または商標です 記載されている会社名 製品名には 各社の商標のものもあります 1

目次 1. 本書の概要... 3 2. 環境作成... 3 3. 何故 SQL は遅延するのか?... 3 4. 遅延原因 1: インデックスが作成されていない... 4 4.1. カーディナリティ... 4 4.1.1. 実行プランの確認方法... 4 4.1.2. カーディナリティの低いカラムでのインデックス... 6 4.1.3. カーディナリティの低いカラムで有効なインデックス... 8 4.2. テーブルサイズ...10 4.2.1. 高度なインデックスの使用方法...10 4.2.2. カバリングインデックス...10 4.2.3. ソート用として使用... 11 5. 遅延原因 2: インデックスが使用されていない...13 5.1. SQL 文が適切に記載されていない...13 5.1.1. 関数を使用した SQL...14 5.1.2. 演算を使用した SQL...16 5.1.3. 暗黙の型変換がおこなわれている SQL...17 5.1.4. 後方一致検索の SQL...19 5.1.5.!= を使用した SQL...20 5.1.6. Is Null を使用した SQL...21 5.2. 最適ではない実行プランによる遅延...23 5.2.1. 統計情報と実行プラン...23 5.2.2. 実データと統計情報の値の乖離による遅延...23 6. チューニングサイクル...28 6.1. 情報収集...28 6.2. 分析...29 6.3. チューニング...29 6.4. テスト 評価...29 2

1. 本書の概要 本書は まだあまり開発経験のないアプリケーション開発者が SQL を最適に保つための SQL の書き方や インデックスを効率的に使用する方法についてまとめています 2. 環境作成 本書で使用するデータベース及びテーブル インデックスは 以下となります CREATE DATABASE DB_Test GO USE DB_Test GO CREATE TABLE T_Emp( ID int NOT NULL, Name Varchar(20), Status Varchar(1), Flag tinyint NOT NULL, UpdDate Datetime, CONSTRAINT PK_ID PRIMARY KEY CLUSTERED(ID)) GO CREATE INDEX IX_Name on T_Emp(Name) CREATE INDEX IX_Status on T_Emp(Status) CREATE INDEX IX_Flag on T_Emp(Flag) CREATE INDEX IX_UpdDate on T_Emp(UpdDate) GO TRUNCATE TABLE T_Emp GO DECLARE @i int = 1 DECLARE @name varchar(10) WHILE @i <= 10000 BEGIN SET @name = 'Name' + RIGHT('000000'+ CONVERT(VARCHAR,@i),6) IF @i <= 9990 INSERT INTO T_Emp VALUES( @i,@name,1,0,getdate() ) ELSE INSERT INTO T_Emp VALUES( @i,@name,2,1,null ) SET @i += 1 END GO 3. 何故 SQL は遅延するのか? SQL Server や Oracle を始めとしたリレーショナルデータベースでは データを取得する際に SQL と呼ばれるデータベース言語を使用してデータベースにアクセスします データベースではその SQL を受け取って SQL を解析した後に値を返しますが この時に結果がなかなか返って来ないまま数十分から数時間が経過してしまった という経験をお持ちの方は多いのではないでしょうか では SQL は何故遅延するのでしょうか? SQL が遅延する原因は大きく分けて 2 つあります 1 つはサーバーなどのリソースによる遅延で もう 1 つが SQL による遅延です サーバーリソースによる遅延とは 接続ユーザー数やデータ量が想定外に増加してしまったことにより CPU 使用率の高騰やメモリー不足などサーバーが高負荷状態になり データベースサーバー自体の処理が 3

追いつかなくなってしまうようなケースで アプリケーション開発段階で考慮することが難しい現象と言えます 一方 SQL による遅延とは SQL 実行時に SQL 側に問題がある為大量データの読み込みなどが発生し SQL の遅延を誘発してしまうケースです このような遅延はほとんどの場合がアプリケーション開発時に防げるものであり アプリケーション開発者はデータの読み込み量を抑え 遅延が発生しないように心掛けて開発する必要があります さもないと 運用開始後に遅延が発生してアプリケーションの改修作業が発生するだけでなく アプリケーションのテストやリリース作業 リリース後の監視から評価まで多大な作業工数がかかってしまうことになります では 大量の読み込みとはどのようなことが原因で発生してしまうのでしょうか? 4. 遅延原因 1: インデックスが作成されていない 大量の読み込みが発生する原因として最も多いのが 適切にインデックスが作成されてない為フルスキャンしてしまうケースです SQL には特定の行を取得する際に WHERE 句を使用して条件を指定しますが 1000 万件のテーブルに対して 1 件を抽出するような SQL を実行した場合 インデックスがないと 1000 万件のデータ全てを読み込んでしまうことになります この為 遅延している SQL の条件句にインデックスを作成することで読み込み数は大幅に改善することができます では インデックスは条件句に指定された全てのカラムに作成すればよいかというとそうではありません インデックスはあまり作成しすぎると更新負荷が高くなってしまい 同時実行性が低下してしまう可能性がある為 作成しすぎには注意が必要です そして インデックスを効果的に作成する際のポイントとしては以下 2 つがあります カーディナリティ データ量 4.1. カーディナリティインデックスを作成する場合 最も考慮すべきはその項目がカーディナリティが高いかどうかという点です カーディナリティとは値の種類のことで 性別のように男女 2 種類しかないようなカラムの場合 カーディナリティが低いといい 逆に 顧客番号のようにユニークな値を格納するカラムの場合 カーディナリティが高いといいます カーディナリティが低いカラムに対してインデックスを作成しても データベースはインデックスを使用せずにテーブルフルスキャンを選択してしまいます この点を SQL Server で実際に確認してみましょう この点を確認するには SQL の実行プランを見る必要があります 以下 実行プランの確認方法になります 4.1.1. 実行プランの確認方法 実行プランとは データベースにアクセスする時のアクセス方法や順番のことです 今回は Microsoft SQL Server Management Studio を使用して実行プランを確認します Microsoft SQL Server Management Studio を起動し SQL Server に接続 4

新しいクエリ をクリック 実際の実行プランを含める を押す SQL 文を記載 実行 ボタンを押しクエリを実行 実行プランタブをクリックして実行プランを表示 実行プランの見方は以下になります SQL クエリアナライザのグラフィカルな実行プランの出力は 右から左 上から下に読みます 分析されたバッチ内の各クエリが表示されます 各クエリのコストも バッチの総コストに占める割合として表示されます 5

実行プランにマウスを置くと 詳細が表示 4.1.2. カーディナリティの低いカラムでのインデックスそれでは カーディナリティが低いカラムだとインデックスが使用されないことを確認してみます 今回は T_Emp というテーブルの Flag カラムに 0 と 1 の 2 種類の値を 5000 件ずつ格納して SELECT 文を実行します T_Emp テーブルへのデータ挿入 TRUNCATE TABLE T_Emp GO DECLARE @i int = 1 DECLARE @name varchar(10) WHILE @i <= 10000 BEGIN SET @name = 'Name' + RIGHT('000000'+ CONVERT(VARCHAR,@i),6) IF @i <= 5000 INSERT INTO T_Emp VALUES( @i,@name,1,0,getdate() ) ELSE INSERT INTO T_Emp VALUES( @i,@name,2,1,null ) SET @i += 1 END GO 6

Status の件数確認 SELECT Flag,COUNT(*) GROUP BY Flag SQL/ 実行プラン WHERE Flag = 0 実行プラン 1. PK_ID を Clustered Index Scan で参照 T_Emp テーブルの Flag というカラムにはインデックス (IX_Flag) が作成されていますが 実行プランを見るとそのインデックスではなくプライマリキー (PK_ID) だけが参照されているのがわかります この PK_ID というプライマリキーは クラスタインデックスというインデックスで T_Emp テーブルそのもののデータが格納されているインデックスになります ( 1) そして 実行プランに Index Scan とあり この Index Scan が PK_ID を全件読み込んだことがわかります つまり この実行プランは PK_ID というプライマリキー ( T_Emp テーブル ) をフルスキャンした ということになります 7

1. クラスタインデックスクラスタインデックスとは リーフブロックにポインタではなく実データを格納しているインデックスのことです 通常のインデックスは リーフブロックにテーブルへのポインタを格納していますが クラスタインデックスはポインタではなく実データをそのまま格納しています この為 プライマリキーを指定してテーブルデータを SELECT するような SQL で有効なインデックスと言えます SQL Server では プライマリキーを作成すると元々存在していたテーブルデータが削除され 全てのテーブルデータがプライマリキー内に格納されるようになります 4.1.3. カーディナリティの低いカラムで有効なインデックスでは カーディナリティの低いカラムにはインデックスをつける必要はないかというとそうとは限らないケースがあります それは インデックスを使用して数件のデータを抽出するような SQL です 例えば 先ほどの Status の件数が 0 が 9,990 件 1 が 10 件格納されていたとします この時に 1 の値を抽出する SELECT 文を実行した場合 10,000 件中 10 件を取得することになる為 インデックスを使用した方がコストが低いと判断されます データ作成 TRUNCATE TABLE T_Emp GO DECLARE @i int = 1 DECLARE @name varchar(10) WHILE @i <= 10000 BEGIN SET @name = 'Name' + RIGHT('000000'+ CONVERT(VARCHAR,@i),6) IF @i <= 9990 INSERT INTO T_Emp VALUES( @i,@name,1,0,getdate() ) ELSE INSERT INTO T_Emp VALUES( @i,@name,2,1,null ) SET @i += 1 END GO Status の件数 SELECT Flag,COUNT(*) GROUP BY Flag 8

SQL/ 実行プラン WHERE Flag = 1 実行プランステップ 1. IX_Flag インデックスを Index Seek で参照 2. その結果と PK_ID キーを Nested Loops で結合 上記実行プランを見ると IX_Flag が Index Seek という実行プランで読み込まれているのが分かります Index Seek は条件に指定された値のみ抽出した場合の実行プランであり 今回の場合は 10 件のみ抽出したことになります その後で T_Emp テーブルをその 10 件と Nested Loops で結合し 結果を返しています このように カーディナリティが低いカラムであってもインデックスを使用することで数件まで絞り込める場合 インデックスが使用され 不要な読み込みを回避することができます 9

4.2. テーブルサイズインデックス作成時に考慮すべきもう 1 つのポイントとしてテーブルのサイズがあります インデックスはテーブルサイズが大きいほど効果が高くなります 例えば 100 件の中から 1 件を抽出するのであれば全テーブルデータを参照してもインデックスを使用しても読み込み数や処理時間はそれほどかわりません ですが 100 万件の中から 1 件のデータを抽出する場合 全データを参照してしまうと 読み込みが大量に発生してしまいます このようなテーブルのデータを抽出する際はインデックスを使用することで効率的にデータを取得することができます また 1 行のサイズが大きい場合も テーブルサイズが大きくなる為フルスキャンのコストが高くなってしまいます 例えば 1 行のレコード長が 10bytes のテーブルと 1KB のテーブルでは同じ行数でもテーブルのサイズが全く異なり 当然フルスキャン時のコストも高くなってしまいます このようなテーブルに対してはインデックスの作成を検討した方がよいと言えます 4.2.1. 高度なインデックスの使用方法以上のように 条件句に指定されているカラムと カーディナリティやデータ量を考慮することで効果的なインデックスを作成することができます ですが さらに 以下のようなインデックスを作成することで インデックスをより効果的に使用することができます 4.2.2. カバリングインデックスカバリングインデックスとは SELECT 文で使用する全てのカラムをインデックスに含めることでパフォーマンスを改善させるチューニングテクニックの 1 つです 例えば 以下のような Flag カラムを条件句に指定した場合 実行プランは Flag のインデックスを参照した後で Name 列の値を取得する為 テーブルを参照する必要があります SQL/ 実行プラン SELECT Name WHERE Flag = 1 10

実行プランステップ 1. IX_Flag インデックスを Index Seek で参照 2. その結果と PK_ID キーを Nested Loops で結合 Flag のインデックス (IX_Flag) が使用されている為高速に処理されていますが IX_Flag インデックスに Name 列がない為 Name を取得する為にテーブルを参照してしまっています この為 この SQL をより効率的に処理させたい場合 SELECT 句にある項目も全てインデックスに含めることで テーブルデータの読み込みを減らすことができ 処理時間も短縮させることができます CREATE INDEX IX_Flag_Name on T_Emp(Flag,Name) GO SQL/ 実行プラン SELECT Name WHERE Flag = 1 実行プランステップ 1. IX_Flag_Name インデックスを Index Seek で参照 4.2.3. ソート用として使用インデックスは値が小さい順に並んでいる為 order by 句のようなソート処理が実行される SQL の場合 そのカラムにインデックスを作成しておくことでソート時の負荷が低くなり処理を高速化させることができます 以下 カバリングインデックスと同様の手順で確認してみます ( カバリングインデックスの項で作成したインデックスは削除して下さい ) 11

SQL/ 実行プラン SELECT Name WHERE Flag = 1 ORDER BY Name 実行プランステップ 1. IX_Flag インデックスを Index Seek で参照 2. その結果と PK_ID キーを Nested Loops で結合 3. Sort 処理実行 ORDER BY を使用している為 テーブルデータとインデックスを結合した後 Sort 処理が実行されているのがわかります この為 この Sort 処理のカラムもインデックスに追加すると ソート処理が回避できる為高速に処理されます CREATE INDEX IX_Flag_Name on T_Emp(Flag,Name) GO SQL/ 実行プラン SELECT Name WHERE Flag = 1 ORDER BY Name 12

実行プランステップ 1. IX_Flag_Name を Index Seek で参照 Flag と Name の複合インデックスを作成することで テーブルへのアクセスと Sort 処理が回避され 作 成されたインデックスのみで処理されていることがわかります 5. 遅延原因 2: インデックスが使用されていない インデックスを作成することで 多くの SQL 遅延は改善されますが 遅延が解消されないケースがあります それは インデックスはあるのに使用されていないようなケースです 具体的に言うと SQL が適切に記載されていないケースと 実行プランが最適でない場合です 5.1. SQL 文が適切に記載されていない 一般的に以下のような SQL ではインデックスが作成されていても使用することができません この為 こ のような SQL 文をできるだけ記述しないよう注意して SQL を記述する必要があります 1. 関数を使用した SQL 2. 演算を使用した SQL 3. 暗黙の型変換がおこなわれている SQL 4. 後方一致検索の SQL 5.!= を使用した SQL 6.Is Null を使用した SQL 5,6 については SQL Server の場合インデックスが使用されます これらについて SQL Server で実際に確認しながら見ていくことにしましょう 13

5.1.1. 関数を使用した SQL 条件句に関数を使用したカラムを指定して実行すると インデックスが使用されず全件検索になってしまいます 以下では SUBSTRING 関数を使用して Name 列の頭 6 文字が Name01 という文字列を検索しています 遅延 SQL WHERE SUBSTRING(Name,1,6) = 'Name01' SQL/ 実行プラン 実行プランステップ 1. IX_Name インデックスを Index Scan で参照 2. その結果と PK_ID キーを Nested Loops で結合 インデックススキャンとあるので インデックスが正しく使われているように見えますが Index Scan は インデックスの全データをスキャンする実行プランになります そして その中から条件に該当するデータ を取得し その結果と PK_ID キーを Nested Loops で結合しています SQL の最適化この SQL をインデックスが使用されるよう記述する場合 カラムに対して関数を使用しないように書き換える必要があります 今回の場合 SUBSTRING 関数で 1 文字目から 6 文字のデータを取得してその値と文字列を比較していますので 以下のように Like 検索に変更することで同等の結果を取得することができ インデックスも使用することができます 14

変更 SQL/ 実行プラン WHERE Name Like 'Name01%' 実行プランステップ 1. X_Name インデックスを Index Seek で参照 2. その結果と PK_ID キーを Nested Loops で結合 上記を見ると IX_Name に対する Index Scan だった実行プランが Index Seek に変わっています Index Seek は 条件に指定された値のみデータを抽出した場合の実行プランです ( 内部的には SQL が範囲検索の SQL 文に変換されています ( 2)) そして Index Seek で抽出した結果は PK_ID と Nested Loops で結合され その結果が返されています つまり IX_Name インデックスを使用して データを抽出しているということができます 2. 範囲指定に変換されたことは Index Seek の詳細を見ることで確認することができます 15

5.1.2. 演算を使用した SQL インデックスが作成されたカラムに対して演算処理を行うと インデックスが使用されません 以下は ID をマイナス 100 した値が 0 より小さいデータを抽出しています SQL/ 実行プラン WHERE ID - 100 < 0 実行プランステップ 1. ID キーを Clustered Index Scan で参照 先ほどの SQL と同じように Index Scan なので インデックスの全データをスキャンした後 条件に指定 したデータを抽出しています SQL の最適化 本 SQL のように左辺の ID を演算するのではなく 右辺の 0 の値に 100 をプラスするように書き換え ることでカラムに対する演算を回避でき インデックスも使用されます 変更 SQL/ 実行プラン WHERE ID < 0 + 100 16

実行プランステップ 1. PK_ID キーを Index Seek で参照 上記を見ると 実行プランが Index Scan から Clustered Index Seek に変わっていて 条件に指定され た値のみ参照していることがわかります これにより インデックスの不要な読み込みを抑えることができ ます 5.1.3. 暗黙の型変換がおこなわれている SQL 暗黙の型変換 ( 文字列型から数値型に変換 ) されているような場合 インデックスは使用されません #SQL Server の場合 数値型から文字列型に暗黙の型変換される場合は インデックスが使用されます SQL/ 実行プラン WHERE Status = 2 17

実行プランステップ 1. PK_ID キーを Clustered Index Scan で参照本 SQL は T_Emp テーブルの Status の値が 2 のデータを抽出しています Status のカラムは文字列型であり 指定した値は数値で検索している為 このまま実行してしまうと暗黙的に SQL が変換され インデックスが使用されない SQL で実行されてしまいます 上記の通り Status 列を CONVERT_IMPLICIT 関数を使用して数値型に変換しています これによりフル スキャンが実行されてしまいます SQL の最適化 本 SQL は暗黙の型変換が発生しないようシングルクォートで囲むことでインデックスが使用されるように なります SQL/ 実行プラン WHERE Status = '2' 18

実行プランステップ 1. IX_Status インデックスを Index Seek で参照 2. その結果と PK_ID キーを Nested Loops で結合 上記を見ると IX_Status の Index Seek で実行されており 適切にインデックスを使用していることが わかります 5.1.4. 後方一致検索の SQL 先に確認した前方一致検索であればインデックスは使用されますが 後方一致検索ではインデックスが使用 されません 本 SQL は Name の後ろから 3 文字が 123 のデータを抽出しています SQL/ 実行プラン WHERE Name Like '%123' 19

実行プランステップ 1. IX_Name インデックスを全データ参照 2. PK_ID キーと Nested Loos を全データ参照 本 SQL は IX_Name インデックスをフルスキャンした後 後ろ 3 文字が 123 のデータを抽出しています 後方一致検索の場合 インデックスを使用するように変更することができません この為 この SQL を高速に処理する必要がある場合 別の条件を追加できないか 全文検索インデックスで代用可能か などを検討する必要があります 5.1.5.!= を使用した SQL!= (Not Equal 検索 ) で検索した場合 Oracle ではインデックスが使用されませんが SQL Server の場合 インデックスが使用されるケースがあります それは インデックスを使用した方がフルスキャンよりコストが低いと SQL Server が判断した場合です SQL/ 実行プラン (10 件取得 ) WHERE Flag!= 0 実行プランステップ 1. IX_Flag インデックスを参照 2. その結果と PK_ID キーを Nested Loops で結合 20

SQL/ 実行プラン (9,990 件取得 ) WHERE Flag!= 1 実行プランステップ 1. PK_ID キーを Clustered Index Scan で参照 上記のように!= を使用した結果が 10,000 件中 10 件を取得するような結果の場合 インデックスが使 用されます 逆に 9,990 件取得する場合 テーブルを全件参照した方が速いと判断してフルスキャンが 実行されます 5.1.6. Is Null を使用した SQL SQL Server の場合 Is Null を使用してもインデックスが使用されるケースがあります これも!= 検索と同様 インデックスを使用した方がフルスキャンより高速に処理可能と SQL Server が判断した場合に使用されます SQL/ 実行プラン (NULL データ抽出 :10 件 ) WHERE UpdDate Is Null 21

実行プランステップ 1. IX_UpdDate インデックスを Index Seek で参照 2. その結果と PK_ID キーを Nested Loops で結合 SQL/ 実行プラン (NOT NULL のデータ抽出 :9,990 件 ) WHERE UpdDate Is Not Null 実行プランステップ 1. PK_ID キーを Clustered Index Scan で参照 22

5.2. 最適ではない実行プランによる遅延以上の SQL は インデックスが使用されるよう SQL 文を書き換えればパフォーマンスが改善される可能性が高いものでした ですが SQL を書き換えてインデックスが使用される SQL を記述してもインデックスが使用されないケースがあります それは データベースが作成した実行プランが最適ではないケースです 実行プランとは データベースにアクセスする時のアクセス方法や順番のことで 具体的に言うと 複数のテーブルを指定した SQL が実行された際に どのテーブルから参照するか どのインデックスを使用するか どのような結合方法で実行するかを解析した結果のことです データベースでは 幾つかの実行プランを作成した後で その中から最も高速に処理することができる実行プランを選択し実行します このような実行プランの作成や選択はオプティマイザというデータベースの頭脳とも言える箇所で行われています このオプティマイザが高速に処理可能と判断した実行プランが 実際に実行した時に遅い場合がある為 遅延が発生してしまうことになってしまいます そして このような遅延のほとんどが統計情報に問題があるケースになります 5.2.1. 統計情報と実行プラン統計情報とは 表や索引 カラムがどのような状態なのかを表している情報のことで 具体的には テーブルにデータが何件格納されているか 1 行の平均サイズはどのぐらいなのか カラムにはどのような値が多く格納されているのかなどの情報が格納されています SQL Server の統計情報では行数や平均キー長 ヒストグラムなどの情報が格納されています また インデックス作成時にインデックス列内の統計情報が作成され テーブル内のデータが更新されると統計情報も自動的に更新されます ( デフォルト ) 実行プランは SQL 文実行後 オプティマイザの解析処理で作成されます オプティマイザは解析時に複数の実行プランを作成し その中で最適な実行プランを選択していますが その基準となる情報が統計情報です この統計情報が実データと乖離しているような場合 誤った実行プランを選択してしまい処理が遅延してしまうことになります 例えば 1,000 万件のデータが格納されているテーブルに対して 10 件取得する SELECT 文を実行したとします この時に 統計情報が古くこのテーブルに 10 件しか格納されていないという情報になってしまっていた場合 フルスキャンの方がインデックスを参照するより高速に処理可能と判断し フルスキャンを選択してしまう可能性があります SQL Server ではデフォルトでは自動で統計情報を収集しているので このように実データと統計情報の値が乖離するようなことは多くないですが この機能を無効にしている場合や大量データを一度に更新した場合などにこのようなことになる可能性があります 5.2.2. 実データと統計情報の値の乖離による遅延統計情報による遅延について実際に SQL Server で確認してみます 今回は 現象を分かりやすくするために 10 件データ挿入時に統計情報を取得し その後で 20 万件挿入して実データと統計情報の値を乖離させて遅延の現象を再現させてみます 1. T_Emp のテーブルデータ作成今回は誤った統計情報を取得すると遅延してしまう現象を確認する為 自動で統計情報が取得されないよう 統計の自動更新 を無効にします 23

2. T_Emp のテーブルデータ作成 10 件のテーブルデータを作成します TRUNCATE TABLE T_Emp GO DECLARE @i int = 1 DECLARE @name varchar(10) WHILE @i <= 10 BEGIN SET @name = 'Name' + RIGHT('000000'+ CONVERT(VARCHAR,@i),6) INSERT INTO T_Emp VALUES( @i,@name,1,0,getdate() ) SET @i += 1 END GO 3. 統計情報取得 10 件格納時の統計情報を取得します 統計情報の手動取得は UPDATE STATISTICS コマンドを使用します UPDATE STATISTICS T_Emp IX_Flag 統計情報が取得されてるかどうか確認します 確認は DBCC SHOW_STATISTICS コマンドで確認することができます DBCC SHOW_STATISTICS('T_Emp','IX_Flag') 24

Rows が 10 となっていることから この統計情報ではテーブルデータが 10 行格納されていることになっています 実行プランを見ると PK_ID のフルスキャンが実行されていることがわかります WHERE Flag = 0 4. 20 万件のデータ作成 T_Status テーブルに 20 万件になるようデータを挿入します DECLARE @i int = 11 DECLARE @name varchar(10) WHILE @i <= 200000 BEGIN SET @name = 'Name' + RIGHT('000000'+ CONVERT(VARCHAR,@i),6) INSERT INTO T_Emp VALUES( @i,@name,2,1,getdate() ) SET @i += 1 END GO 25

件数確認 SELECT Flag,COUNT(*) GROUP BY Flag 5. 統計情報の確認 統計情報が更新されてないことを確認します DBCC SHOW_STATISTICS('T_Emp','IX_Flag') 6. SELECT 文実行統計情報が 10 件でテーブルデータが 20 万件格納されている状態で 以下のような Flag を条件に 10 件取得する SQL 文を実行した時の実行プランを確認します WHERE Flag = 0 26

実行プランステップ 1. PK_ID キーを Clustered Index Scan で参照 実行プランを見ると Clustered Index Scan とあり PK_ID ( T_Emp テーブル ) のフルスキャンに なっていることがわかります 7. 統計情報を取得後再実行 統計情報を取得して 統計情報の値を最新の状態にしてから同様の SELECT 文を実行します UPDATE STATISTICS T_Emp IX_Flag DBCC SHOW_STATISTICS('T_Emp','IX_Flag') WHERE Flag = 0 27

実行プランステップ 1. IX_Flag インデックスを Index Seek で参照 2. その結果と PK_ID キーを Nested Loops で結合 このように テーブルデータと統計情報で同期が取れていないと オプティマイザが誤った実行プランを最適と判断してしまいます SQL Server では統計情報は自動更新の為 あまり意識する必要は有りませんが 大量データの更新処理等が実行された時は統計情報を取得して このような遅延処理が起きないよう気をつける必要があります 6. チューニングサイクル以上の点を考慮してアプリケーションを開発することで 運用が開始した後に処理遅延が発生する可能性も少なくなります 但し このように考慮して開発しても実際にはデータ量の増加により予想外に処理が遅延してしまうことがあります このようなことにならない為に 運用開始後に遅延している SQL を発見し対処する そしてまた監視 というようなチューニングサイクルを実施する必要があります チューニングサイクルのフェーズは以下の通りとなります チューニングサイクル 1. 情報収集 2. 分析 3. チューニング 4. テスト 評価 6.1. 情報収集 まず最初に データベースの稼働データや処理時間が長い SQL を取得します データベースの稼働データは稼働 状況の傾向を把握する為に常に取得しておく必要があります 28

具体的な情報の収集方法については 自習書の 監視ツールの基本操作 を参考にして下さい 参考 : http://www.microsoft.com/japan/sqlserver/2008/self-learning/default.mspx 6.2. 分析次に 取得した情報を分析します 分析は データ量や処理量の増加に伴いアプリケーションや SQL が遅延していないか データベースの全体で読み込み量やサーバーの CPU 使用率が増加していないかなど ボトルネックの原因を調査します 例えば 日々処理が遅延する SQL が確認された場合 テーブルのフルスキャンが実行されていないか データ量の増加に伴って読み込みが多くなる処理がないかなどをポイントにボトルネックを特定します 6.3. チューニング遅延原因が把握できたら 遅延を解消する為のチューニングを行います チューニングは本書で見てきたような観点 つまり インデックスが貼ることで改善できるか インデックスが使用されない SQL の書き方になってないか データと統計情報の値が乖離していないかなどを確認し チューニングを実施します 6.4. テスト 評価チューニングした結果をテストし効果を確認します 特に インデックスを作成するチューニングの場合 そのインデックスと同じカラムを参照している SQL にも影響してしまう可能性がある為 そのような SQL の実行プランも確認することが好ましいです また この処理がチューニングされたことにより 別の所で新たにボトルネックが発生する可能性がある為 引き続きデータを取得し 情報収集する必要があります 以上のチューニングサイクルを実施することで データベースのパフォーマンスを向上させ システムを安定的に運用させることができます 29