Comments
Description
Transcript
『パフォーマンス&チューニング・ガイド: オプティマイザと抽象プラン』
『パフォーマンス&チューニング・ガイド: オプティマイザと抽象プラン』 Adaptive Server® Enterprise 12.5.1 ドキュメント ID:DC31659-01-1251-01 改訂:2003 年 8 月 Copyright © 1989-2004 by Sybase, Inc. All rights reserved. このマニュアルは Sybase ソフトウェアの付属マニュアルであり、新しいマニュアルまたはテクニカル・ノートで特に示さ れないかぎりは、後続のリリースにも付属します。このマニュアルの内容は予告なしに変更されることがあります。この マニュアルに記載されているソフトウェアはライセンス契約に基づいて提供されるものであり、無断で使用することはで きません。 このマニュアルの内容を弊社の書面による事前許可を得ずに、電子的、機械的、手作業、光学的、またはその他のいかな る手段によっても、複製、転載、翻訳することを禁じます。 マニュアルの注文 マニュアルの注文を承ります。ご希望の方は、サイベース株式会社営業部または代理店までご連絡ください。マニュアル の変更は、弊社の定期的なソフトウェア・リリース時にのみ提供されます。 Sybase の商標 Sybase、Sybase のロゴ、AccelaTrade、ADA Workbench、Adaptable Windowing Environment、Adaptive Component Architecture、Adaptive Server、Adaptive Server Anywhere、Adaptive Server Enterprise、Adaptive Server Enterprise Monitor、 Adaptive Server Enterprise Replication、Adaptive Server Everywhere、Adaptive Server IQ、Adaptive Warehouse、Anywhere Studio、Application Manager、AppModeler、APT Workbench、APT-Build、APT-Edit、APT-Execute、APT-FORMS、APTTranslator、APT-Library、AvantGo、AvantGo Application Alerts、AvantGo Mobile Delivery、AvantGo Mobile Document Viewer、 AvantGo Mobile Inspection、AvantGo Mobile Marketing Channel、AvantGo Mobile Pharma、AvantGo Mobile Sales、AvantGo Pylon、AvantGo Pylon Application Server、AvantGo Pylon Conduit、AvantGo Pylon PIM Server、AvantGo Pylon Pro、Backup Server、BizTracker、ClearConnect、Client-Library、Client Services、Convoy/DM、Copernicus、Data Pipeline、Data Workbench、DataArchitect、Database Analyzer、DataExpress、DataServer、DataWindow、DB-Library、dbQueue、Developers Workbench、Direct Connect Anywhere、DirectConnect、Distribution Director、e-ADK、E-Anywhere、e-Biz Integrator、EWhatever、EC Gateway、ECMAP、ECRTP、eFulfillment Accelerator、Embedded SQL、EMS、Enterprise Application Studio、 Enterprise Client/Server、Enterprise Connect、Enterprise Data Studio、Enterprise Manager、Enterprise SQL Server Manager、 Enterprise Work Architecture、Enterprise Work Designer、Enterprise Work Modeler、eProcurement Accelerator、EWA、Financial Fusion、Financial Fusion Server、Gateway Manager、GlobalFIX、ImpactNow、Industry Warehouse Studio、InfoMaker、 Information Anywhere、Information Everywhere、InformationConnect、InternetBuilder、iScript、Jaguar CTS、jConnect for JDBC、Mail Anywhere Studio、MainframeConnect、Maintenance Express、Manage Anywhere Studio、M-Business Channel、MBusiness Network、M-Business Server、MDI Access Server、MDI Database Gateway、media.splash、MetaWorks、My AvantGo、 My AvantGo Media Channel、My AvantGo Mobile Marketing、MySupport、Net-Gateway、Net-Library、New Era of Networks、 ObjectConnect、ObjectCycle、OmniConnect、OmniSQL Access Module、OmniSQL Toolkit、Open Biz、Open Client、Open ClientConnect、Open Client/Server、Open Client/Server Interfaces、Open Gateway、Open Server、Open ServerConnect、Open Solutions、Optima++、PB-Gen、PC APT Execute、PC Net Library、PocketBuilder、Pocket PowerBuilder、Power++、 power.stop、PowerAMC、PowerBuilder、PowerBuilder Foundation Class Library、PowerDesigner、PowerDimensions、 PowerDynamo、PowerJ、PowerScript、PowerSite、PowerSocket、Powersoft、PowerStage、PowerStudio、PowerTips、 Powersoft Portfolio、Powersoft Professional、PowerWare Desktop、PowerWare Enterprise、ProcessAnalyst、Rapport、Report Workbench、Report-Execute、Replication Agent、Replication Driver、Replication Server、Replication Server Manager、 Replication Toolkit、Resource Manager、RW-DisplayLib、S-Designor、SDF、Secure SQL Server、Secure SQL Toolset、Security Guardian、SKILS、smart.partners、smart.parts、smart.script、SQL Advantage、SQL Anywhere、SQL Anywhere Studio、SQL Code Checker、SQL Debug、SQL Edit、SQL Edit/TPU、SQL Everywhere、SQL Modeler、SQL Remote、SQL Server、SQL Server Manager、SQL SMART、SQL Toolset、SQL Server/CFT、SQL Server/DBM、SQL Server SNMP SubAgent、SQL Station、 SQLJ、STEP、SupportNow、S.W.I.F.T. Message Format Libraries、Sybase Central、Sybase Client/Server Interfaces、Sybase Financial Server、Sybase Gateways、Sybase MPP、Sybase SQL Desktop、Sybase SQL Lifecycle、Sybase SQL Workgroup、 Sybase User Workbench、SybaseWare、Syber Financial、SyberAssist、SyBooks、System 10、System 11、System XI ( ロゴ )、 SystemTools、Tabular Data Stream、TradeForce、Transact-SQL、Translation Toolkit、UltraLite.NET、UNIBOM、Unilib、 Uninull、Unisep、Unistring、URK Runtime Kit for UniCode、Viewer、Visual Components、VisualSpeller、VisualWriter、VQL、 WarehouseArchitect、Warehouse Control Center、Warehouse Studio、Warehouse WORKS、Watcom、Watcom SQL、Watcom SQL Server、Web Deployment Kit、Web.PB、Web.SQL、WebSights、WebViewer、WorkGroup SQL Server、XA-Library、XAServer、XP Server は、米国法人 Sybase, Inc. の商標です。 Unicode と Unicode のロゴは、Unicode, Inc. の登録商標です。 このマニュアルに記載されている上記以外の社名および製品名は、各社の商標または登録商標の場合があります。 Use, duplication, or disclosure by the government is subject to the restrictions set forth in subparagraph (c)(1)(ii) of DFARS 52.2277013 for the DOD and as set forth in FAR 52.227-19(a)-(d) for civilian agencies. Sybase, Inc., One Sybase Drive, Dublin, CA 94568. 目次 はじめに ................................................................................................................................................. xv 第1章 パフォーマンスとチューニングの概要 ................................................... 1 第2章 オプティマイザの概要 ............................................................................ 3 定義 ........................................................................................................ 4 クエリ処理の手順 ........................................................................... 4 オプティマイザを活用する ............................................................. 5 オブジェクトのサイズがクエリのチューニングにとって重要な理由 ... 5 クエリの最適化 ...................................................................................... 6 SQL 抽出テーブルと最適化 ............................................................ 7 最適化のために調査される要素 ............................................................. 8 前処理による最適化可能な句の追加...................................................... 9 句から同等な探索引数への変換...................................................... 9 式から探索引数への変換............................................................... 10 探索引数の推移閉包...................................................................... 10 ジョイン推移閉包 ......................................................................... 11 述部要素変形................................................................................. 12 探索引数を作成するためのガイドライン............................................. 14 探索引数と有用なインデックス ........................................................... 15 探索引数の構文 ............................................................................. 15 探索引数に統計値が使用される方法............................................. 17 複数の探索引数における統計値の使用 ......................................... 19 探索引数のデフォルト値............................................................... 20 変数とパラメータを使用する探索引数 ......................................... 21 ジョインの構文とジョイン処理 ........................................................... 21 ジョインの処理のしくみ............................................................... 22 ジョインに対し統計値が使用できないとき.................................. 22 密度値とジョイン ......................................................................... 23 複数カラムのジョイン .................................................................. 23 1 つのテーブルにある探索引数とジョイン .................................. 23 データ型の不一致とクエリの最適化.................................................... 24 データ型の階層とインデックスの問題に関する概要 ................... 25 探索引数として使用されるパラメータおよび変数のデータ型 ..... 27 ジョイン・カラムで互換性のあるデータ型.................................. 29 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン iii 目次 データ型と比較についてのアドバイス......................................... ジョインの対象となるデータ型の強制的な変換 .......................... コスト計算の精度を高めるストアド・プロシージャ分割 ................... コストの基本単位 ................................................................................ 第3章 高度な最適化ツール .............................................................................. 35 特殊な最適化手法 ................................................................................ オプティマイザのオプションを指定する ............................................ ジョインでのテーブル順序を指定する ................................................ forceplan の使用に伴うリスク...................................................... forceplan を指定する前に ............................................................. オプティマイザが検討するテーブル数を指定する .............................. クエリにインデックスを指定する ....................................................... リスク ........................................................................................... インデックスを指定する前に ....................................................... クエリに I/O サイズを指定する ........................................................... インデックス・タイプと大容量 I/O.............................................. prefetch 指定がきかない場合........................................................ set prefetch on .............................................................................. キャッシュ方式を指定する .................................................................. select 文、delete 文、update 文の場合 ........................................ 大容量 I/O とキャッシュ方式の制御 .................................................... キャッシュ方式に関する情報の取得 ............................................ 非同期ログ・サービス ......................................................................... ユーザ・ログ・キャッシュ (ULC) アーキテクチャの理解 ........... ALS の使用が適する場合.............................................................. ALS の使用 ................................................................................... 変更されたシステム・プロシージャ ............................................ マージ・ジョインの有効化と無効化 ................................................... ジョイン推移閉包の有効化と無効化 ................................................... クエリの並列度の指定 ......................................................................... クエリ・レベルの parallel 句の例................................................. 小さいテーブルの同時実行性の最適化 ................................................ ロック・スキームの変更 .............................................................. 第4章 35 36 37 38 38 39 40 41 41 42 43 44 45 45 46 47 47 48 49 50 50 51 51 52 53 54 55 55 クエリ・チューニング用ツール ............................................................ 57 概要 ...................................................................................................... ツールの影響........................................................................................ showplan と noexec を同時に指定する........................................ noexec と statistics io .................................................................. ツールとクエリ処理の関連 .................................................................. iv 30 30 32 33 57 59 59 59 60 Adaptive Server Enterprise 目次 第5章 1 つのテーブルに対するアクセス・メソッドとクエリ・コスト計算 ... 61 テーブル・スキャンにかかるコスト .................................................... 63 全ページロック・テーブルのスキャンにかかるコスト ................ 63 データオンリーロック・テーブルのスキャンにかかるコスト ..... 64 ローからページへ ................................................................................. 66 クラスタ率が大容量 I/O に与える影響.......................................... 67 インデックス・アクセスにかかるコストを評価する ........................... 69 単一のローを返すクエリ ............................................................... 69 多数のローを返すクエリ ............................................................... 69 カバーリング・インデックスを使う範囲クエリ ........................... 72 非カバーリング・インデックスを使う範囲クエリ ....................... 73 order by を使ったクエリのコスト見積もり.......................................... 77 プレフィクス・サブセットとソート ............................................. 78 キー順序とソート.......................................................................... 78 オプティマイザがソート・オペレーションのコストを 計算する仕組み ...................................................................... 80 クラスタード・インデックスのある全ページロック・ テーブル ................................................................................. 81 インデックスがクエリをカバーする場合のソート ....................... 83 ソートと非カバーリング・インデックス...................................... 83 アクセス・メソッドと or 句および in 句のコスト計算 ........................ 84 or 構文 ........................................................................................... 84 in (values_list) から or 処理への変換............................................. 84 or 句に対する処理の仕組み........................................................... 85 集合関数の最適化方法.......................................................................... 89 集合関数 max と min の組み合わせの処理.................................... 90 更新オペレーションの実行方法 ........................................................... 91 直接更新 ........................................................................................ 91 遅延更新 ........................................................................................ 93 インデックスの遅延挿入 ............................................................... 94 ジョインによる更新モードの制限................................................. 97 更新の最適化 ................................................................................. 98 更新をチューニングする場合の sp_sysmon の使用 ................... 100 第6章 ジョインとサブクエリのアクセス・メソッドとコスト計算............... 101 ジョインのコスト計算と最適化 ......................................................... 101 処理 ............................................................................................. 102 インデックス密度とジョイン...................................................... 102 データ型の不一致とジョイン...................................................... 103 ジョイン順序 ............................................................................... 103 ネストループ・ジョイン .................................................................... 107 コスト計算式 ............................................................................... 108 内部テーブルと外部テーブルの決定方法.................................... 108 セルフジョイン................................................................................... 109 ソートマージ・ジョインのアクセス・メソッドとコスト計算 .......... 111 フルマージ・ジョインの実行方法............................................... 113 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン v 目次 右マージ・ジョインと左マージ・ジョインの実行方法 ............. ソートマージ・ジョインの実行方法 .......................................... 混合ジョインの例 ....................................................................... マージ・ジョインのコスト計算 ................................................. ユニークな値がある場合のフルマージ・ジョインの コスト計算........................................................................... 例:クラスタード・インデックスのある全ページロック・ テーブル .............................................................................. 重複する値がある場合のフルマージ・ジョインの コスト計算........................................................................... ソートのコスト計算 ................................................................... マージ・ジョインが使用できない場合....................................... ワーカー・プロセスの使用......................................................... マージの実行パフォーマンス向上のための推奨事項 ................. マージ・ジョインを有効または無効にする....................................... サーバ・レベル........................................................................... セッション・レベル ................................................................... 再フォーマット方式........................................................................... サブクエリの最適化........................................................................... in、any、exists サブクエリのフラット化 .................................. 式サブクエリのフラット化......................................................... サブクエリの結果を実体化する ................................................. and 句に続くサブクエリ ............................................................ or 句に続くサブクエリ ............................................................... サブクエリ結果のキャッシュ ..................................................... サブクエリを最適化する ............................................................ ジョイン内の or 句と union ............................................................... 第7章 118 118 119 120 121 122 122 124 124 124 125 126 126 131 131 134 134 135 135 136 並列クエリ処理 ................................................................................... 137 並列処理のメリットを利用できるクエリの種類 ............................... Adaptive Server のワーカー・プロセス・モデル .............................. 並列クエリの実行 ....................................................................... 並列クエリからの結果の戻り ..................................................... 並列データ・アクセスのタイプ......................................................... ハッシュベース・テーブル・スキャン....................................... パーティションベース・スキャン .............................................. ハッシュベース・インデックス・スキャン ............................... ジョインによる 2 つのテーブルの並列処理 ............................... showplan メッセージ.................................................................. 並列度の制御...................................................................................... 並列処理を制御するための設定パラメータ ............................... セッションの並列処理を制御するための set オプションの使用 .......................................................... クエリの並列処理の制御 ............................................................ ワーカー・プロセスの可用性とクエリの実行............................ 並列処理で使用するその他の設定パラメータ............................ vi 114 115 115 117 138 139 141 142 143 144 145 145 146 148 148 149 152 153 153 154 Adaptive Server Enterprise 目次 分割されたテーブルを操作するためのコマンド ................................ 155 リソースの配分とパフォーマンス...................................................... 157 CPU リソース.............................................................................. 157 ディスク・リソースと I/O........................................................... 158 チューニングの例:CPU と I/O の飽和 ...................................... 158 並列クエリ設定のガイドライン ......................................................... 159 ハードウェアのガイドライン...................................................... 159 パフォーマンスの目標とハードウェア・ガイドライン .............. 160 並列クエリのチューニングの例 .................................................. 160 分割と並列度のガイドライン...................................................... 162 データのサブセットを使用した実験 ........................................... 163 システム・レベルの影響 .................................................................... 164 ロックの問題 ............................................................................... 164 デバイスの問題 ........................................................................... 164 プロシージャ・キャッシュの影響............................................... 165 並列クエリの結果が異なる場合 ......................................................... 165 set rowcount を使用するクエリ .................................................. 166 ローカル変数を設定するクエリ .................................................. 166 一貫した結果の取得 .................................................................... 166 第8章 並列クエリ最適化................................................................................ 169 並列クエリ最適化とは? .................................................................... 169 最適化における応答時間と合計作業量 ....................................... 170 最適化が実行される場合 .................................................................... 170 オーバヘッド・コスト........................................................................ 171 考慮されない要素........................................................................ 171 並列アクセス・メソッド .................................................................... 172 並列パーティション・スキャン .................................................. 173 並列クラスタード・インデックス・パーティション・ スキャン ( 全ページロック・テーブル )............................... 174 並列ハッシュベース・テーブル・スキャン ................................ 176 並列ハッシュベース・インデックス・スキャン ......................... 178 並列レンジベース・スキャン...................................................... 180 その他の並列方式........................................................................ 183 並列アクセス・メソッドのまとめ...................................................... 184 並列アクセス・メソッドの選択 .................................................. 184 並列クエリの並列度 ........................................................................... 185 上限値.......................................................................................... 186 最適化された並列度 .................................................................... 186 ネストループ・ジョイン ............................................................. 189 例 ................................................................................................. 192 ワーカー・プロセスに対する実行時調整.................................... 194 並列クエリの例................................................................................... 194 シングルテーブル・スキャン...................................................... 195 マルチテーブル・ジョイン ......................................................... 197 サブクエリ................................................................................... 200 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン vii 目次 ワークテーブルを必要とするクエリ .......................................... union クエリ ............................................................................... 集約を伴うクエリ ....................................................................... select into 文 ............................................................................... ワーカー・プロセスの実行時調整 ..................................................... Adaptive Server によるクエリ・プランの調整方法 ................... 実行時調整の効果に対する評価 ................................................. 実行時調整の識別と管理 ............................................................ 実行時調整の発生回数の削減 ..................................................... sp_sysmon による実行時調整の検査 ......................................... 並列処理のパフォーマンスの問題に対する診断 ............................... クエリが並列実行されない場合 ................................................. 期待どおりの並列処理パフォーマンスが得られない場合.......... サポート・センタへの診断依頼 ................................................. 並列クエリのリソース制限 ................................................................ 第9章 並列ソート .......................................................................................... 209 並列ソートのメリットを利用するコマンド....................................... 稼働条件とリソースの概要 ................................................................ 並列ソート方式の概要 ....................................................................... 分散マップの作成 ....................................................................... 動的な範囲による分割 ................................................................ 範囲ソート .................................................................................. 結果のマージ .............................................................................. 並列ソート用のリソース設定 ............................................................ 並列ソート中のワーカー・プロセスの稼働条件 ........................ select クエリ・ソート時のワーカー・プロセスの動作条件....... キャッシュ、ソート・バッファ、並列ソート............................ ディスクの動作条件 ................................................................... リカバリについて .............................................................................. ソート動作の監視およびチューニング用のツール ............................ set sort_resources on の使用...................................................... sp_sysmon を使用したインデックス作成のチューニング ................ 並列ソートを使用した create index の高速化 ................................... 第 10 章 209 210 212 213 214 214 215 215 216 219 220 226 228 229 229 234 235 非同期プリフェッチのチューニング................................................... 237 非同期プリフェッチによるパフォーマンスの向上 ............................ ページのプリフェッチによるクエリ・パフォーマンスの 向上...................................................................................... マルチユーザ環境でのプリフェッチ制御メカニズム ................. リカバリ中の予備セット ............................................................ 逐次スキャン中の予備セット ..................................................... ノンクラスタード・インデックス・アクセス中の 予備セット........................................................................... dbcc チェック中の予備セット.................................................... viii 201 201 201 202 202 203 203 204 205 205 206 206 207 207 208 237 238 239 240 241 241 241 Adaptive Server Enterprise 目次 予備セットの最小および最大サイズ ........................................... 242 プリフェッチが自動的に無効になる場合 ........................................... 244 プールの溢れ ............................................................................... 244 I/O システムの過負荷 .................................................................. 244 不要な読み込み ........................................................................... 245 非同期プリフェッチのチューニング目標 ........................................... 247 設定用コマンド ........................................................................... 248 Adaptive Server のほかのパフォーマンス機能 .................................. 248 大容量 I/O .................................................................................... 248 MRU ( 使い捨て ) スキャン ......................................................... 250 並列スキャンと大容量 I/O........................................................... 250 非同期プリフェッチ制限値の特殊な設定 ........................................... 251 リカバリ用の非同期プリフェッチ制限値の設定 ......................... 251 dbcc 用の非同期プリフェッチ制限値の設定............................... 252 高いプリフェッチ・パフォーマンスのための管理作業 ..................... 253 ヒープ・テーブルのねじれの除去............................................... 253 クラスタード・インデックス・テーブルのねじれの除去 .......... 253 ノンクラスタード・インデックスのねじれの除去 ..................... 253 パフォーマンス・モニタリングと非同期プリフェッチ ..................... 254 第 11 章 複数のテンポラリ・データベース ...................................................... 255 概要..................................................................................................... 255 テンポラリ・データベースの作成後 .................................................. 259 sp_tempdb の使用 .............................................................................. 260 テンポラリ・データベースとのバインド ........................................... 260 セッションのバインド................................................................. 261 複数のテンポラリ・データベースとシステム.................................... 262 システム・テーブルの変更 ......................................................... 262 @@tempdbid グローバル変数 .................................................... 263 tempdb_id() 関数 ......................................................................... 263 ログ・トランケーション ............................................................. 263 ロールバックとリカバリ ............................................................. 264 テンポラリ・データベースの削除............................................... 265 alter database.............................................................................. 266 キャッシュ特性 ........................................................................... 266 ストアド・プロシージャの処理 .................................................. 267 tempdb 書き込みの最適化........................................................... 268 高可用性に関する考慮事項 ......................................................... 268 テンポラリ・データベースのダンプとロード ............................ 270 sp_dboption ストアド・プロシージャ ........................................ 271 オープン・データベース数の設定............................................... 271 変更されたプロシージャ ............................................................. 271 変更および追加された DBCC ..................................................... 272 その他の変更 ............................................................................... 273 インストールに関する注意事項 ......................................................... 273 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン ix 目次 アプリケーション用のテンポラリ・データベースの サイズ指定と設定 ................................................................ 共有テンポラリ・テーブル......................................................... ユーザ作成のストアド・プロシージャの更新 ............................ 以前のバージョンへのダウングレード....................................... 第 12 章 tempdb のパフォーマンスについて ................................................... 277 tempdb の管理がパフォーマンスに及ぼす影響 ................................. tempdb パフォーマンス問題の主な解決方法 ............................. テンポラリ・テーブルの種類と使い方 .............................................. 一時的なテンポラリ・テーブル ................................................. 正規のユーザ・テーブル ............................................................ ワークテーブル........................................................................... tempdb の初期割り付け ..................................................................... tempdb のサイズ設定......................................................................... tempdb の配置 ................................................................................... tempdb セグメントからのマスタ・デバイスの削除.......................... 複数のディスクの場合の並列クエリのパフォーマンスの 使用...................................................................................... tempdb の専用キャッシュへのバインド............................................ キャッシュ・バインド用コマンド .............................................. テンポラリ・テーブルとロック......................................................... tempdb 内のログの最小化 ................................................................. select into の使用 ........................................................................ ローを短くする........................................................................... テンポラリ・テーブルの最適化......................................................... テンポラリ・テーブルにインデックスを作成する。................... テンポラリ・テーブルを使ってネスト・プロシージャを 作成する .............................................................................. tempdb を使用する処理を複数のプロシージャに分割する........ 第 13 章 277 278 278 279 279 280 280 281 282 282 283 284 284 285 285 285 286 286 288 288 289 カーソルとパフォーマンス ................................................................. 291 意味 .................................................................................................... 集合指向プログラミングとロー指向プログラミング ................. 例 ................................................................................................ 各ステージで必要とされるリソース ................................................. メモリ使用と実行カーソル......................................................... カーソル・モード .............................................................................. インデックス使用とカーソルの動作条件 .......................................... 全ページロック・テーブル......................................................... データオンリーロック・テーブル .............................................. カーソルがある場合とない場合のパフォーマンスの比較 ................. カーソルがないストアド・プロシージャの例 ............................ カーソルがあるストアド・プロシージャの例 ............................ カーソルがある場合とない場合のパフォーマンスの比較 .......... x 274 274 275 276 291 292 293 294 296 297 297 297 298 299 299 300 302 Adaptive Server Enterprise 目次 読み込み専用カーソルを使ったロック............................................... 303 独立性レベルとカーソル .................................................................... 304 分割されたヒープ・テーブルとカーソル ........................................... 305 カーソルを最適化するために ............................................................. 305 カーソルを使ったカーソル select 文の最適化 ............................ 306 or 句または in リストの代わりに union を使う........................... 306 カーソルの意図を宣言する ......................................................... 306 for update 句にカラム名を指定する............................................ 307 set cursor rows を使う ................................................................ 308 複数のコミットとロールバックにわたってカーソルを オープンに保つ .................................................................... 309 1 つの接続で複数のカーソルをオープンする ............................. 309 第 14 章 抽象プランの概要................................................................................ 311 意味..................................................................................................... 311 抽象プランの管理 ............................................................................... 312 クエリ・テキストとクエリ・プランの関係 ....................................... 313 クエリ・プランに影響するオプションの制約 ............................ 313 完全なプランと部分プラン................................................................. 314 部分プランの作成........................................................................ 315 抽象プラン・グループ........................................................................ 315 抽象プランのクエリへの関連付け...................................................... 316 第 15 章 クエリの抽象プランのユーザーズ・ガイド ........................................ 317 概要..................................................................................................... 317 抽象プラン言語 ........................................................................... 318 テーブルの識別 ........................................................................... 320 インデックスの識別 .................................................................... 321 ジョイン順の指定........................................................................ 322 ジョイン型の指定........................................................................ 325 部分プランとヒントの指定 ......................................................... 326 サブクエリの抽象プランの作成 .................................................. 329 実体化されたビューの抽象プラン............................................... 335 集合関数を含むクエリの抽象プラン ........................................... 336 再フォーマット方式の指定 ......................................................... 338 OR 方式の制限事項 ..................................................................... 338 store 演算子が指定されていない場合 ......................................... 339 抽象プランを記述するためのヒント .................................................. 339 「変更前」と「変更後」のプランの比較............................................. 340 サーバワイドな取得モードの影響............................................... 341 プランをコピーするための時間と領域 ....................................... 341 ストアド・プロシージャの抽象プラン............................................... 342 プロシージャとプランの所有者 .................................................. 342 可変実行パスと最適化を使用するプロシージャ ......................... 343 アドホック・クエリと抽象プラン...................................................... 343 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン xi 目次 第 16 章 抽象プランの作成と使用..................................................................... 345 set コマンドを使ってプランの取得と関連付けを行う ...................... set plan dump を使ってプラン取得モードを有効にする ........... 格納されているプランにクエリを関連付ける ............................ プランの取得中に plan replace モードを使用する..................... plan dump モード、plan load モード、および plan replace モードを同時に使用する................................. set plan exists check オプション ....................................................... 抽象プランにほかの set オプションを使用する ................................ showplan を使用する.................................................................. noexec を使用する ..................................................................... forceplan を使用する .................................................................. サーバ全体での抽象プランの取得と関連付けモード ........................ SQL によるプランの作成................................................................... create plan を使用する ............................................................... plan 句を使用する....................................................................... 第 17 章 348 350 351 351 351 352 352 353 353 354 システム・プロシージャを使用した抽象プランの管理 ...................... 357 抽象プラン管理のためのシステム・プロシージャ ............................ 抽象プラン・グループの管理 ............................................................ グループの作成........................................................................... グループの削除........................................................................... グループについての情報の取得 ................................................. グループの名前の変更 ................................................................ 抽象プランの検索 .............................................................................. 個々の抽象プランの管理.................................................................... プランの表示 .............................................................................. 別のグループへのプランのコピー .............................................. 個々の抽象プランの削除 ............................................................ 2 つの抽象プランの比較 ............................................................. 既存のプランの変更 ................................................................... グループにあるすべてのプランの管理 .............................................. グループにあるすべてのプランのコピー ................................... グループにあるすべてのプランの比較....................................... 1 つのグループのすべての抽象プランの削除 ............................ プラン・グループのインポートとエクスポート ............................... プランのユーザ・テーブルへのエクスポート ............................ ユーザ・テーブルからのプランのインポート ............................ xii 345 346 347 347 357 358 358 359 359 362 362 363 363 364 364 365 366 366 366 367 370 370 370 371 Adaptive Server Enterprise 目次 第 18 章 抽象プラン言語リファレンス.............................................................. 373 キーワード.......................................................................................... 373 オペランド.......................................................................................... 373 抽象プランの抽出テーブル ......................................................... 374 プランの例に使用しているスキーマ .................................................. 374 g_join .................................................................................................. 375 hints .................................................................................................... 378 i_scan ................................................................................................. 379 in ......................................................................................................... 380 lru........................................................................................................ 382 m_g_join ............................................................................................. 383 mru...................................................................................................... 385 nested ................................................................................................. 385 nl_g_join ............................................................................................. 387 parallel ................................................................................................ 388 plan ..................................................................................................... 389 prefetch............................................................................................... 391 prop..................................................................................................... 392 scan .................................................................................................... 393 store.................................................................................................... 394 subq .................................................................................................... 395 t_scan ................................................................................................. 398 table .................................................................................................... 399 union ................................................................................................... 401 view..................................................................................................... 402 work_t ................................................................................................. 403 索引....................................................................................................................................................... 405 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン xiii 目次 xiv Adaptive Server Enterprise はじめに 対象読者 このマニュアルは、データベース管理者、データベース設計者、アプリ ケーション開発者、システム管理者を対象としています。 注意 自分のデータベースを使用して、変更とクエリをテストすることが できます。該当するデータベースのスナップショットをとり、テスト・ マシンに設定してください。 このマニュアルの内容 このマニュアルは、Adaptive Server のパフォーマンスのチューニング、 トラブルシューティング、または改善に使用します。 「第 1 章 パフォーマンスとチューニングの概要」では、このマニュアルと Adaptive Server のパフォーマンス&チューニング・シリーズの他のマニュ アルの概要について説明します。 「第 2 章 オプティマイザの概要」では、クエリの最適化処理や、統計値を 探索引数に適用してクエリにジョインする方法について説明します。 「第 3 章 高度な最適化ツール」では、クエリ・パフォーマンスをチューニ ングする拡張ツールについて説明します。 「第 4 章 クエリ・チューニング用ツール」では、クエリ・チューニング・ ツールの概要とその効果について説明します。 「第 5 章 1 つのテーブルに対するアクセス・メソッドとクエリ・コスト 計算」では、Adaptive Server がテーブルを 1 つだけ含んでいるクエリの テーブルにどのようにアクセスするかと、さまざまなアクセス・メソッ ドに対するコストの見積もり方について説明します。 「第 6 章 ジョインとサブクエリのアクセス・メソッドとコスト計算」では、 Adaptive Server がジョインやサブクエリの処理中にどのようにテーブル にアクセスするかと、コストの決定方法について説明します。 「第 7 章 並列クエリ処理」では、並列クエリ処理で必要となる概念とリ ソースについて説明します。 「第 8 章 並列クエリ最適化」では、並列クエリの最適化について詳しく説 明します。 「第 9 章 並列ソート」では、クエリおよびインデックス作成時の並列ソー トの使用方法について説明します。 「第 10 章 非同期プリフェッチのチューニング」では、非同期プリフェッ チによって大容量ディスク I/O を実行するクエリのパフォーマンスを向 上させる方法について説明します。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン xv 「第 11 章 複数のテンポラリ・データベース」では、Adaptive Server を使って複 数のテンポラリ・データベースを作成する方法について説明します。複数のテ ンポラリ・データベースを使って、プライベートのテンポラリ・テーブルや ワーク・テーブルなどのテンポラリ・オブジェクトを作成できます。 「第 12 章 tempdb のパフォーマンスについて」では、テンポラリ・データベー スである tempdb の重要性について説明します。また、そのパフォーマンスの 向上に役立つ情報も記載されています。 「第 13 章 カーソルとパフォーマンス」では、カーソルとパフォーマンスの問 題について説明します。 「第 14 章 抽象プランの概要」では、抽象プランの概要と、このプランを使用し たクエリ最適化問題の解決方法について説明します。 「第 15 章 クエリの抽象プランのユーザーズ・ガイド」では、特定の種類のクエ リに抽象プランを書き込む方法の概要を説明します。また、設定やシステムを 変更したためにクエリに加えられた変更を、抽象プランを使用してクエリの最 適化で検出する方法についても説明します。 「第 16 章 抽象プランの作成と使用」では、抽象プランの保存時や使用時に実行 するコマンドについて説明します。 「第 17 章 システム・プロシージャを使用した抽象プランの管理」では、抽象 プランとそのグループを管理するシステム・プロシージャについて説明します。 「第 18 章 抽象プラン言語リファレンス」では、抽象プランの言語について説 明します。 関連マニュアル : • • パフォーマンス&チューニング・シリーズには、このマニュアルの他に次 のマニュアルがあります。 • 『パフォーマンス&チューニング・ガイド:基本』 • 『パフォーマンス&チューニング・ガイド:ロック』 • 『パフォーマンス&チューニング・ガイド:モニタリングと分析』 使用しているプラットフォームの『リリース・ノート』- マニュアルには 記載できなかった最新の情報が記載されています。 『リリース・ノート』の最新版 ( 英語版 ) にはインターネットからアクセ スできます。この製品の CD-ROM がリリースされたあとに追加された重 要な製品情報やマニュアル情報を確認する場合は、 Sybase Technical Library を参照してください。 • xvi 使用しているプラットフォームの『インストール・ガイド』- すべての Adaptive Server および関連する Sybase 製品のインストール、アップグ レード、設定の手順について説明しています。 Adaptive Server Enterprise はじめに • 使用しているプラットフォームの 『Adaptive Server Enterprise 設定ガイド』- Adaptive Server の特定の設定作業を行う方法について説明しています。 • 『Adaptive Server Enterprise 新機能ガイド』- Adaptive Server バージョン 12.5 の新しい機能について説明しています。また、新しい機能をサポート するためのシステム変更や、既存のアプリケーションに影響する変更につ いても説明しています。 • 『Transact-SQL ユーザーズ・ガイド』- リレーショナル・データベース言 語の拡張版である Sybase の Transact-SQL について説明しています。この マニュアルでは、データベース管理システムの操作に慣れていない方のた めに、テキストブック形式で説明しています。また、pubs2 と pubs3 サ ンプル・データベースについても説明します。 • 『システム管理ガイド』- サーバとデータベースを管理するための高度な 情報について説明しています。このマニュアルでは、物理的なリソース、 セキュリティ、ユーザ・データベース、システム・データベースの管理 方法、および文字セットの変換、言語の国際化、ソート順の指定方法に ついての手順とガイドラインを説明しています。 • 『ASE リファレンス・マニュアル』- すべての Transact-SQL コマンド、 関数、プロシージャ、データ型について説明しています。また、TransactSQL コマンドの予約語のリストとシステム・テーブルの定義について も説明します。 • 『ASE ユーティリティ・ガイド』- オペレーティング・システム・レベル で実行される、isql および bcp などの、Adaptive Server のユーティリティ・ プログラムについて説明しています。 • 『クイック・リファレンス・ガイド』- コマンド、関数、システム・プロ シージャ、拡張システム・プロシージャ、データ型、ユーティリティの名 前と構文の包括的な一覧表を記載したポケット版のマニュアルです。印刷 版のみが用意されています。 • 『システム・テーブル・ダイヤグラム』- システム・テーブルと、そのエ ンティティの関係をポスター形式で図解しています。印刷版のみが用意さ れています。 • 『トラブルシューティング&エラー・メッセージ・ガイド』- 発生頻度の 高いエラー・メッセージとシステムの問題について、解決方法を説明して います。 • 『コンポーネント統合サービス・ユーザーズ・ガイド』- リモートの Sybase データベースおよび Sybase 以外のデータベースへ接続するための Adaptive Server コンポーネント統合サービス機能について説明しています。 • 『Adaptive Server Enterprise における Java』- Adaptive Server データベース で Java クラスをデータ型、関数、ストアド・プロシージャとしてインス トールして使用する方法について説明しています。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン xvii その他の情報ソース xviii • 『Adaptive Server Enterprise における XML Services』- データベースに XML 機能を導入する、 Sybase ネイティブの XML プロセッサと Sybase Java ベー スの XML のサポートについて、また XML サービスに準拠したクエリと マッピング用の関数について説明しています。 • 『高可用性システムにおける Sybase フェールオーバの使用』- Sybase の フェールオーバ機能を使用して、Adaptive Server を高可用性システムのコ ンパニオン・サーバとして設定する方法について説明しています。 • 『Job Scheduler ユーザーズ・ガイド』- コマンド・ラインまたはグラフィ カル・ユーザ・インタフェース (GUI) を使用して、ローカルまたはリモー トの Adaptive Server 上でジョブを作成してスケジュールする方法につい て説明しています。 • 『Adaptive Server 分散トランザクション管理機能の使用』- 分散トランザ クション処理環境での Adaptive Server DTM 機能の設定、使用、トラブル シューティングについて説明しています。 • 『EJB Server ユーザーズ・ガイド』- EJB Server を使用して Adaptive Server で Enterprise JavaBeans を展開、実行する方法について説明しています。 • 『XA インタフェース統合ガイド for CICS、Encina、TUXEDO』- X/Open XA トランザクション・マネージャを備えた Sybase の DTM XA インタフェー スを使用する方法について説明しています。 • 『用語解説』- Adaptive Server マニュアルで使用されている技術用語につ いて説明しています。 • 『jConnect for JDBC プログラマーズ・リファレンス』- jConnect for JDBC 製品について説明し、この製品を使用してリレーショナル・データベース 管理システムに保管されているデータにアクセスする方法について説明 しています。 • 『Enhanced Full-Text Search Specialty Data Store ユーザーズ・ガイド』- Verity で全文検索機能を使用して Adaptive Server Enterprise のデータを検索する 方法について説明しています。 • 『Historical Server ユーザーズ・ガイド』- Historical Server を使用して、SQL Server と Adaptive Server のパフォーマンス情報を入手する方法について説 明しています。 • 『Monitor Server ユーザーズ・ガイド』- Monitor Server を使用して、SQL Server と Adaptive Server のパフォーマンス統計を取得する方法について説 明しています。 • 『Monitor Client Library プログラマーズ・ガイド』- Adaptive Server のパ フォーマンス・データにアクセスする Monitor Client Library アプリケー ションの記述方法を説明しています。 Sybase Technical Library CD と Technical Library Product Manuals Web サイトを利 用すると、製品について詳しく知ることができます。 Adaptive Server Enterprise はじめに • Getting Started CD には、PDF 形式のリリース・ノートとインストール・ガ イドが収録されています。また、その他のマニュアルや、Technical Library CD には含まれない更新情報が収録されることもあります。この CD は製 品のソフトウェアに同梱されています。Getting Started CD に収録されてい るマニュアルを参照または印刷するには、Adobe Acrobat Reader が必要で す (CD 内のリンクを使用して Adobe の Web サイトから無料でダウンロー ドできます )。 • Technical Library CD には、製品マニュアルが収録されています。この CD は製品のソフトウェアに同梱されています。DynaText リーダー (Technical Library CD に収録 ) を使用すると、製品についての情報に簡単にアクセス できます。 Technical Library のインストールと起動の方法については、マニュアル・ パッケージに含まれている『Technical Library Installation Guide』を参照し てください。 • Technical Library Product Manuals Web サイトは、Technical Library CD の HTML バージョンで、標準の Web ブラウザを使ってアクセスできます。 また、製品マニュアルのほか、EBFs/Updates、Technical Documents、Case Management、Solved Cases、ニュース・グループ、Sybase Developer Network へのリンクもあります。 Technical Library Product Manuals Web サイトにアクセスするには、Product Manuals (http://www.sybase.com/support/manuals/) にアクセスしてくだ さい。 Sybase Web サイトの技術的な資料は頻繁に更新されます。 Web 上の Sybase 製品 の動作確認情報 ❖ ❖ 製品認定の最新情報にアクセスする 1 Web ブラウザで Technical Documents を指定します。 (http://www.sybase.com/support/techdocs/) 2 左側のナビゲーション・バーから [Products] を選択します。 3 製品リストから製品名を選択し、[Go] をクリックします。 4 [Certification Report] フィルタを選択し、時間枠を指定して [Go] をクリッ クします。 5 [Certification Report] のタイトルをクリックして、レポートを表示します。 Sybase Web サイト ( サポート・ページを含む ) の自分専用のビューを作成する MySybase プロファイルを設定します。MySybase は無料サービスです。この サービスを使用すると、Sybase Web ページの表示方法を自分専用にカスタマ イズできます。 1 Web ブラウザで Technical Documents を指定します。 (http://www.sybase.com/support/techdocs/) 2 [MySybase] をクリックし、MySybase プロファイルを作成します。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン xix Sybase EBF とソフト ウェアの更新 ❖ EBF とソフトウェア更新の最新情報にアクセスする 1 Web ブラウザで Sybase Support Page (http://www.sybase.com/support) を指定します。 2 [EBFs/Maintenance] を選択します。すでに Web アカウントをお持ちの場合 はユーザ名とパスワードを要求されますので、各情報を入力します。Web アカウントをお持ちでない場合は、新しいアカウントを作成します。サー ビスは無料です。 3 製品を選択します。 4 時間枠を指定して [Go] をクリックします。 5 EBF/Update レポートを表示するには [Info] アイコンをクリックします。 ソフトウェアをダウンロードするには製品の説明をクリックします。 表記の規則 この項では、このマニュアルで使用されている表記について説明します。 SQL 文のフォーマット SQL は自由な形式の言語で、1 行内のワード数や、改行の仕方に規則はありま せん。このマニュアルでは、読みやすくするため、例や構文を文の句ごとに改 行しています。複数の部分からなり、2 行以上にわたる場合は、字下げしてい ます。 フォントと構文の規則 フォントと構文の規則は、表 1 のとおりです。 表 1: フォントと構文の規則 要素 コマンド名、コマンドのオプション名、ユーティリティ 名、ユーティリティのフラグ、キーワードは、太字で表 記する。 データベース名、データ型、ファイル名、パス名は、斜 体で表記する。 変数 (ユーザが入力する値を表す語) は斜体で表記する。 例 select sp_configure master データベース select column_name from table_name where search_conditions カッコはコマンドの一部として入力する。 xx compute row_aggregate ( column_name ) Adaptive Server Enterprise はじめに 要素 例 中カッコは、その中のオプションを 1 つ以上選択しなけ ればならないことを示す。コマンドには中カッコは入力 しない。 {cash, check, credit} 角カッコは、オプションを選択しても省略してもよいこ とを意味する。コマンドには角カッコは入力しない。 [anchovies] 縦線は、中カッコまたは角カッコの中の縦線で区切られ たオプションのうち 1 つだけを選択できることを意味 する。 {die_on_your_feet | live_on_your_knees | live_on_your_feet} カンマは、中カッコまたは角カッコの中のカンマで区切 られたオプションをいくつでも選択できることを意味 する。オプションはコマンドの一部として入力する必要 がある。 [extra_cheese, avocados, sour_cream] 省略記号 (...) は、直前の要素を必要な回数だけ繰り返し 指定できることを意味する。 buy thing = price [cash | check | credit] [, thing = price [cash | check | credit]]... この例では、製品 (thing) を少なくとも 1 つ購入 (buy) し、 価格 (price) を指定する必要がある。支払方法を角カッコの 中から 1 つ選択できる。さらに、他の製品を購入すること もできる。各 buy に対して、購入した製品 (thing)、価格 (price)、オプションで支払方法 (cash、check、credit のいず れか ) を指定する。 • 次は、オプション句のあるコマンドの構文の例です。 sp_dropdevice [ device_name] 次は、複数のオプション句を持つコマンドの構文の例です。 select column_name from table_name where search_conditions 構文では、キーワード ( コマンド ) は通常のフォントで表記し、識別子は小文 字で表記します。また、ユーザが提供するワードは斜体で表記します。 • 次は、コンピュータからの出力例です。 0736 New Age Books Boston MA 0877 Binnet & Hardley Washington DC 1389 Algodata Infosystems Berkeley CA パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン xxi 大文字と小文字の区別 こ の マ ニ ュ ア ル で は、例 に 使 用 す る 文 字 は ほ と ん ど が 小 文 字 で す が、 Transact-SQL のキーワードを入力するときは、大文字と小文字は区別されま せん。たとえば、SELECT、Select、select はすべて同じです。テーブル名な どのデータベース・オブジェクトの大文字と小文字を Adaptive Server が区別 するかどうかは、Adaptive Server にインストールされたソート順によって決 まります。シングルバイト文字セットを使用している場合は、Adaptive Server のソート順を再設定することによって、大文字と小文字の区別の取り扱い方 を変更できます。 詳細については、『システム管理ガイド』を参照してください。 式 Adaptive Server の構文では、さまざまな種類の式が使用されています。 表 2: 構文で使用されている式の種類 使用法 expression 定義 logical expression TRUE ( 真 )、FALSE ( 偽 )、UNKNOWN ( 未知または認識できない ) のいずれかを返す。 constant expression 常に同じ値を返す。たとえば “5+3”、“ABCDE” など。 float_expr 浮動小数式、または暗黙的に浮動小数値に変換される式。 integer_expr 整数式、または暗黙的に整数値に変換される式。 numeric_expr 1 つの値を返す数値式。 char_expr 1 つの文字値を返す式。 binary_expression 1 つの binary 値または varbinary 値を返す式。 例 定数、リテラル、関数、カラム識別子、変数、パラメータが含まれる。 このマニュアルにある多くの例は、pubtune という名前のデータベースに基 づいています。このデータベースのスキーマは、pubs2 データベースと同じ ですが、このマニュアルの例で使用するテーブルにはより多くのローがあり ます。たとえば、titles には 5000、authors には 5000、titleauthor には 6250 の ローがあります。pubs2 とは異なるインデックスが作成され、多くの例では 別の機能が示されます。また、インデックスについて本文に説明があります。 pubtune データベースは Adaptive Server とともに提供されるわけではありま せん。多数の例が、set showplan や set statistics io などのコマンドの結果を示 しているため、このマニュアルのクエリを pubs2 データベースで実行しても、 I/O の結果が同じになるとは限りません。また、多くの場合、このマニュアル で示されるのと同じクエリ・プランが作成されることもありません。 不明な点があるときは xxii Sybase ソフトウェアがインストールされているサイトには、Sybase 製品の保 守契約を結んでいるサポート・センタとの連絡担当の方 ( コンタクト・パー ソン ) を決めてあります。マニュアルだけでは解決できない問題があった場 合には、担当の方を通して Sybase のサポート・センタまでご連絡ください。 Adaptive Server Enterprise 第 1 章 パフォーマンスとチューニングの概要 Adaptive Server Enterprise のパフォーマンスのチューニングでは、複数のプ ロセスを通して低パフォーマンスの原因、競合、最適化、使用状況を分析 します。 Adaptive Server のオプティマイザはクエリを取り込み、その実行に最適な 方法を探し出します。最適化は、データベースまたはテーブルの統計に基 づいて実行されます。統計が更新されたり、クエリが変更されるまで、最 適化されたプランは有効です。テーブル全体に対して、または一部のデー タをサンプリングして、統計を更新できます。 Adaptive Server はクエリに対して抽象プランを生成し、テキストとそのテ キストに関連する抽象プランを sysqueryplans システム・テーブルに保存 できます。抽象プランは、バッチまたはクエリの中でオプティマイザの判 断を操作するためにオプションを指定する代わりに使用します。抽象プラ ンを使用すると、SQL 文を、構文を変更せずに最適化結果を変更できます。 このマニュアルはパフォーマンスとチューニング・シリーズの一部であり、 Adaptive Server での最適化について説明します。 パフォーマンスとチューニング・シリーズには、ほかに次のマニュアルが あります。 • 『パフォーマンス&チューニング・ガイド:基本』 このマニュアルでは、Adaptive Server のパフォーマンスに対する質問 の理解と調査に関する基本事項について説明します。また、パフォー マンス障害が発生している箇所の検出方法を説明しています。 • 『パフォーマンス&チューニング・ガイド:ロック』 Adaptive Server は、アクティブなトランザクションが現在使用してい るテーブル、データ・ページ、またはデータ・ローをロックすること によって確保します。ロックは、同時制御メカニズムであり、トラン ザクション内部およびトランザクション間でのデータの一貫性を確 保します。マルチユーザ環境では、複数のユーザが同じデータを同時 に扱うため、ロックが必要です。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 1 • 『パフォーマンス&チューニング・ガイド:モニタリングと分析』 Adaptive Server では、サーバをモニタリングするためにレポートが使用さ れます。このマニュアルでは、モニタリングと最適化のために、統計をど のように取得して使用するかについて説明します。ストアド・プロシー ジャ sp_sysmon は、Adaptive Server のパフォーマンスを示す大容量レポー トを生成します。 また、Sybase Central の Sybase Monitor を使用して、サーバのステータスに 関するリアルタイム情報を取得することもできます。 各マニュアルは、システム管理者やデータベース管理者が利用する特定の情報 を重点的に説明するよう作成されています。 2 Adaptive Server Enterprise 第 2 章 オプティマイザの概要 この章では、Adaptive Server のクエリ・オプティマイザの概要と、クエリ がどのような手順で実行されるかについて説明します。 トピック名 定義 ページ 4 オブジェクトのサイズがクエリのチューニングにとって重要な理由 5 クエリの最適化 6 最適化のために調査される要素 8 前処理による最適化可能な句の追加 9 探索引数を作成するためのガイドライン 14 探索引数と有用なインデックス 15 ジョインの構文とジョイン処理 21 データ型の不一致とクエリの最適化 24 コスト計算の精度を高めるストアド・プロシージャ分割 32 コストの基本単位 33 この章では、個々のクエリ句のコストがどのように決定されるかについて 説明します。 「第 5 章 1 つのテーブルに対するアクセス・メソッドとクエリ・コスト計 算」では、これらのコストを使用して、どのように逐次テーブル・クエリ の論理 I/O コスト、物理 I/O コスト、I/O コスト合計を見積もるかを説明 しています。 「第 6 章 ジョインとサブクエリのアクセス・メソッドとコスト計算」では、 クエリが 2 つ以上のテーブルをジョインするとき、またはクエリにサブ クエリが含まれるときに、コストがどのように使用されるかを説明して います。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 3 定義 定義 オプティマイザは、解析され、正規化されたクエリとデータベース・オブジェ クトに関する情報を調べます。オプティマイザへ入力される情報は、解析され た SQL クエリと、クエリ内で指定されたテーブル、インデックス、カラムに 関する統計値です。オプティマイザから出力されるのは、 「クエリ・プラン」 です。 クエリ・プランは、コンパイルされたコードであり、クエリを実行するために 順序付けられた一連の手順が記述されています。各テーブルへのアクセス・メ ソッド ( テーブル・スキャンまたはインデックス・スキャン、使用するジョイ ンのタイプ、ジョイン順など ) も含まれます。 オプティマイザは、テーブルとインデックスに関する統計値を使用して、他の アクセス・メソッドを使用した場合のコストを予測し、特定のクエリを解析し ます。また、オプティマイザは、最適なクエリ・プラン、つまり I/O の観点か ら見て最もコストのかからないプランを見つけだします。多くのクエリには、 多くのクエリ・プラン候補があります。Adaptive Server は、最もコストのかか らないプランを選択し、そのプランをコンパイルして実行します。 クエリ処理の手順 Adaptive Server は、次の手順でクエリを処理します。 4 1 クエリを解析し、正規化します。パーサは SQL 構文が正しいことを確認 します。正規化は、クエリ内で参照されるすべてのオブジェクトが存在す ることを確認します。ユーザがクエリ内のすべてのテーブルとカラムにア クセスできるパーミッションを所持していることを確認します。 2 前処理として、いくつかの探索引数が最適化されたフォームに変更され、 最適化された探索引数とジョイン句が追加されます。 3 クエリが最適化されるときに、その各部分が分析され、最適なクエリ・プ ランが選択されます。最適化は次の処理で構成されます。 • 各テーブルの分析 • 探索引数またはジョイン・カラムに一致する、各インデックスの使用 コストの見積もり • ジョイン順とジョイン・タイプの選択 • 最終アクセス・メソッドの決定 4 選択したクエリ・プランをコンパイルします。 5 クエリを実行し、結果をユーザに返します。 Adaptive Server Enterprise 第2章 オプティマイザの概要 オプティマイザを活用する オプティマイザの目標は、あるクエリを処理するために必要な合計時間が少な いアクセス・メソッドをテーブルごとに選択することです。オプティマイザに よる選択は、クエリ対象のテーブルに関する統計値と、キャッシュ方式、キャッ シュ・サイズ、I/O サイズなどその他の要因に基づいています。また、オプティ マイザが意思決定に使用する重要なコンポーネントは、テーブル、インデック ス、カラムに関する統計値です。 状況によっては、オプティマイザが選択したアクセス・メソッドが正しくない ように見えることがあります。この原因は、不正確または不完全な情報 ( 古い 統計値など ) にある場合があります。また、さらに分析を進めて特殊なクエリ 処理オプションを使用することで、問題の原因を特定し、解決または回避でき る場合もあります。 クエリ・オプティマイザは、クエリの実行コストの尺度として I/O コストを使 います。次の I/O がクエリ処理の大部分を占めます。 • 物理 I/O。ページをディスクから読み込む必要がある場合に発生。 • 論理 I/O。キャッシュ内のページをクエリに対して読み込む場合に発生。 詳細については、 「アクセス・メソッド」と「クエリのコスト」を参照してく ださい。 オブジェクトのサイズがクエリのチューニングにとって重要な理由 クエリとシステムの動作を理解するためには、テーブルとインデックスのサイ ズを知る必要があります。チューニング作業のいくつかの段階の中では、次の 目的でサイズについての情報が必要になります。 • 特定のクエリ・プランに対応する statistics io のレポートについて理解する。 statistics io を使って、実行される I/O を調査する方法については、 『パ フォーマンス&チューニング・ガイド:モニタリングと分析』マニュアル の「第 4 章 set statistics コマンドの使用」を参照。 • オプティマイザによるクエリ・プランの選択について理解する。Adaptive Server のコストベースのオプティマイザは、使用する可能性がある各アク セス・メソッドの必要な物理 I/O と論理 I/O を見積もり、最もコストの低 いメソッドを選択する。特定のクエリ・プランが通常と異なっていると思 える場合は、dbcc traceon(302) を使うと、オプティマイザがそのプラン を選択した理由を確認できる。この出力には、ページ数の見積もりも含ま れる。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 5 クエリの最適化 • データベース・オブジェクトのサイズと、そのオブジェクトについて予想 される I/O パターンに基づいて、オブジェクトの配置を決定する。データ ベース・オブジェクトを複数のデータベース・デバイスに分散し、ディス クの読み込みと書き込みが均等に分散することによって、パフォーマンス を向上させることができる。 オブジェクトの配置については、 『パフォーマンス&チューニング・ガイ ド:基本』の「第 6 章 データの物理的配置の制御」を参照。 • パフォーマンスの変化について理解する。オブジェクト・サイズが大きく なると、パフォーマンス特性が変化する可能性がある。たとえば、ある テーブルが頻繁に使用され、常にキャッシュに格納されているとする。こ のテーブルが大規模になって、キャッシュに収まらなくなると、このテー ブルにアクセスするクエリのパフォーマンスが突然低下する可能性があ る。複数回のスキャンを必要とするジョインでは、特にその可能性が高い。 • キャパシティについて計画を立てる。新しいシステムを設計する場合、ま たは従来のシステムの拡張を計画する場合は、物理ディスクとメモリのプ ランニングのために、必要となる領域について知っておく必要がある。 • Adaptive Server Monitor と sp_sysmon の物理 I/O に関するレポートを理解 する。 サイズ管理の詳細については、『システム管理ガイド』を参照してください。 クエリの最適化 クエリの最適化を理解するには、クエリのパフォーマンスを向上できるかどう かを判断するために、クエリからデータベース・オブジェクトにアクセスする 仕組み、オブジェクトのサイズ、テーブルへのインデックスの設定について 知っておかなければなりません。 最適化の問題の兆候は、次のとおりです。 6 • あるクエリの動作が、インデックスとテーブル・サイズに基づく予想より も遅い。 • あるクエリの動作が同じようなクエリより遅い。 • あるクエリの動作が突然、通常よりも遅くなる。 • クエリを単体として処理する場合よりも、ストアド・プロシージャ内でク エリを処理する方が時間がかかる。 • インデックスが使えると予想される場合に、クエリ・プランがテーブル・ スキャンを使用することを示す。 Adaptive Server Enterprise 第2章 オプティマイザの概要 最適化の問題の原因には、次のようなものがあります。 • 統計値が更新されてから時間が経過しているため、実際のデータの分布 と、Adaptive Server がクエリの最適化に使用する値が一致しない。 • あるトランザクションによって参照されるローが、インデックス統計値に 反映されているパターンに合わない。 • テーブルの広い範囲のアクセスに 1 つのインデックスが使われている。 • where 句が、最適化に適さないフォームで記述されている。 • 重要なクエリに対する適切なインデックスが存在しない。 • あるストアド・プロシージャがコンパイルされた後に、基本となるテーブ ルに重大な変更が実行された。 SQL 抽出テーブルと最適化 1 つの SQL 文として表されるクエリでは、複数の SQL 文で表されるクエリよ りもオプティマイザが有効に活用されます。SQL 抽出テーブルを使用しない 場合には複数の SQL 文とテンポラリ・テーブルが必要になる状況でも、SQL 抽出テーブルを使用すると、特に中間集約結果を格納する必要がある場合に、 1 つの手順で簡単にクエリを表せます。次に例を示します。 select dt_1.* from (select sum(total_sales) from titles_west group by total_sales) dt_1(sales_sum), (select sum(total_sales) from titles_east group by total_sales) dt_2(sales_sum) where dt_1.sales_sum = dt_2.sales_sum ここでは、集約結果が SQL 抽出テーブル dt_1 と dt_2 から取得され、この 2 つ の SQL 抽出テーブル間でジョインが計算されます。すべての操作を 1 つの SQL 文で実行できます。 SQL 抽出テーブルの詳細については、『Transact-SQL ユーザーズ・ガイド』を 参照してください。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 7 最適化のために調査される要素 最適化のために調査される要素 クエリ・プランは、検索方式と、クエリが必要とするデータを検索するための 順序付けられた実行手順の集まりから構成されます。クエリ・プランを作成す るとき、オプティマイザは次のことを調べます。 • クエリの各テーブルの、ロー単位とデータ・ページ単位でのサイズ。読み 込む必要のあるオブジェクト・アロケーション・マップとアロケーショ ン・ページの数。 • クエリ内で使用されているテーブルとカラムに存在するインデックス、イ ンデックスの種類、それぞれのインデックスの高さ、リーフ・ページの 数、クラスタ率。 • インデックスがクエリをカバーするかどうか。つまり、データ・ページに アクセスしなくてもインデックスのリーフ・ページからデータを検索する ことによってクエリの要求を満たせるかどうか。Adaptive Server は、クエ リ内に where 句がなくても、クエリーをカバーするインデックスを使用 できる。 • インデックスのキーの密度と分布。 • 使用可能なデータ・キャッシュ ( 複数の場合もあり ) のサイズ、キャッシュ がサポートする I/O のサイズ、使用されるキャッシュ方式。 • 物理読み込みと論理読み込みのコスト。 • ジョイン句、最適なジョイン順とジョイン・タイプ。各ジョインに必要な スキャンのコストと回数を検討し、I/O 回数を制限するのにインデックス が利用できるかを検討する。 • ジョインに含まれる内部テーブルに有用なインデックスがない場合、ジョ イン・カラムのインデックスを使用してワークテーブル ( 内部テンポラ リ・テーブル ) を構築すると、テーブル・スキャンを繰り返すより高速化 するかどうか。 • テーブルをスキャンすることなく、インデックスを使用して値を見つけら れる max または min 集合関数がクエリ内にあるかどうか。 • ジョインなどのクエリを満たすために、データまたはインデックス・ペー ジを繰り返し必要とするかどうか。または、ページをスキャンする必要が 1 回しかないため、使い捨て方式を採用できるかどうか。 各プランごとに、オプティマイザが論理 I/O と物理 I/O を計算して合計コスト を算出します。Adaptive Server は、これに基づいて最もコストのかからないプ ランを採用します。 ストアド・プロシージャとトリガが最初に実行されるときに、そのオブジェク トが最適化され、クエリ・プランがプロシージャ・キャッシュ内に格納されま す。キャッシュ内にプランの使用していないコピーがある場合に、他のユーザ が同一のプロシージャを実行すると、コンパイルされたクエリ・プランは再コ ンパイルされるのではなく、キャッシュ内にコピーされます。 8 Adaptive Server Enterprise 第2章 オプティマイザの概要 前処理による最適化可能な句の追加 クエリが解析され正規化された後、オプティマイザが解析を始める前に、最適 化できる句の数を増やすための次のような前処理が行われます。 • いくつかの探索引数が、同等な引数に変換される。 • 探索引数として使用されている式のいくつかが前処理され、最適化可能な リテラル値が生成される。 • 探索引数に推移閉包が ( 可能であれば ) 適用される。 • ジョイン・カラムに推移閉包が ( 可能であれば ) 適用される。 • or を使用している一部のクエリに対して、別の最適化パスが得られるよう な探索引数が新しく生成される。 showplan、statistics io、dbcc traceon(302) などのクエリ・チューニング・ツー ルからの出力を調べる場合以外は、前処理によって加えられた変更はユーザに は知らされません。最適化した探索引数が追加されたクエリを実行すると、追 加された句が次のところに表示されます。 • dbcc traceon(302) の出力では、最適化するために追加された句のコスト のかかる追加ブロック。 • showplan の出力で、探索引数またはジョインを指定しなかったテーブル に “Keys are” というメッセージが表示されることがある。 句から同等な探索引数への変換 前処理では、探索引数 (SARG) で使われているフォームに変換できるクエリ句 を探します。表 2-1 に、これらの句を示します。 表 2-1: 句と同等な探索引数 句 between 変換 like パターンの最初の文字が定数の場合は、like 句を大なり条件または小なり条件を指定したクエリ に変換できる。たとえば、like "sm%" は >= "sm" と <"sn" に変換される。 >= 句と <= 句に変換。たとえば、between 10 and 20 は >= 10 and <= 20 に変換される。 最初の文字がワイルドカードの場合、like "%x" のような句は、インデックスを利用してアクセ スすることができない。ただし、ヒストグラム値は、一致するローの数の見積もりに使用される。 in (values_list) or クエリのリストに変換。たとえば、int_col in (1, 2, 3) は int_col = 1 or int_col = 2 or int_col = 3 に変換される。IN リスト内の最大要素数は 1025。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 9 前処理による最適化可能な句の追加 式から探索引数への変換 多くの式がリテラルな検索文字列に変換されてから、クエリが最適化されま す。次の例では、処理後の式を、dbcc traceon(302) の出力の探索引数分析で 表示される形式で示しています。 暗黙的変換 where 句の例 numeric_col = 5 処理後の式 numeric_col = 5.0 変換関数 int_column = convert(int, "77") int_column = 77 算術 salary = 5000*12 salary = 6000 0 数学関数 width = sqrt(900) width = 30 文字列関数 shoe_width = replicate("E", 5) shoe_width = "EEEEE" 文字列連結 full_name = "Fred" + " " + "Simpson" full_name = "Fred Simpson" 日付関数 week = datepart(wk, "5/22/99") week = 21 演算 注意 getdate() は最適化されない。 これらの変換を行うことにより、オプティマイザは、デフォルトの選択値を使 わずに、カラムのヒストグラム値を使用できるようになります。 次の例外があります。 • getdate 関数 • object_id や object_name などのほとんどのシステム関数 これらの関数は、最適化の前にリテラル値に変換されることはありません。 探索引数の推移閉包 前処理では、探索引数に対して、推移閉包を適用します。たとえば、次のクエ リでは、title_id 上の titles と titleauthor をジョインし、titles.title_id 上の探索引 数を包含します。 select au_lname, title from titles t, titleauthor ta, authors a where t.title_id = ta.title_id and a.au_id = ta.au_id and t.title_id = "T81002" 上記のクエリは、titleauthor.title_id 上の探索引数も包含しているように最適化 されます。 select au_lname, title from titles t, titleauthor ta, authors a where t.title_id = ta.title_id and a.au_id = ta.au_id and t.title_id = "T81002" and ta.title_id = "T81002" 10 Adaptive Server Enterprise 第2章 オプティマイザの概要 この句の追加により、オプティマイザは、titles.title_id 上のインデックス統計 値を使用して、titleauthor テーブル内の一致するローの数を見積もることがで きます。コストの見積もりの精度が高いほど、より効果的なインデックスと ジョイン順を選択することができます。 ジョイン推移閉包 ジョインの推移閉包がサーバ・レベルまたはセッション・レベルで有効な場 合、通常の等価ジョインのジョイン・カラムに推移閉包が前処理で適用されま す。次のクエリでは、t1.c11 と t2.c21 の等価ジョイン、t2.c21 と t3.c31 の等 価ジョインを指定しています。 select * from t1, t2, where t1.c11 and t2.c21 = and t3.c31 = t3 = t2.c21 t3.c31 1 ジ ョ イ ン の 推 移 閉 包 を 適 用 し な い と、唯 一 の ジ ョ イ ン 順 は、(t1, t2, t3)、 (t2, t1, t3)、(t2, t3, t1)、(t3, t2, t1) とみなされます。t1.c11 = t3.31 のジョインを 追加することによって、オプティマイザはジョインのリストを拡張します。可 能性としては、(t1, t3, t2) と (t3, t1, t2) が考えられます。そして、探索引数の推 移閉包により、t3.c31 = 1 と指定した条件を t1 と t2 のジョイン・カラムに適 用します。 前述のように、推移閉包は通常の等価ジョインにしか使用されません。次に対 しては、ジョインの推移閉包は適用されません。 • 非等価ジョイン。たとえば、t1.c1 > t2.c2。 • 式を含む等価ジョイン。たとえば、t1.c1 = t2.c1 + 5。 • or 句に含まれる等価ジョイン。 • 外部ジョイン。たとえば、t1.c11 *= t2.c2、left join、right join。 • サブクエリの境界を超えるジョイン。 • 参照整合性のチェックまたはビューの with check option で使用されるジョ イン。 • 互換性のないデータ型のカラム。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 11 前処理による最適化可能な句の追加 ジョインの推移閉包を有効にする システム管理者は、enable sort-merge joins and JTC 設定パラメータを使用し て、ジョインの推移閉包をサーバ・レベルで有効化できます。この設定パラ メータは、マージ・ジョインも有効にします。セッション・レベルでは、set jtc on を使用してジョインの推移閉包を有効にします。この設定は、サーバワ イドの設定より優先されます。ジョインの推移閉包の使用によりパフォーマン スが向上するクエリの種類については、 「ジョイン推移閉包の有効化と無効化」 (52 ページ ) を参照してください。 述部要素変形 述部要素変形は、オプティマイザの選択の幅を広げます。or でリンクされて いる述部ブロックから、and でリンクされている句を抽出して、最適化できる 句をクエリに追加します。最適化された追加の句は、クエリの実行に使用でき るアクセス・パスが他にもあることを示します。元の or 述部は、クエリの正 当性を確認するために保持されます。 述部変形は次の手順で行われます。 1 各 or 句内で完全一致を調べる簡単な述部 ( ジョイン、探索引数、in リス ト ) が抽出されます。例では、各ブロックで完全一致を調べている次の句 が抽出されます。 t.pub_id = p.pub_id between 句を、">= and <=" 句に変換してから述部変形を行います。クエ リ例では、両方のクエリ・ブロックで between 15 を使用しています ( た だし範囲の上限は異なっています )。同等の句が、手順 1 によって次のよ うに展開されます。 price >=15 2 同一テーブルの探索引数が抽出されます。展開においては、同一のテーブ ルを参照しているすべての条件を、1 つの述部として扱います。type と price はどちらも titles テーブルのカラムなので、抽出後の句は次のように なります。 (type = "travel" and price >=15 and price <= 30) or (type = "business" and price >= 15 and price <= 50) 3 in リストと or 句が抽出されます。ある 1 つのブロック内において、1 つ のテーブルに複数の in リストがある場合、最初のリストだけが抽出され ます。前述の例では、展開後のリストは次のようになります。 p.pub_id in ("P220", "P583", "P780") or p.pub_id in ("P651", "P066", "P629") 12 Adaptive Server Enterprise 第2章 オプティマイザの概要 4 ここまでの手順は並行して行われ、同じ句が抽出されることもあります が、重複している句は削除されます。 5 生成された条件がそれぞれ調べられ、最適化された探索引数またはジョイ ン句として使用できるかどうか判断されます。クエリ最適化に有効な条件 だけが保持されます。 6 展開によってできた新しい句は、ユーザによって指定された既存のクエリ 句に追加されます。 例 次に示すクエリ中の最適化された句は、すべて or 句で囲まれています。 select p.pub_id, price from publishers p, titles t where ( t.pub_id = p.pub_id and type = "travel" and price between 15 and and p.pub_id in ("P220", ) or ( t.pub_id = p.pub_id and type = "business" and price between 15 and and p.pub_id in ("P651", ) 30 "P583", "P780") 50 "P066", "P629") 先に説明したように、述部変形では、or でリンクされた句のブロックから and でリンクされた句を抜き出します。カッコで囲んだすべてのブロックに共通す る句だけが抽出されます。前述の例で、ある句が or でリンクされたブロックの うちの 1 つにだけあって他のブロックにない場合は、 その句は抽出されません。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 13 探索引数を作成するためのガイドライン 探索引数を作成するためのガイドライン クエリに探索引数を記述する場合は、次のガイドラインに従います。 • 探索句のカラム名を指定した側に、関数、算術演算子、その他の式を指定 しないようにします。可能ならば、関数やその他の演算子を、検索句の式 の側に移動します。 • 互換性のないデータ型を、ジョインされるカラムや、探索引数として使用 される変数とパラメータに対して指定しないようにします。 詳細については、 「データ型の不一致とクエリの最適化」(24 ページ ) を参 照してください。 • 複合インデックスの先行カラムを探索引数として使用します。セカンダ リ・キーを使った最適化では、先行カラム使用時よりパフォーマンスが低 下します。 • オプティマイザが使用できるような探索引数を、できる限り多く指定し ます。 • クエリの述部が、1 つのテーブルに対して 102 個を超えている場合は、最 も有効である可能性が高い句をクエリの先頭近くに配置します。最適化で は、各テーブルについて、先頭から 102 個の探索引数しか使用されないた めです ( ただし、すべての探索条件がローの修飾に使用されます )。 • > ( 大なり ) を使用しているクエリは、>= ( 以上 ) を使って書きなおすとパ フォーマンスが向上する場合があります。たとえば、次のクエリでは、 int_col にインデックスが作成されています。このインデックスを使用し て、int_col の値が 3 の最初の値を検出します。次に、さらにスキャンを 行って、3 より大きい最初の値を検出します。int_col の値が 3 のローが多 い場合は、サーバで多くのページをスキャンして、int_col の値が 3 より 大きい最初のローを検出しなければなりません。 select * from table1 where int_col > 3 このような場合は、次のように記述すると効率的にスキャンできます。 select * from table1 where int_col >= 4 文字列や浮動小数点データを扱う場合、この最適化は難しくなるので、 データを確認する必要があります。 14 • showplan の出力を調べて、どのキーとインデックスが使用されているか を確認します。 • 使用されるはずのインデックスが使用されていないと思われる場合は、 dbcc traceon(302) の出力を調べて、オプティマイザがインデックスを認 識しているか確認します。 Adaptive Server Enterprise 第2章 オプティマイザの概要 探索引数と有用なインデックス クエリの最適化に使用される述部 where 句と having 句を区別することは重要 です。この 2 つの句は、後のクエリ処理でも、返すローをフィルタするために 使用します。 where 句のカラムが先行のインデックス・キーに一致する場合、データ・ロー へのアクセス・パスを決めるために探索引数が使用されます。インデックス は、一致するデータ・ローを見つけて取り出すために使用されます。ローが、 データ・キャッシュの中から見つかるか、ディスクからデータ・キャッシュに 読み込まれると、残りの句がすべて適用されます。 次のクエリ例では、authors テーブルに au_lname のインデックスと city のイ ンデックスがある場合、一致するローを見つけるために、どちらのインデック スも使用できます。 select au_lname, city, state from authors where city = "Washington" and au_lname = "Catmull" オプティマイザは、統計値に基づいて、どのインデックスによるアクセスが最 もコストが低いかを判断します。ここで使用される統計値には、ヒストグラ ム、テーブル中のロー数、インデックスの高さ、インデックスのクラスタ率、 データ・ページのクラスタ率などがあります。インデックスの中からデータ・ ページへのアクセス・コストが最低になるものが選択されて、クエリの実行に 使用されます。次に、いったんアクセスされたデータ・ローには、その他の句 が適用されます。 探索引数の構文 探索引数 (SARG) は、次のいずれかの形式で表される式です。 <column> <operator> <expression> <expression> <operator> <column> <column> is null 上記のパラメータの意味は、次のとおりです。 • column にはカラム名しか指定できません。カラム名に関数、式、連結を 指定すると、カラム上のインデックスを使用できません。 • operator は、次のいずれかでなくてはなりません。 =, >, <, >=, <=, !>, !<, <>, !=, is null • expression には、次のように定数または定数を算出する式が入ります。オ プティマイザでインデックス統計値がどのように使用されるかは、式の値 がコンパイル時に決定されるかどうかで異なります。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 15 探索引数と有用なインデックス • expression が既知の定数か、前処理で既知の定数に変換される場合は、 その値と格納されているインデックスのヒストグラム値とを比較し、 正確なロー数の見積もりを返します。 • expression の値がコンパイル時に明らかでない場合、オプティマイザ は総密度を使用して、クエリによって返されるロー数を見積もりま す。クエリ・バッチ内に設定される変数の値や、ストアド・プロシー ジャ内に設定されるパラメータは、実行時まで認識されません。 • 式のデータ型とカラムのデータ型の間に互換性がない場合、インデッ クスは使用できないため考慮されません。 詳細については、 「データ型の不一致とクエリの最適化」(24 ページ ) を参照してください。 不等演算子 不等演算子 < > と != に対しては、特別な処理が行われます。オプティマイザ はカラムにインデックスがあればカバーリング・ノンクラスタード・インデッ クスを調べて、インデックスがクエリをカバーしている場合は、非マッチン グ・インデックス・スキャンを行います。インデックスがクエリをカバーして いない場合は、テーブル・スキャンによってテーブルにアクセスします。 探索引数の例 完全に最適化できる句の例を次に示します。これらのカラムに統計値がある場 合は、その統計値をクエリが返すロー数の見積もりに使用します。カラムにイ ンデックスがある場合は、インデックスを使用してデータにアクセスします。 au_lname = "Bennett" price >= $12.00 advance > $10000 and advance < $20000 au_lname like "Ben%" and price > $12.00 次の探索引数は最適化できません。 advance * 2 = 5000 /*expression on column side not permitted */ substring(au_lname,1,3) = "Ben" /* function on column name */ ただし、次のように記述すると、上の 2 つの句は最適化可能になります。 advance = 5000/2 au_lname like "Ben%" 次のクエリには、au_lname のインデックスだけがあります。 select au_lname, au_fname, phone from authors where au_lname = "Gerland" and city = "San Francisco" 16 Adaptive Server Enterprise 第2章 オプティマイザの概要 次の句は、以下の理由により探索引数です。 au_lname = "Gerland" • au_lname にインデックスがある。 • カラム名に対して、関数または他のオペレーションが指定されていない。 • 演算子が有効な探索引数演算子である。 • 定数のデータ型がカラムのデータ型に一致する。 city = "San Francisco" この句は、city カラムにインデックスがないため、上の条件のうち最初の条件 だけがあてはまりません。このような場合、au_lname 上のインデックスはク エリに使用されます。姓が一致するデータ・ページがすべてキャッシュ内に読 み込まれ、それぞれの一致したローに対して、その都市が検索基準と一致する かどうかが調べられます。 探索引数に統計値が使用される方法 インデックスを作成すると、統計値が生成されてシステム・テーブルに格納さ れます。探索引数とジョインのコストの判断に関連する統計値は、次のとおり です。 • インデックスに関する統計値。つまり、ページとローの数、インデックス の高さ、リーフ・ページの数、ロー・サイズの平均値。 • カラム内のデータに関する次の統計値。 • • インデックスの先行カラムのヒストグラム。ヒストグラムは、探索引 数の選択性、つまり、テーブルのローのうち与えられた値と一致する ものがいくつあるかを判断するために使用される。 • 密度値。インデックス内のキーの密度を示す。 クラスタ率。データ記憶領域の断片化の程度と大容量 I/O の効果を表す。 クエリの処理中は、これらの統計値のサブセット (たとえばリーフ・ページの 数 ) だけが更新されます。その他の統計値は、update statistics を実行したとき か、インデックスを削除して再作成したときにだけ更新されます。これらの統 計値は、optdiag を使用して表示できます。 詳細については、 『パフォーマンス&チューニング・ガイド:モニタリングと 分析』マニュアルの「第 6 章 統計テーブルおよび optdiag を使った統計の表示」 を参照してください。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 17 探索引数と有用なインデックス ヒストグラム・セル インデックスを作成したときに、インデックスの最初のカラムにヒストグラム が作成されます。ヒストグラムには、カラムの分布値に関する情報が格納され ます。そのため、update statistics を使って、複合インデックスのマイナー・ キーの統計値と、インデックスなしの検索句で使用されるカラムの統計値を生 成できます。 カラムのヒストグラムには、一連の手順またはセルにデータが含まれていま す。セルの数は、インデックスの作成時、または update statistics の実行時に 指定できます。各セルに対して、ヒストグラムにカラム値とセルの重みが保管 されます。 ヒストグラムのセルには、次の 2 種類があります。 • 「頻度セル」。カラム内の重複度の高さを示します。頻度セルの重みとテー ブル内のロー数を掛け合わせた数が、そのセルの値と一致するテーブル内 のローの数になります。カラムに高い重複度がない場合は、ヒストグラム には範囲セルしか存在しません。 • 「範囲セル」。値の範囲を示します。範囲セルの重みと範囲セル密度は、探 索引数の値が範囲セル内にある場合に、返されるロー数の見積もりに使用 されます。 ヒストグラムの詳細については、 『パフォーマンス&チューニング・ガイド:モ ニタリングと分析』の「ヒストグラムの内容」(138 ページ ) を参照してください。 密度値 密度とは、インデックス内に重複キーが存在する平均比率を表します。有効な 値の範囲は 0 ~ 1 です。N 個のローを持ち、キーがユニークであるインデック スの密度は 1/N です。また、キーがすべて重複しているインデックスの密度は 1 になります。 複数のキーを持つインデックスの場合は、インデックス内のキーの各プレフィ クスについて密度値がそれぞれ計算され、格納されます。カラム A、B、C、D のインデックスでは、次のカラムの組み合わせについて、密度がそれぞれ格納 されます。 18 • A • A、B • A、B、C • A、B、C、D Adaptive Server Enterprise 第2章 オプティマイザの概要 範囲セル密度と総密度 各プレフィクス・サブセットに、次の 2 種類の密度値が保管されます。 • 範囲セル密度。探索引数で使用される。 • 総密度。ジョインで使用される。 範囲セル密度は、ヒストグラムの範囲セルで示されるすべての値について重複 平均値を表します。総密度は、頻度セルと範囲セルのすべての値の重複平均値 を表します。ジョインに対して一致するロー数や、クエリ最適化時に値が未定 の探索引数に対して一致するロー数の見積もりに、総密度が使用されます。 オプティマイザが密度とヒストグラムを使用する方法 オプティマイザが探索引数を分析するときは、ヒストグラム値、密度、テーブ ル内のロー数を使用して、探索引数で指定された値と一致するロー数を次のよ うに見積もります。 • 探索引数の値が頻度セルの値と一致する場合、一致するローの見積もり数 は、頻度セルの重みにテーブル内のロー数を掛けた値と等しくなります。 次のクエリは、データ値に重複が多いので、頻度セルに一致します。 where authors.city = "New York" 頻度セルの重みが 0.015606 で、authors テーブルに 5000 ローある場合、 オプティマイザはクエリが返すロー数を 5000 * 0.015606 = 78 と見積もり ます。 • 探索引数の値が範囲セル内に収まる場合、オプティマイザは範囲セル密度 を使用してロー数を見積もります。たとえば、city の値が範囲セル内にあ り、カラムの範囲セル密度が 0.000586 であるクエリでは、返されるロー 数は 5000 * 0.000586 = 3 と見積もられます。 • 範囲クエリには、オプティマイザが、値の範囲に含まれるすべてのセルの 重みを加算します。範囲の開始値または終端値のどちらかが範囲セルにあ る場合、オプティマイザは補間を使用して、その範囲に含まれるセルの ロー数を見積もります。 複数の探索引数における統計値の使用 同一のテーブルに複数の探索引数がある場合、オプティマイザは統計値を使用 して、探索引数の選択性を結合します。 次のクエリでは、テーブル内の 2 つのカラムに対して探索引数を指定します。 select title_id from titles where type = "news" and price < $20 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 19 探索引数と有用なインデックス type と price のインデックスを使用して、選択性がさまざまな値に見積もられ ます。これは、price に対する統計値が作成されているかどうかによって、次 のように異なります。 type の統計値だけの場合、オプティマイザは、type の頻度セルの重みと price の選択性のデフォルト値を使用します。type の選択性が 0.106600 で、 不等号を使用した範囲クエリのデフォルトの選択性は 33% です。このク エリに返されるロー数は、0.106600 * 0.33、つまり 0.035178 を使用して見 積もります。テーブル内のロー数が 5000 の場合、見積もりは 171 ローに なります。 • 統計値がない場合に使用されるデフォルト値については、表 2-2 を参照し てください。 price の統計値もある場合、そのヒストグラムを使用して、price の探索引 数と一致するローが 0.133334 であると見積もります。この値に type の選 択性を掛けると 0.014213 になり、返されるロー数の見積もりは 71 になり ます。 • このクエリに実際に返されるローの数は 53 ですが、さらに他の統計値を使用 すると正確さが向上します。この例のシングル・テーブル・クエリでは、より 正確な選択性を使用しても、type と price のインデックスを使用するというア クセス・メソッドは変更されませんでした。ただし、統計値を追加すること で、テーブル・スキャンや他のインデックスの使用について、オプティマイザ がより良い選択を行えるシングル・テーブル・クエリもあります。ジョイン・ クエリでは、各テーブルの統計値が正確であるほど、より効率的なジョイン順 が選択されます。 探索引数のデフォルト値 探索引数に対して統計値が使用できないときや、最適化時に探索引数の値が未 定のときは、オプティマイザはデフォルト値を使用します。そのデフォルト値 を表 2-2 に示します。 表 2-2: 不定探索引数に適用する密度概数値 演算の種類 等号 不等号 閉じた範囲 20 演算子 = <, <=, > または >= between 密度概数値 総密度 ( カラムの統計値が使用可能な 場合 )、または 10% 33% 25% Adaptive Server Enterprise 第2章 オプティマイザの概要 変数とパラメータを使用する探索引数 オプティマイザによる見積もりはクエリの実行前に行われるので、オプティマ イザはバッチまたはプロシージャ内で設定される変数値を考慮できません。コ ンパイル時に変数値が不明の場合、オプティマイザは表 2-2 に示したデフォル ト値を使用します。 次の例では、@city の値をバッチ内で設定します。 declare @city varchar(25) select @city = city from publishers where pub_name = "Brave Books" select au_lname from authors where city = @city オプティマイザは、総密度 0.000879 を使用して、返されるローを 4 つと見積 もりますが、実際に返されるローの数はもっと大きくなると予想されます。 同じような問題が、ストアド・プロシージャ内に変数値を設定する場合にも起 こります。この場合は、プロシージャを分割するとパフォーマンスが向上しま す。まず、最初のプロシージャで変数を設定してから、その変数をパラメータ として渡して 2 番目のプロシージャを呼び出します。これで、2 番目のプロ シージャは、正しく最適化されます。 この例については、 「コスト計算の精度を高めるストアド・プロシージャ分割」 (32 ページ ) を参照してください。 ジョインの構文とジョイン処理 ジョイン句の形式は次のとおりです。 table1.column_name <operator> table2.column_name ジョインの演算子は次のとおりです。 =, >, >=, <, <=, !>, !<, !=, <>, *=, =* 次のように記述します。 table1 on table1 on [ left | right ] join table2 column_name = column_name inner join table2 column_name = column_name ジョインを最適化する場合、オプティマイザはカラム名のインデックスだけを 考慮します。カラム名の結合にどのような演算子や式を使用しても、可能なア クセス・メソッドとしてカラムのインデックスの使用が評価されることはあり ません。ジョイン内のカラムがデータ型に互換性がない場合、オプティマイザ は 1 つのカラムの 1 つのインデックスだけを検討します。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 21 ジョインの構文とジョイン処理 ジョインの処理のしくみ オプティマイザは、ジョイン・クエリのクエリ・プランを作成するときに次の ことを実行します。 • 使用できるインデックスとテーブル・スキャンに必要な I/O を見積もるこ とによって、各テーブルのインデックスを評価する。 • 可能なジョイン順の合計コスト見積もりの判断に基づいて、ジョイン順を 決定する。ネストループ・ジョインとソートマージ・ジョインの両方のコ ストを見積もる。 • ジョインの内部テーブルに効果的なインデックスがない場合は、オプティ マイザはテンポラリ・インデックスを構築すること、つまり「再フォー マット」と呼ばれる処理を行うことを決定する。 詳細については、 「再フォーマット方式」(125 ページ) を参照してください。 • I/O サイズとキャッシュ方式を決定する。 • 並列クエリ処理が有効である場合、逐次実行のコストと並列実行のコスト を比較する。 詳細については、 「第 8 章 並列クエリ最適化」を参照してください。 適切なインデックス設定、探索引数の選択性、キーの密度など、1 つのテーブ ルでの選択コストを決定する要因は、ジョインに対しては重要度が著しく増し ます。 ジョインに対し統計値が使用できないとき ジョイン内のカラムに対して統計値が使用できない場合は、オプティマイザは 次のデフォルト値を使用します。 演算子の種類 例 選択性のデフォルト値 等号 t1.c1 = t1.c2 不等号 t1.c1 t1.c1 t1.c1 t1.c1 > t1.c2 >= t1.c2 < t1.c2 <= t1.c2 1/ 小さい方のテーブル のロー数 33% 次のクエリ例では、いずれの city カラムにも統計値がない場合に、オプティマ イザが、両方のテーブルに対するジョイン選択性として 1/500 を使用します。 その結果、stores テーブルは 500 ローを、authors テーブルは 5000 ローを所持 します。 select au_fname, au_lname, stor_name from authors a, stores s where a.city = s.city 22 Adaptive Server Enterprise 第2章 オプティマイザの概要 密度値とジョイン ジョイン・カラムの統計値が使用できる場合、各ジョイン・キーと一致する ロー数の見積もりには総密度が使用されます。authors テーブルのロー数が 5000 で、city カラムの総密度が 0.000879 である場合は、オプティマイザは 5000 * 0.000879 = 4 と計算します。つまり、city カラムのジョインが他のテーブルの ローと一致するたびに authors から 4 つのローが返されると見積もります。 複数カラムのジョイン 1 つのジョイン・クエリが 2 つのテーブルから複数のジョイン・カラムを指定 し、これらのカラムに複合インデックスがある場合は、複合総密度が使用され ます。たとえば次のクエリで、authors と publishers のそれぞれに city と state のインデックスがある場合、各テーブルに対して city と state の複合総密度が 使用されます。 select au_lname, pub_name from authors a, publishers p where a.city = p.city and a.state = p.state 1 つのテーブルにある探索引数とジョイン 探索引数とジョインが 1 つのテーブルにある場合、ジョインのコスト計算時に カラムの選択性が結合されて、ロー数がより正確に見積もられます。 次の例では、city カラムと state カラムの両方で authors と stores をジョイン します。authors テーブルの state カラムに探索引数があるため、探索引数の 推移閉包によって stores テーブルの state カラムにも探索引数が次のように追 加されます。 select au_fname, au_lname, stor_name from authors a, stores s where a.city = s.city and a.state = s.state and a.state = "GA" 各テーブルの city 上にインデックスはあるが state に対して使用できる統計値 が存在しない場合、オプティマイザは、city に対して総密度と結合した探索引 数の選択性のデフォルト値 (10%)を使用します。これにより、このクエリの 探索引数に一致するロー数が過大に見積もられます。また、さらに多くのロー が state の探索引数と一致する場合は、ロー数が過小に見積もられます。各テー ブルの state に統計値がある場合、条件を満たすローの見積もり数は正確にな り、ジョイン・クエリのコスト計算も全体的に精度が上がります。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 23 データ型の不一致とクエリの最適化 データ型の不一致とクエリの最適化 使用されるはずのインデックスをクエリが使っていない場合は、一般にデータ 型の不一致が問題になります。データ型の不一致は、次のところで起こります。 • カラムの代わりに、異なるデータ型を持つ変数またはストアド・プロシー ジャ・パラメータを使用している探索句。次に例を示します。 where int_col = @money_parameter • データ型の異なるカラムでジョインされたジョイン・クエリ。次に例を示 します。 where tableA.int_col = tableB.money_col データ型の不一致によって、オプティマイザがインデックスを考慮できない場 合、最適化するうえで問題が起こります。一般的に問題となるのは次の場合です。 • 整数型の int、smallint、tinyint 間での比較 • money と smallmoney の比較 • datetime と smalldatetime の比較 • 精度と位取りが異なる numeric 型と decimal 型の比較 • numeric 型または decimal 型と、整数または通貨カラムの比較 問題が起こらないように、テーブルを作成するときには、ジョインの対象とな りそうなカラムに対し、同じデータ型 ( 精度と位取りも同じにする ) を使用し てください。探索引数として使用される変数やストアド・プロシージャ・パラ メータには、一致するデータ型を使用してください。以降の項では、同じデー タ型を使用しなかった場合に適用される規則と考慮事項について、詳しく説明 します。また、トラブルシューティングのヒントについても取り上げます。 24 Adaptive Server Enterprise 第2章 オプティマイザの概要 データ型の階層とインデックスの問題に関する概要 探索引数またはジョイン・カラムが異なるデータ型の場合、データ型階層がイ ンデックスの使用を制御します。次のクエリでは、hierarchy 値とデータ型の 名前が出力されます。 select hierarchy, name from systypes order by 1 hierarchy name --------- -----------------------------1 floatn 2 float 3 datetimn 4 datetime 5 real 6 numericn 7 numeric 8 decimaln 9 decimal 10 moneyn 11 money 12 smallmoney 13 smalldatetime 14 intn 15 int 16 smallint 17 tinyint 18 bit 19 univarchar 20 unichar 21 reserved 22 varchar 22 sysname 22 nvarchar 23 char 23 nchar 24 varbinary 24 timestamp 25 binary 26 text 27 image ユーザ定義データ型が作成されている場合、このクエリでそのデータ型の該当 した階層値のところにリストされます。 一般的な規則として、異なるデータ型が使用された場合、systypes.hierarchy 値によって、インデックスを使用できるかどうかが決まります。 • 探索引数の場合。カラムのデータ型が、パラメータまたは変数の hierarchy 値に等しいか上位ならば、そのインデックスは考慮される。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 25 データ型の不一致とクエリの最適化 • ジョインの場合。そのカラムの systypes.hierarchy 値が、階層内の他のカ ラムの値と比べて、等しいか階層の上位にある場合のみ、インデックスが 考慮される。 • char データ型と unichar データ型を同時に使用すると、char が unichar に 変換される。 例外は次のとおりです。 • char 型と varchar 型、 unichar 型と univarchar 型、 または binary 型と varbinary 型の比較。たとえば、char カラムと varchar カラムの hierarchy 値はそれぞ れ 22 と 23 ですが、インデックスの評価では、それらは同じデータ型とし て扱われます。次のジョインでは、どちらのカラムに対してもインデック スが考慮されます。 where t1.char_column = t2.varchar_column NULL 値が承認される char カラムは varchar として格納されますが、ジョ インのどちらのカラムに対してもインデックスが使用されます。 • null 型のカラムは規則に影響しない。つまり、float と floatn は異なる階層 値を持っていますが、これらは常に同じデータ型として扱われます。 • decimal 型または numeric 型の比較は、精度と位取りも影響する。numeric 型と decimal 型を比較する場合、numeric 型または decimal 型を他のデー タ型 (int、money など ) と比較する場合も含まれます。 詳細については、 「Numeric データ型と Decimal データ型の比較」(26 ペー ジ ) を参照してください。 Numeric データ型と Decimal データ型の比較 クエリが numeric 型または decimal 型のカラムをジョインするとき、次の 2 つ の条件を満たす場合はインデックスを使用できます。 • ジョインの対象となるカラムの位取りが、他のジョイン・カラムの位取り と等しいかそれより大きい。 • カラムの整数部の長さが、他のカラムの整数部の長さと等しいかそれより 長い。 次に、インデックスが考慮される場合の例をいくつか示します。 26 ジョインされるデータ型 考慮されるインデックス numeric(12,4) と numeric(16,4) numeric(16,4) のインデックスだけが考慮される。 numeric(12,4) の整数部の方が小さいため。 numeric(12,4) と numeric(12,8) どちらのインデックスも考慮されない。整数部は numeric(12,8) の方が、位取りは numeric(12,4) の方 が小さいため。 numeric(12,4) と numeric(12,4) どちらのインデックスも考慮される。 Adaptive Server Enterprise 第2章 オプティマイザの概要 Numeric 型と他のデータ型の比較 numeric 型のカラムや decimal 型のカラムを、他の数値データ型 (money また は int など ) のカラムと比較する場合は、次のように扱われます。 • numeric と decimal は 整数カラムや通貨カラムより階層の上位にあるの で、numeric カラムまたは decimal カラムのインデックスだけが考慮さ れる。 • numeric または decimal のインデックスが考慮されるには、精度と位取り の必要条件が満たされている必要がある。numeric カラムの位取りは、整 数カラムまたは通貨カラムの位取り以上でなくてはなりません。また、 numeric カラムの整数部の桁数は、整数カラムまたは通貨カラムで使用で きる最大桁数以上でなくてはなりません。 整数型データと通貨型データの精度と位取りを、表 2-3 に示します。 表 2-3: 整数型および通貨型の精度と位取り データ型 tinyint 精度、位取り 3,0 smallint 5,0 int 10,0 smallmoney 10,4 money 19,4 探索引数として使用されるパラメータおよび変数のデータ型 変数またはストアド・プロシージャ・パラメータを探索引数として使用する場 合、それらのデータ型とカラムのデータ型を宣言時に一致させて、確実にイン デックスが使用できるようにしてください。次に例を示します。 declare @int_var int select @int_var = 50 select * from t1 where int_col = @int_var インデックスの使用は、階層におけるデータ型の優先度によって決まります。 カラムのインデックスは、カラムのデータ型が変数のデータ型より優先度が高 い場合にだけ使用されます。たとえば、int は smallint や tinyint より優先度が 高いです。整数型だけを抜き出してみると、次のようになります。 hierarchy --------15 16 17 name -----------------------------int smallint tinyint パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 27 データ型の不一致とクエリの最適化 変数またはパラメータのデータ型が smallint または tinyint の場合、データ型が int のカラムのインデックスだけがクエリに使用されます。tinyint のカラムの インデックスは、int のパラメータに対して使用できません。 同様に、money は int より優先度が高いので、データ型が money の変数また はパラメータを int カラムと比較する場合、int カラムのインデックスは使用で きません。 これにより、トランケーションまたはオーバフローによって発生する問題が回 避されます。次のクエリ例のような、int_col のインデックスを使用するため に、money の値を 5 にトランケートすることは、有効でも正しくもありません。 declare @money_var money select @money_var = $5.12 select * from t1 where int_col = @money_var 探索引数のデータ型不一致に関するトラブルシューティング インデックスを持ったカラムの探索引数でデータ型の不一致問題が発生する と、クエリは他の探索引数がある場合には他のインデックスを使用するか、ま たはテーブル・スキャンを実行します。showplan の出力には、クエリの各テー ブルで使用されているアクセス・メソッドとキーが表示されます。 また、dbcc traceon(302) を使用して、インデックスが考慮されているかどう かを確認できます。たとえば、int_col で整数変数を探索引数として使用する と、出力は次のようになります。 Selecting best index for the SEARCH CLAUSE: t1.int_col = unknown-value SARG is a local variable or the result of a function or an expression, using the total density to estimate selectivity. Estimated selectivity for int_col, selectivity = 0.020000. 整数カラムの探索引数として使用される変数に money 型などの互換性のない データ型を使用すると、dbcc traceon(302) の出力に “Selecting best index for the SEARCH CLAUSE” ブロックは表示されません。これは、インデックスが考慮 されていないため、使用されないことを示します。インデックスがクエリ内で 予測したとおりに使用されてない場合、デバッグの第一段階として、このコス ト計算の項目を dbcc traceon(302) の出力から探してください。 前述の例には、“unknown-value” ( 不定値 ) という表示があり、また、この探索 引数に一致するロー数の見積もりに総密度が使用されています。これは、変数 の値がバッチの段階で設定されるためであり、データ型の不一致とは別の問題 です。 詳細については、 「変数とパラメータを使用する探索引数」(21 ページ ) を参照 してください。 28 Adaptive Server Enterprise 第2章 オプティマイザの概要 ジョイン・カラムで互換性のあるデータ型 オプティマイザがジョイン・カラムのインデックスを考慮するのは、カラムの データ型がすべて等しいときか、データ型の階層内で、そのジョイン・カラム の方が他のカラムより優先度が高いときに限られます。そのため、オプティマ イザは、ある 1 つのジョイン・カラムについてだけインデックスの使用を考慮 し、ジョイン順の選択が制限されることになります。 たとえば、次のクエリでは decimal と int のデータ型のカラムをジョインして います。 select * from t1, t2 where t1.decimal_col = t2.int_col decimal は int より階層での優先度が高いので、 オプティマイザは t1.decimal_col のインデックスだけを考慮でき、t2.int_col のインデックスは使用できません。 このため、t2 のテーブル・スキャンを行ってから t1.decimal_col のインデック スを使用する、ということが起こります。 表 2-4 に、一般的に問題があるデータ型のインデックス選択に、階層がどのよ うに影響するかを示します。 表 2-4: カラムのデータ型が一致しないときに考慮されるインデックス ジョイン・カラムのデータ型 money、smallmoney インデックスが考慮されるカラムのデータ型 money datetime、smalldatetime datetime int、smallint int int、tinyint int smallint、tinyint smallint ジョインのデータ型不一致に関するトラブルシューティング データ型の不一致によってジョインの片方にインデックスが使用されていな いと思われる場合は、dbcc traceon(302) を使用し、出力から “Selecting best index for the JOIN CLAUSE” の項目を探します。データ型に互換性があるなら ば、各ジョインに以下のような 2 ブロックが出力されます。 Selecting best index for the JOIN CLAUSE: t1.int_col = t2.int_col ジョインのもう一方のテーブルについては、この後次のように出力されます。 Selecting best index for the JOIN CLAUSE: t2.int_col = t1.int_col decimal カラムと int カラムの比較のように、互換性のないデータ型を比較す るクエリでは、このブロックは次のように 1 つしか表示されません。 Selecting best index for the JOIN CLAUSE: t1.decimal_col = t2.int_col パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 29 データ型の不一致とクエリの最適化 これは、t2.int_col のインデックスを外部カラムとして使用する場合のジョイ ン・コスト計算が、実行されないことを示しています。 データ型と比較についてのアドバイス データ型の不一致の問題を避けるためのポイントは次のとおりです。 • テーブル作成時、ジョインするカラムのデータ型を同じにする。 • 頻繁にジョインされる 2 つのテーブルのカラムが異なるデータ型を持つ 場合、alter table...modify を使用してデータ型を一方のカラムに揃えるこ とを検討する。 • 探索引数として使用される変数またはストアド・プロシージャ・パラメー タを宣言するときは、必ずカラムのデータ型を使用する。 • ユーザ定義データ型の定義を検討する。sp_addtype を使用して定義を作 成しておけば、これらの定義は create table、alter table、create procedure などのコマンドで使用でき、さらにデータ型の宣言にも使用できる。 • データ型の不一致によりパフォーマンス問題が生じているクエリでは、変 換関数を使用してジョインの他のテーブルのインデックスを考慮できる。 この対処法については、次の項で説明する。 ジョインの対象となるデータ型の強制的な変換 どうしても異なるデータ型同士をジョインしなければならず、このジョインに よってパフォーマンスが低下する場合、クエリによっては、ジョイン対象の一 方を他方のデータ型に強制的に変換できることがあります。次の例では、 smallmoney_col のインデックスを使用できないため、クエリが huge_table の テーブル・スキャンを実行します。 select * from tiny_table, huge_table where tiny_table.money_col = huge_table.smallmoney_col huge_table.smallmoney_col のインデックスが使用できれば、パフォーマンス は向上します。次のクエリでは、小さいテーブルの money カラムに convert 関数を使用すると、大きいテーブルのインデックスが使えるようになります。 また、テーブル・スキャンは小さいテーブルに対して行われます。 select * from tiny_table, huge_table where convert(smallmoney,tiny_table.money_col) = huge_table.smallmoney_col 30 Adaptive Server Enterprise 第2章 オプティマイザの概要 tiny_table.money_col が大きいので smallmoney への変換中にデータ型の変換 エラーが発生する可能性があるため、この方法では tiny_table.money_col に値 がないことを前提としています。smallmoney の最大値より大きい値がある場 合、この解決法を利用するために、smallmoney カラムの最大値を指定する探 索引数を追加することで対処します。それは、次のようになります。 select smallmoney_col, money_col from tiny_table , huge_table where convert(smallmoney,tiny_table.money_col) = huge_table.smallmoney_col and tiny_table.money_col <= 214748.3647 浮動小数点データと数値データを変換すると、意味が変わるクエリもありま す。次のクエリは、整数と浮動小数点数値を比較します。 select * from tab1, tab2 where tab1.int_column = tab2.float_column このクエリでは int_column のインデックスは使用できません。この変換では インデックス・アクセスを強制的に tab1 にしていますが、次のように convert を使用していないクエリとは異なる結果が返されます。 select * from tab1, tab2 where tab1.int_col = convert(int, tab2.float_col) たとえば、int_column が 4 で float_column が 4.2 の場合、変更後のクエリでは、 後者を暗黙的に 4 に変換し、元のクエリでは返さなかったローを返します。こ の対処方法は、次のセルフジョインを追加することによって実行できます。 and tab2.float_col = convert(int, tab2.float_col) この対処方法は、tab2.float_col のすべての値を、変換エラーなく int に変換で きることを前提としています。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 31 コスト計算の精度を高めるストアド・プロシージャ分割 コスト計算の精度を高めるストアド・プロシージャ分割 オプティマイザは、実行時にならないと @city の値がわからないため、次のプ ロシージャの最後にある select で統計値を使えません。 create procedure au_city_names @pub_name varchar(30) as declare @city varchar(25) select @city = city from publishers where pub_name = @pub_name select au_lname from authors where city = @city 次に、プロシージャを 2 つのプロシージャに分割する例を示します。最初のプ ロシージャが 2 番目のプロシージャを呼び出します。 create procedure au_names_proc @pub_name varchar(30) as declare @city varchar(25) select @city = city from publishers where pub_name = @pub_name exec select_proc @city create procedure select_proc @city varchar(25) as select au_lname from authors where city = @city 2 番目のプロシージャの実行時に、Adaptive Server は @city の値を認識するた め、select 文を最適化できるようになります。ただし、2 番目のプロシージャ で @city の値を修正してから select 文で使用する場合、オプティマイザは、プ ロシージャ開始時点での @city の値に基づいてクエリを最適化するため、誤っ たプランを選んでしまいます。2 番目のプロシージャの実行のたびに @city の 値が変化する場合、まったく異なるクエリ・プランが選ばれることがあるた め、with recompile の使用をおすすめします。 32 Adaptive Server Enterprise 第2章 オプティマイザの概要 コストの基本単位 オプティマイザがクエリのコストを見積もる場合、2 つの要因が考慮されます。 1 つは物理 I/O ( ディスクからのページ読み込み ) のコスト、もう 1 つは論理 I/O ( データ・キャッシュ内でのページ検索 ) のコストです。オプティマイザでは、 物理 I/O のコストとして 18、論理 I/O のコストとして 2 を割り当てています。 これらの数字は、コストの相対的な単位であり、ミリ秒やクロック・チックな どの時間の単位を表すものではありません。これらの単位は、この章の計算式 の中では、物理 I/O のコスト、論理 I/O のコストの順で使用されます。テーブ ルへのアクセスにかかる合計コストは、次のように表すことができます。 コスト = 物理 I/O の回数 *18 + 論理 I/O の回数 *2 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 33 コストの基本単位 34 Adaptive Server Enterprise 第 3 章 高度な最適化ツール この章では、オプティマイザが選択するジョイン順、インデックス、I/O サイズ、キャッシュ方式に影響する、クエリ処理のオプションについて説 明します。 トピック名 特殊な最適化手法 ページ 35 オプティマイザのオプションを指定する 36 非同期ログ・サービス 48 ジョインでのテーブル順序を指定する 37 オプティマイザが検討するテーブル数を指定する 39 クエリにインデックスを指定する 40 クエリに I/O サイズを指定する 42 キャッシュ方式を指定する 45 大容量 I/O とキャッシュ方式の制御 47 非同期ログ・サービス 48 マージ・ジョインの有効化と無効化 51 ジョイン推移閉包の有効化と無効化 52 クエリの並列度の指定 53 小さいテーブルの同時実行性の最適化 55 特殊な最適化手法 『パフォーマンス&チューニング・ガイド:基本』に記載されている情報 に精通すると、この章の内容を理解するのに役立ちます。ツールの使用に より Adaptive Server オプティマイザが決定した内容が上書きされ、使用法 を誤るとパフォーマンスに重大な悪影響を及ぼすので、注意してくださ い。各クエリのパフォーマンスとシステム全体のパフォーマンスの両方に 対する影響について理解する必要があります。 Adaptive Server のオプティマイザは、コストベースの高度なオプティマ イザであり、ほとんどの状況で適切なクエリ・プランを生成します。た だし、オプティマイザが最適なパフォーマンスを得るための適切なイン デックスを選択しなかったり、最良ではないジョイン順を選択したりす る場合があるため、クエリに使用するアクセス・メソッドを制御する必 要があります。この章で説明するオプションを使うと、こうした制御が できます。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 35 オプティマイザのオプションを指定する また、チューニング時に、異なるジョイン順、I/O サイズ、またはキャッ シュ方式の効果の確認が必要になる場合もあります。この章で説明するオ プションの中には、手間をかけて再構成をしなくてもクエリ処理方式また はアクセス・メソッドを指定できるものがあります。 Adaptive Server は、クエリ最適化に影響するツールやクエリ句、およびオ プティマイザが選択した最適化方法を知ることができる優れたクエリ分 析ツールを提供します。 注意 この章では、特定の最適化の問題に対する回避方法も説明します。説 明に該当するような問題が発生した場合は、Sybase の保守契約を結んでい るサポート・センタに連絡して、問題に関する情報を知らせてください。 オプティマイザのオプションを指定する Adaptive Server では、クエリ・バッチやクエリのテキストにコマンドを入 力して、以下のような最適化のオプションを指定できます。 • ジョインでのテーブルの順序 • ジョイン最適化中に同時に評価されるテーブルの数 • テーブル・アクセスに使われるインデックス • I/O サイズ • キャッシュ方式 • 並列度 まれに、オプティマイザが最適なプランを選択できない場合があります。 このような場合、 「最適な」プランよりもほんのわずかだけコストがかか るプランが選択されることがあるため、強制的に選択されたこれらのオプ ションを維持、調節するコストと、最適なプランより低いパフォーマンス とをよく比較検討する必要があります。 ジョイン順、インデックス、I/O サイズ、またはキャッシュ方式を指定す るコマンドを statistics io、showplan などのクエリ・レポート・コマンド と組み合わせて使うと、オプティマイザがその選択を行った理由を判断で きます。 36 Adaptive Server Enterprise 第3章 高度な最適化ツール 警告! この章で説明するオプションは注意して使ってください。強制の オプションによってオプティマイザが選ぶクエリ・プランは、状況によっ ては不適切であり、パフォーマンスを著しく低下させる場合があります。 アプリケーションにこれらのオプションを含める場合は、クエリ・プラ ン、I/O 統計値などのパフォーマンス・データを定期的にチェックしてく ださい。 一般的には、これらのオプションはチューニングや動作確認のためのツー ルとして使用するもので、最適化の問題に対する長期的な解決策として使 用するものではありません。 ジョインでのテーブル順序を指定する Adaptive Server は、I/O を最小限に抑えるためにジョイン順を最適化します。 ほとんどの場合、オプティマイザが選択する順序は、select コマンドの from 句の順序と一致しません。指定した順序どおりに Adaptive Server がテーブ ルにアクセスするようにするには、次のコマンドを使います。 set forceplan [on|off] この場合でも、各テーブルへのアクセスは、オプティマイザにより最適な 方法が選択されて行われます。forceplan を使用してジョイン順を指定す ると、オプティマイザは、別のテーブル順序では使われるインデックスと は違うインデックスを使用したり、存在するインデックスを使用できな かったりします。 他のクエリ分析ツールを使った結果、オプティマイザが最適なジョイン順 を選択していないと考えられる場合は、このコマンドをデバッグの補助と して使用できます。set statistics io on を使い、forceplan を指定した場合 としない場合の I/O を比較することによって、強制した順序が I/O と論理 読み込みを減らしているかどうかを常に検証します。 forceplan を指定する場合は、定期的にパフォーマンス管理をチェックし、 forceplan を使うクエリとプロシージャが、パフォーマンスを向上させる このオプションを必要としていることも検証してください。 forceplan はストアド・プロシージャの中で指定できます。 set forceplan は、ジョイン・タイプではなくジョイン順だけを指定します。 ジョイン・タイプを指定するコマンドはありません。ただし、サーバ・レ ベルまたはセッション・レベルでマージ・ジョインを無効にすることは可 能です。 詳細については、 「マージ・ジョインの有効化と無効化」(51 ページ ) を参 照してください。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 37 ジョインでのテーブル順序を指定する forceplan の使用に伴うリスク ジョイン順を強制的に指定する場合には次のリスクが伴います。 • 誤って使用されると、クエリのコストが著しく高くなる恐れがある。 statistics io を使い、forceplan を使用する場合としない場合でクエリ を常に入念にテストすること。 • メンテナンスが必要になる。forceplan を含むクエリとストアド・プ ロシージャを定期的にチェックする必要がある。また、Adaptive Server の今後のバージョンで、インデックスを強制的に使用させる原因と なっていた問題が解決される可能性があるため、強制されたクエリ・ プランを使うすべてのクエリは新しいバージョンのインストール時 に常にチェックする必要がある。 forceplan を指定する前に forceplan を使用する前に、次のことを実行します。 • showplan 出力を調べて、インデックス・キーが意図したとおりに使 われているかどうかを判断する。 • dbcc traceon(302) を使用して、ほかに最適化の問題がないか探す。 • インデックスで update statistics を実行する。 • update statistics コマンドを使い、インデックスなしの検索句の探索 引数の統計値をクエリに追加する。特に複合インデックスのマイ ナー・キーと一致する探索引数の場合。 • クエリが 5 つ以上のテーブルをジョインする場合は、set table count を使ってジョイン順が良くなるかどうかを確認する。 詳細については、 「オプティマイザが検討するテーブル数を指定する」 (39 ページ ) を参照。 38 Adaptive Server Enterprise 第3章 高度な最適化ツール オプティマイザが検討するテーブル数を指定する 「ジョインのコスト計算と最適化」(101 ページ ) で説明したように、 Adaptive Server は一度に 2 つから 4 つのテーブルの順列を検討することによって ジョインを最適化します。ジョインするクエリで、選択されているジョイ ン順が不適切であると考えられる場合は、set table count を使って同時に検 討されるテーブルの数を増やすことができます。構文は次のとおりです。 set table count int_value 有効値は 0 から 8 です。0 はデフォルトの動作をリストアします。 たとえば、一度に 4 つのテーブルを対象とする最適化を実行する場合は、 次のようになります。 set table count 4 dbcc traceon(310) は、一度に検討されるテーブルの数をレポートします。 詳細については、 『パフォーマンス&チューニング・ガイド:モニタリン グと分析』の「dbcc traceon(310) および最終クエリ・プランのコスト」(177 ページ ) を参照してください。 値を小さくすると、オプティマイザがすべてのジョイン順の候補を検討す る可能性が減ります。ジョイン順を決める際に検討されるテーブルの数を 増やすと、クエリを最適化するために要する時間が非常に長くなる可能性 があります。 テーブルが増えるごとにクエリの最適化に要する時間が増大するため、set table count オプションは、ジョイン順の改良による実行時間の短縮分が、 最適化のための時間の増加分を上回る場合に、たいへん有効となるオプ ションです。たとえば、次のような場合があります。 • より最適なジョイン順を指定することで、クエリの最適化と実行時間 の合計が短縮できると考えられる場合。特にいったんプランがプロ シージャ・キャッシュに入れられた後、何度も実行されると予想され るストアド・プロシージャなどの場合。 • 後で使用するための抽象プランを保存する場合。 statistics time を使って解析時間とコンパイル時間を調べ、statistics io を 使ってジョイン順の改良によって物理 I/O と論理 I/O が減っていることを 確かめます。 table count を増やしてジョインの最適化は向上しても、CPU 時間が受け 入れがたいほど増大する場合は、クエリの from 句を書き直して、showplan 出力が示すジョイン順でテーブルを指定し、forceplan を使用してクエリ を実行します。定期的なパフォーマンス管理チェックで、forceplan を指 定したジョイン順が良好なパフォーマンスを維持していることを確かめ てください。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 39 クエリにインデックスを指定する クエリにインデックスを指定する select、update、delete 文に (index index_name) 句を使用して、クエリに使 用するインデックスを指定できます。テーブル名を指定することによって、 クエリで強制的にテーブル・スキャンを実行させることもできます。構文 は次のとおりです。 select select_list from table_name [correlation_name] (index {index_name | table_name } ) [, table_name ...] where ... delete table_name from table_name [correlation_name] (index {index_name | table_name }) ... update table_name set col_name = value from table_name [correlation_name] (index {index_name | table_name})... 次に例を示します。 select pub_name, title from publishers p, titles t (index date_type) where p.pub_id = t.pub_id and type = "business" and pubdate > "1/1/93" オプティマイザが最適なクエリ・プランを選択していないと考えられる場 合に、クエリにインデックスを指定すると有効です。このオプションを指 定するときは、次のガイドラインに従ってください。 • クエリの statistics io を常にチェックして、選択されたインデックス が必要とする I/O の方が、オプティマイザが選ぶ方法よりも少ないか どうかを確認する。 • クエリ句に対して有効な値のすべての範囲をテストする。特に次のク エリを調整する場合など。 • データの分散が偏っているテーブルのクエリを調整する。 • 範囲クエリを実行する。範囲クエリのアクセス・メソッドは範囲 のサイズによって影響を受けやすいため。 このオプションは、インデックス・オプションを指定した方がクエリが向 上することがテスト結果から明らかになった場合にだけ使用します。アプ リケーションにこのインデックス・オプションを指定した場合は、結果の プランがオプティマイザが選ぶほかの方法よりも優れていることを定期 的にチェックしてください。 40 Adaptive Server Enterprise 第3章 高度な最適化ツール 注意 ノンクラスタード・インデックスとテーブルとが同じ名前である場 合は、テーブル名を指定したつもりでもノンクラスタード・インデックス が使われます。select select_list from tablename (0) を使用すると、テーブ ル・スキャンを強制的に実行できます。 リスク インデックスを指定すると、次のリスクが伴います。 • データの分布が変わると、強制されたインデックスの方がほかの選択 よりも効率が良くない場合がある。 • インデックスを削除すると、インデックスを指定するすべてのクエリ とプロシージャが、インデックスが存在しないことを示す情報メッ セージを出力する。このようなクエリは、最適な他のアクセス・メ ソッドで最適化される。 • このオプションを使うすべてのクエリは定期的にチェックしなけれ ばならないため、メンテナンス・コストが増加する。また、Adaptive Server の今後のバージョンで、インデックスを強制的に使用させる原 因となっていた問題が解決される可能性があるため、強制されたイン デックスを使うすべてのクエリは新しいバージョンのインストール 時に常にチェックする必要がある。 • インデックスは、インデックスを使うクエリが最適化されるときに存 在していなければならない。インデックスを作成してから、同一の バッチ内のクエリにこのインデックスを使用することはできない。 インデックスを指定する前に 次の処理を行ってから、クエリにインデックスを指定します。 • showplan 出力をチェックして、"Keys are" メッセージを探し、期待さ れたとおりにインデックス・キーが使われていることを確認する。 • dbcc traceon(302) を使用して、ほかに最適化の問題がないか探す。 • インデックスで update statistics を実行する。 • インデックスが複合インデックスで、インデックスを探索引数として 使用する場合は、インデックスのマイナー・キーで update statistics を 実行する。これにより、オプティマイザのコスト見積もり能力が大幅 に向上する。検索句で頻繁に使用する他のカラムの統計を作成しても、 見積もり能力が向上する。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 41 クエリに I/O サイズを指定する クエリに I/O サイズを指定する Adaptive Server に対して、デフォルト・データ・キャッシュか名前付き データ・キャッシュ内に大容量 I/O が設定されている場合、オプティマイ ザは次のクエリに対して大容量 I/O を使うことを決定できます。 • テーブル全体をスキャンするクエリ • >、<、> x、< y、between、like "charstring %" などを使う範囲クエリで、 クラスタード・インデックスを使うクエリ • 大量のインデックス・リーフ・ページをスキャンするクエリ テーブルまたはインデックスが使うキャッシュが 16K I/O に設定されてい る場合は、1 つの I/O で同時に 8 ページまで読み込むことができます。名 前付きデータ・キャッシュごとに複数のプールを設定でき、プールごとに 異なった I/O サイズを設定できます。I/O サイズをクエリに指定すると、そ のクエリに使用される I/O は指定した I/O サイズのプールで実行されます。 名前付きデータ・キャッシュの設定については、 『システム管理ガイド』を 参照してください。 オプティマイザが選んだ I/O サイズと異なる I/O サイズを指定するには、 select 文、delete 文、または update 文の index 句に prefetch を指定します。 構文は次のとおりです。 select select_list from table_name ( [index {index_name | table_name} ] prefetch size) [, table_name ...] where ... delete table_name from table_name ( [index {index_name | table_name} ] prefetch size) ... update table_name set col_name = value from table_name ( [index {index_name | table_name} ] prefetch size) ... 有効なプリフェッチ・サイズはページ・サイズによって異なります。オブ ジェクトが使うデータ・キャッシュ内に指定したサイズのプールが存在し ない場合は、オプティマイザは使用可能なサイズのなかで最適なサイズを 選択します。 au_lname にクラスタード・インデックスが設定されている場合は、次の クエリはデータ・ページをスキャンするときに 16K I/O を実行します。 select * from authors (index au_names prefetch 16) where au_lname like "Sm%" 42 Adaptive Server Enterprise 第3章 高度な最適化ツール 通常は大容量 I/O を実行するクエリに対して、2K I/O の場合の I/O 統計値 を調べたい場合には、次のように I/O サイズを 2 に指定します。 select type, avg(price) from titles (index type_price prefetch 2) group by type 注意 大容量 I/O への参照は、論理ページ・サイズが 2K のサーバに基づき ます。ページ・サイズが 8K のサーバでは、I/O の基本単位は 8K になり ます。ページ・サイズが 16K のサーバでは、I/O の基本単位は 16K にな ります。 インデックス・タイプと大容量 I/O prefetch を使って I/O サイズを指定すると、データ・ページとリーフレベ ル・インデックス・ページの両方が影響を受けます。表 3-1 に、その影響 を示します。 表 3-1: アクセス・メソッドとプリフェッチ アクセス・メソッド 大容量 I/O の処理対象 テーブル・スキャン データ・ページ クラスタード・インデックス 全ページロック・テーブルではデータ・ ページのみ データオンリーロック・テーブルでは データ・ページとリーフレベル・インデッ クス・ページ ノンクラスタード・インデックス ノンクラスタード・インデックスのデー タ・ページとリーフ・ページ showplan は、データおよびリーフレベル・ページの両方で使用される I/O サイズをレポートします。 詳細については、 『パフォーマンス&チューニング・ガイド:モニタリン グと分析』の「I/O サイズのメッセージ」(104 ページ ) を参照してください。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 43 クエリに I/O サイズを指定する prefetch 指定がきかない場合 通常は、クエリに I/O サイズを指定すると、オプティマイザはこの I/O サ イズをクエリのプランに取り込みます。しかし、場合によっては、指定し たとおりの大容量 I/O が行われないことがあります。これにはクエリ全般 に関して一切行われない場合と、またはある 1 回の容量 I/O 要求について 行われない場合の双方があります。 大容量 I/O は、以下の場合クエリには使用できません。 • 指定サイズの I/O 用にキャッシュが構成されていない。オプティマイ ザは使用可能なサイズのうち最適なサイズで代用している。 • sp_cachestrategy を使用して、テーブルまたはインデックスに対する 大容量 I/O をオフにしている。 大容量 I/O は、次の場合はシングル・バッファに使用できません。 • その I/O 要求に含まれるページのいずれかが別のプール内にある。 • ページがアロケーション・ユニットの最初のエクステントにある。こ のエクステントは、そのアロケーション・ユニットに対するアロケー ション・ページを保持しており、データ・ページは 7 ページしかない。 • 要求した I/O サイズに対応するプール内に、使用できるバッファが ない。 大容量 I/O が実行できない場合、Adaptive Server は、クエリによって必要 とされるエクステント内にある特定のページ ( 複数可 ) について、常に 2K I/O を実行します。 プリフェッチ指定に従っているかどうかを判別するには、showplan を使 用してクエリ・プランを表示し、statistics io を使用してクエリに対する I/O 処理の結果を調べます。sp_sysmon を使用すると、キャッシュごとに 要求された大容量 I/O と拒否された大容量 I/O に関する情報がレポートさ れます。 詳細については、 『パフォーマンス&チューニング・ガイド:モニタリン グと分析』の「データ・キャッシュ管理」(85 ページ ) を参照してください。 44 Adaptive Server Enterprise 第3章 高度な最適化ツール set prefetch on デフォルトでは、大容量 I/O プールが設定されている場合、クエリは常に 大容量 I/O を使用し、オプティマイザは常に大容量 I/O によってクエリの コストが減少すると判断します。セッション中に大容量 I/O を使用できな いようにするには、次のコマンドを使用します。 set prefetch off 大容量 I/O を再び使用可能にするには、次のコマンドを使用します。 set prefetch on sp_cachestrategy を使ってオブジェクトの大容量 I/O をオフにした場合は、 set prefetch on はその設定を上書きしません。 set prefetch off を使ってセッションの大容量 I/O をオフにした場合は、 select 文、delete 文、または insert 文の一部としてプリフェッチ・サイズ を指定してもその設定を上書きできません。 set prefetch コマンドは、実行される同一のバッチ内で有効になるため、 プロシージャ内のクエリの実行に影響を与えるようにストアド・プロシー ジャ内に指定することができます。 キャッシュ方式を指定する テーブルのデータ・ページまたはノンクラスタード・インデックスのリー フ・レベル ( カバード・クエリ ) をスキャンするクエリについては、Adaptive Server のオプティマイザは、MRU ( 使い捨て ) 方式と LRU 方式という 2 つ のキャッシュ置換方式のどちらかを選択します。 これらの方式の詳細については、 『パフォーマンス&チューニング・ガイ ド:基本』の「キャッシュ方式の概要」(170 ページ ) を参照してください。 一般的にはオプティマイザは、次の場合には MRU ( 使い捨て ) 方式を選 択します。 • テーブル・スキャンを実行するクエリ • クラスタード・インデックスを使う範囲クエリ • ノンクラスタード・インデックスのリーフ・レベルをスキャンするカ バード・クエリ • ジョインの内部テーブルのサイズがキャッシュよりも大きい場合の、 その内部テーブル • ジョインの外部テーブル ( 外部テーブルは 1 回だけ読み取ればよい ため ) • マージ・ジョインの両方のテーブル パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 45 キャッシュ方式を指定する オブジェクトのキャッシュ方式を指定するには、次の方法があります。 • select 文、update 文、または delete 文に lru または mru を指定する 方法 • sp_cachestrategy を使って mru 方式を使用不可にする、または再び 使用可能にする方法 MRU 方式が指定され、ページがデータ・キャッシュ内にすでに存在する 場合は、ページはウォッシュ・マーカの位置ではなく、キャッシュの MRU 側の終端に置かれます。 キャッシュ方式を指定すると、データ・ページとインデックスのリーフ・ ページにだけ影響します。ルート・ページと中間ページは、常に LRU 方 式を使います。 select 文、delete 文、update 文の場合 次のように select コマンド、delete コマンド、または update コマンドに lru か mru ( 使い捨て ) を使用して、クエリの I/O サイズを指定できます。 select select_list from table_name (index index_name prefetch size [lru|mru]) [, table_name ...] where ... delete table_name from table_name (index index_name prefetch size [lru|mru]) ... update table_name set col_name = value from table_name (index index_name prefetch size [lru|mru]) ... 次のクエリは、16K I/O の指定に LRU 置換方式を追加します。 select au_lname, au_fname, phone from authors (index au_names prefetch 16 lru) prefetch サイズの指定の詳細については、 「クエリに I/O サイズを指定する」 (42 ページ ) を参照してください。 46 Adaptive Server Enterprise 第3章 高度な最適化ツール 大容量 I/O とキャッシュ方式の制御 sysindexes テーブルのステータス・ビットは、テーブルまたはインデッ クスを大容量 I/O プリフェッチ、または MRU 置換方式の対象とするかど うかを示します。デフォルトでは、どちらも使用可能です。これらの方式 を使用不可にする、または再び使用可能にするには、sp_cachestrategy シ ステム・プロシージャを使います。構文は次のとおりです。 sp_cachestrategy dbname , [ownername.]tablename [, indexname | "text only" | "table only" [, { prefetch | mru }, { "on" | "off"}]] 次のコマンドは、authors テーブルの au_name_index に対して大容量 I/O プリフェッチ方式を使用しないように設定します。 sp_cachestrategy pubtune, authors, au_name_index, prefetch, "off" 次のコマンドは、titles テーブルに対して MRU 置換方式を再び使用可能に します。 sp_cachestrategy pubtune, titles, "table only", mru, "on" オブジェクトに対するキャッシュ方式の使用方法を変更または表示でき るのは、システム管理者とオブジェクト所有者だけです。 キャッシュ方式に関する情報の取得 あるオブジェクトに対して使われているキャッシュ方式を確認するには、 次のようにデータベース名とオブジェクト名を指定して sp_cachestrategy を実行します。 sp_cachestrategy object name ---------------titles pubtune, titles index name large IO MRU ---------------- -------- -------NULL ON ON showplan 出力は、ワークテーブルを含む各オブジェクトのキャッシュ方 式を表示します。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 47 非同期ログ・サービス 非同期ログ・サービス ALS によって Adaptive Server のスケーラビリティが向上し、ハイエンド の対称型マルチプロセッサ・システムに対してサブシステムをロギングす る場合のスループットが向上します。 エンジン数が 4 以上ないと、ALS を使用できません。それより少ないエ ンジンを使って ALS を有効にしようとすると、エラー・メッセージが表 示されます。 ALS の有効化 ALS の有効化、無効化、設定には sp_dboption ストアド・プロシージャを 使用できます。 sp_dboption <db Name>, "async log service", "true|false" checkpoint の発行 sp_dboption を発行したあとで、ALS オプションを設定するデータベース に次のように checkpoint を発行する必要があります。 sp_dboption "mydb", "async log service", "true" use mydb checkpoint checkpoint を使用すると、1 つまたは複数のデータベースを識別したり、 all 句を使用したりできます。 checkpoint [all | [dbname[, dbname[, dbname.....]]] ALS の無効化 データベースにアクティブなユーザがいないことを確認してから、 ALS を 無効にします。アクティブなユーザがいる場合、チェックポイントの発行 時にエラー・メッセージが表示されます。 sp_dboption "mydb", "async log service", "false" use mydb checkpoint ------------Error 3647:Cannot put database in single-user mode.Wait until all users have logged out of the database and issue a CHECKPOINT to disable "async log service". データベースにアクティブなユーザがいない場合は、次の例のように ALS を無効にできます。 sp_dboption "mydb", "async log service", "false" use mydb checkpoin] ------------- 48 Adaptive Server Enterprise 第3章 ALS の表示 高度な最適化ツール 指定したデータベースで ALS が有効になっているかどうかを調べるには、 sp_helpdb をチェックします。 sp_helpdb "mydb" ---------mydb 3.0 MB sa 2 July 09, 2002 select into/bulkcopy/pllsort, trunc log on chkpt, async log service ストアド・プロシージャの詳細については、 「変更されたシステム・プロ シージャ」(51 ページ ) を参照してください。 ユーザ・ログ・キャッシュ (ULC) アーキテクチャの理解 Adaptive Server のロギング・アーキテクチャでは、ユーザ・ログ・キャッ シュ (ULC)を使用します。これにより、タスクごとにログ・キャッシュ が割り当てられます。タスクは、他のタスクのキャッシュに書き込むこと はできません。また、トランザクションによってログ・レコードが生成さ れるたびに、タスクはユーザ・ログ・キャッシュへの書き込みを続けます。 トランザクションがコミットまたはアボートされたとき、またはユーザ・ ログ・キャッシュが満杯になると、ユーザ・ログ・キャッシュは共通のロ グ・キャッシュへフラッシュされ、現在のすべてのタスクから共有可能と なった後にディスクに書き込まれます。 ULC のフラッシュは、コミットまたはアボート操作が発生したときに最初 に実行されます。フラッシュの手順は次のとおりです。各手順によって、 遅延または競合の増加を引き起こす可能性があります。 1 最後のログ・ページでロックを取得する。 2 必要に応じて、新しいログ・ページを割り付ける。 3 ULC からログ・キャッシュへログ・レコードをコピーする。 手順 2 と 3 では、最後のログ・ページでロックを保持する必要がある。 これにより、他のタスクがフラッシュ対象のログ・キャッシュに書き 込んだり、コミットやアボート操作を実行することを防止できる。 4 ログ・キャッシュをディスクにフラッシュする。 手順 4 では、ダーティ・バッファに対して write コマンドを発行し、 ログ・キャッシュのスキャンを繰り返す必要がある。 スキャンを繰り返すと、ログがバインドされているバッファ・キャッ シュのスピンロック競合が発生する可能性がある。またトランザク ションの負荷が大きい場合、このスピンロックの競合は重大な問題と なる場合がある パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 49 非同期ログ・サービス ALS の使用が適する場合 次のパフォーマンス上の問題の中から、 少なくとも 1 つ以上が当てはまり、 対象のシステムがオンライン・エンジンを 4 つ以上実行している場合には、 特定のデータベースに対して ALS を有効にできます。 • 最後のログ・ページで競合が多発する。 "Task Management" レポート・セクションの sp_sysmon の出力が非常 に高い値を示している場合、最後のログ・ページで競合が発生してい ることがわかる。次に例を示す。 Task Management Log Semaphore Contention 表 3-2: 競合が発生しているログ・ページ per sec per xact count % of total 58.0 73.1 0.3 • 34801 ログ・デバイスで帯域幅を十分に活用していない。 注意 複数のデータベース環境に ALS を設定すると、スループットと応答 時間に予期しない変動が発生する可能性があるため、単一のデータベー ス環境で高トランザクションが要求される場合のみ ALS を使用してくだ さい。複数のデータベースに対して ALS を設定する場合は、最初にスルー プットと応答時間が正常であることをチェックしてください。 ALS の使用 ダーティ・バッファ (ディスクに書き込まれていないデータでいっぱい のバッファ)のスキャン、データのコピー、データのログへの書き込みに 使用するスレッドには、次の 2 つがあります。 • ユーザ・ログ・キャッシ (ULC) フラッシャ • ログ・ライタ ULC フラッシャ ULC フラッシャは、タスクのユーザ・ログ・キャッシュを一般のログ・ キャッシュにフラッシュするためだけに使用されるシステム・タスク・ス レッドです。タスクをコミットする準備ができたら、ユーザはフラッシャ・ キューへコミット要求を入れます。各エントリにはハンドルがあります。 ULC フラッシャでは、このハンドルを使って、要求をキューに入れたタ スクの ULC にアクセスします。ULC フラッシャ・タスクは絶えずフラッ シャ・キューを監視して、キューから要求を削除し、ULC ページをログ・ キャッシュにフラッシュします。 50 Adaptive Server Enterprise 第3章 高度な最適化ツール ログ・ライタ ULC フラッシャによって ULC ページがログ・キャッシュにフラッシュさ れると、タスク要求はウェイクアップ・キューに入れられます。ログ・ラ イタはログ・キャッシュ内のダーティ・バッファ・チェーンを巡回チェッ クして、ダーティ・バッファを検出すると書き込みコマンドを発行し、 ページがすべてディスクに書き込まれたタスクのウェイクアップ・キュー をモニタします。ログ・ライタはダーティ・バッファ・チェーンを巡回 チェックするので、バッファがいつディスクへの書き込み準備ができたか わかります。 変更されたシステム・プロシージャ ALS を有効にするために、次の 2 つのストアド・プロシージャが変更さ れています。 • sp_dboption に ALS を有効、または無効にするためのオプションが追 加されています。 • sp_helpdb に ALS を表示するためのカラムが追加されています。 これらのストアド・プロシージャの一般情報については、 『ASE リファレ ンス・マニュアル』を参照してください。 マージ・ジョインの有効化と無効化 マージ・ジョインは、デフォルトではサーバ・レベルで無効になってい ます。マージ・ジョインが無効になっている場合、サーバはネストルー プ・ジョインだけを見積もり、マージ・ジョインは考慮されません。マー ジ・ジョインをサーバ全体で有効にするには、enable sort-merge joins and JTC を 1 に設定します。これにより、ジョイン推移閉包も有効とな ります。 set sort_merge on コマンドは、サーバ・レベルを上書きします。これに より、セッションまたはストアド・プロシージャでマージ・ジョインが使 用できるようになります。 マージ・ジョインを有効にするには、次のコマンドを使います。 set sort_merge on マージ・ジョインを無効にするには、次のコマンドを使います。 set sort_merge off マージ・ジョインをサーバワイドに設定する方法については、 『システム 管理ガイド』を参照してください。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 51 ジョイン推移閉包の有効化と無効化 ジョイン推移閉包の有効化と無効化 デフォルトでは、最適化に時間がかかるため、サーバ・レベルでのジョイ ン推移閉包は有効になっていません。set jtc on を使って、セッション・レ ベルでジョイン推移閉包を有効にできます。このコマンドは、enable sortmerge joins and JTC 設定パラメータのサーバ・レベルの設定を上書きし ます。 短時間で実行されるクエリでは、複数のテーブルが含まれる場合でも、 ジョイン推移閉包によって実行コストの面での改善はほとんどなく、最適 化時間が増加する可能性があります。たとえば、次のクエリにジョイン推 移閉包を適用すると、追加された各テーブルに対し、可能なジョインの数 が倍加されます。 select * from t1, t2, t3, t4, ... tN where t1.c1 = t2.c1 and t1.c1 = t3.c1 and t1.c1 = t4.c1 ... and t1.c1 = tN.c1 ただし、サイズが非常に大きいテーブルのジョインでは、ジョイン推移閉 包によって追加されたジョイン順のコスト計算にかかる最適化時間が、結 果としてジョイン順の応答時間を大幅に改善する場合があります。 set statistics time を使うと、クエリの最適化にかかる時間を確認でき ます。set jtc on を使ってクエリを実行して最適化時間が大幅に増加し ても、より最適なジョイン順を選択することでクエリの実行が向上する 場合は、showplan 出力または dbcc traceon(302, 310) 出力をチェック します。クエリ・テキストにその効果的なジョイン順を明示的に追加し ます。ジョイン推移閉包なしでクエリを実行でき、ジョイン推移閉包に よって生成されたすべての可能なジョイン順を確認するために最適化 時間を増加させることなく、実行時間を改善できます。 また、ジョイン推移閉包を有効にして、効果的なクエリの抽象プランを保 存できます。次に、有効な保存されているプランからこれらのクエリを読 み込んで実行すると、保存されている実行プランが使用されてクエリが最 適化され、最適化時間が非常に短縮されます。 抽象プランの使用の詳細については、このマニュアルの関連する章を参照 してください。 ジョイン推移閉包をサーバワイドに設定する方法については、 『システム 管理ガイド』を参照してください。 52 Adaptive Server Enterprise 第3章 高度な最適化ツール クエリの並列度の指定 select コマンドの from 句に parallel 拡張と degree_of_parallelism 拡張を指 定すると、スキャンに使用されるワーカー・プロセスの数を制限できます。 parallel パーティション・スキャンが実行される場合は、 degree_of_parallelism の値を分割の数以上にする必要があります。並列イ ンデックス・スキャンの場合は、degree_of_parallelism には任意の値を指 定します。 select 文の構文は、次のようになります。 select... [from {tablename} [(index index_name [parallel [degree_of_parallelism | 1]] [prefetch size] [lru|mru])], {tablename} [([index_name] [parallel [degree_of_parallelism | 1] [prefetch size] [lru|mru])] ... 表 3-3 は、逐次スキャンまたは並列スキャンを実行する場合の、index キー ワードと parallel キーワードを組み合わせる方法を示します。 表 3-3: 逐次実行と並列実行の場合のオプティマイザに対する指定 指定するスキャンの種類 並列パーティション・スキャン 使用する構文 (index tablename parallel N) 並列インデックス・スキャン (index index_name parallel N) 逐次テーブル・スキャン (index tablename parallel 1) (index index_name parallel 1) 逐次インデックス・スキャン オプティマイザが選択するテーブ (parallel N) ル・スキャンまたはインデックス・ スキャンの並列処理 オプティマイザが選択するテーブ (parallel 1) ル・スキャンまたはインデックス・ スキャンの逐次処理 マージ・ジョインでテーブルに並列度を指定すると、テーブルのスキャン とマージ・ジョインの両方で使用される並列度に影響が及びます。 セッション・レベルで set parallel_degree 1 コマンドを指定しているか、 またはサーバ・レベルで parallel degree 設定パラメータを指定し、並列 処理を使用不可に設定している場合は、parallel オプションは使用できま せん。parallel オプションは、これらの設定を上書きできません。 degree_of_parallelism に並列度として設定できる最大値を超える値を指定 すると、Adaptive Server はその指定を無視します。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 53 クエリの並列度の指定 次の条件のいずれかが真である場合、オプティマイザは並列度に指定され ている値を無視します。 • from 句がカーソル定義で使用されている。 • サブクエリの内側のクエリ・ブロック内で、from 句に parallel が使用 されている。さらに、オプティマイザが、サブクエリのフラット化の 処理中に、テーブルを一番外側のクエリ・ブロックに移動しない。 • テーブルがビュー、システム・テーブル、仮想テーブルのどれか。 • テーブルが外部ジョインの内部テーブル。 • クエリが、テーブルについて exists、min、max のいずれかを指定する。 • max scan parallel degree 設定パラメータの値が 1 に設定されている。 • 分割されていないクラスタード・インデックスが指定されているか、 parallel オプションだけが指定されている。 • ノンクラスタード・インデックスがカバーリングされている。 • クエリが OR 方式を使って処理される。 OR 方式の詳細については、 「アクセス・メソッドと or 句および in 句 のコスト計算」(84 ページ ) を参照。 • select 文が更新または挿入に使用されている。 クエリ・レベルの parallel 句の例 1 つのクエリに並列度を指定するには、テーブル名の次に parallel を指定 します。次の例は、逐次処理で実行されます。 select * from titles (parallel 1) 次の例は、クエリで使用されるインデックスを指定し、並列度を 5 に設定 します。 select * from titles (index title_id_clix parallel 5) where ... テーブル・スキャンを強制的に実行するには、インデックス名の代わりに テーブル名を使用します。 54 Adaptive Server Enterprise 第3章 高度な最適化ツール 小さいテーブルの同時実行性の最適化 15 ページ以下のデータオンリーロック・テーブルでは、そのテーブルに 効果的なインデックスがある場合、Adaptive Server はテーブル・スキャン を考慮に入れません。その代わり、クエリ内の最適化できる探索引数と 一致する最もコストのかからないインデックスが常に選択されます。イ ンデックス・スキャンに必要なロックは、テーブル・スキャンの場合よ りもほんの少し I/O を多く要求する場合もありますが、高い同時実行性を 提供し、デッドロックの可能性を減らします。 小さなテーブルの同時実行性が問題ではなく、代わりに I/O を最適化した い場合は、sp_chgattribute を使用してこの最適化を無効にできます。次の コマンドは、テーブルの同時実行性を無効にします。 sp_chgattribute tiny_lookup_table, "concurrency_opt_threshold", 0 同時実行性の最適化を無効にすると、オプティマイザは、I/O をあまり要 求しないときにテーブル・スキャンを選択できます。 また、テーブルの同時実行性の最適化スレッショルドを増やすこともでき ます。次のコマンドは、テーブルの同時実行性の最適化スレッショルドを 30 ページに設定します。 sp_chgattribute lookup_table, "concurrency_opt_threshold", 30 同時実行性の最適化スレッショルドの最大値は 32,767 です。この値を -1 に設定すると、任意のサイズのテーブルに対して同時実行性の最適化が強 制されます。これは、インデックス・アクセスよりもテーブル・スキャン が選択され、その結果ロックの競合やデッドロックが発生するときに便利 な場合があります。 現在の設定は、systabstats.conopt_thld に保存され、optdiag の一部とし て出力されます。 ロック・スキームの変更 同時実行性の最適化は、データオンリーロック・テーブルだけに影響し ます。表 3-4 に、ロック・スキームの変更による影響を示します。 表 3-4: テーブルの変更による同時実行性の最適化設定への影響 ロック・スキームの変更 保存されている値への影響 全ページからデータオンリーに変更 デフォルトの 15 に設定 データオンリーから全ページに変更 0 に設定 1 つのデータオンリー・スキームから別の データオンリー・スキームに変更 設定値を保持 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 55 小さいテーブルの同時実行性の最適化 56 Adaptive Server Enterprise 第 4 章 クエリ・チューニング用ツール この章では、クエリのチューニングに役立つツールについて説明します。 トピック名 概要 ページ 57 ツールの影響 59 ツールとクエリ処理の関連 60 この章で挙げるツールの詳細については、以降の章で説明します。 概要 Adaptive Server は、クエリ最適化を理解してクエリのパフォーマンスを 向上させるために役立つ、次のような診断および情報ツールを備えてい ます。 • テーブルおよびインデックスのサイズの検査や、見積もりをするため のツール。これらのツールについては、 『パフォーマンス&チューニ ング・ガイド:基本』の「第 11 章 テーブルとインデックスのサイズ の決定」を参照してください。 • set statistics io on は、 クエリの各テーブルが必要とする論理読み込み、 物理読み込み、論理書き込み、物理書き込みの数を示す。リソース制 限が有効になっている場合、実際の I/O コストの合計も示される。set statistics io については、 『パフォーマンス&チューニング・ガイド: モニタリングと分析』の「第 4 章 set statistics コマンドの使用」を参 照してください。 • set showplan on は、あるバッチ内のクエリごとに実行される手順を 表示する。多数のローを返すクエリの場合は特に、set noexec on と 同時に使用されることが多い。 詳細については、 『パフォーマンス&チューニング・ガイド:モニタ リングと分析』の「第 5 章 set showplan の使用」を参照してください。 • set statistics subquerycache on は、サブクエリごとに、キャッシュ・ ヒット数、キャッシュ・ミス数、キャッシュ内に存在するロー数を表 示する。 例については「サブクエリ結果のキャッシュ」(135 ページ ) を参照し てください。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 57 概要 • set statsitics time on は、各コマンドの解析とコンパイルにかかる時 間を表示する。 詳細については、 『パフォーマンス&チューニング・ガイド:モニタ リングと分析』の「コンパイル時間と実行時間のチェック」(56 ペー ジ ) を参照してください。 • dbcc traceon (302) および dbcc traceon(310) は、特定のプランを選択 した理由についての補足情報を示し、オプティマイザが正しくないプ ランを選択していると思われる場合に使われる。 詳細については、 『パフォーマンス&チューニング・ガイド:モニタ リングと分析』マニュアルの「第 7 章 診断ツール dbcc traceon を使用 するチューニング」を参照してください。 • optdiag ユーティリティ・コマンドは、テーブル、インデックス、カ ラムの統計を表示する。 詳細については、 『パフォーマンス&チューニング・ガイド:モニタ リングと分析』マニュアルの「第 6 章 統計テーブルおよび optdiag を 使った統計の表示」を参照してください。 • 58 このマニュアルの「第 3 章 高度な最適化ツール」では、インデック スの選択、ジョイン順、その他のクエリ最適化のオプションを実行す るために使用するツールについて説明している。ツールには次のもの がある。 • set forceplan - from 句に指定された順序で、クエリにテーブル を使用させる。 • set table count - オプティマイザが、ジョイン順の決定中に一度 に考慮するテーブルの数を増やす。 • (index...prefetch...mru_lru...parallel) を使用する select、delete、 update 句 - クエリ用に使用されるインデックス、I/O サイズ、 またはキャッシュ方式を指定する。 • set prefetch - prefetch を切り替えて、 クエリがどのようにチュー ニングされるかを試す。 • set sort_merge - ソートマージ・ジョインを禁止する。 • set parallel_degree - クエリの並列度を指定する。 • sp_cachestrategy - ステータス・ビットを設定して、プリフェッ チおよび使い捨てキャッシュ方式を使用可能または使用不可に する。 Adaptive Server Enterprise 第4章 クエリ・チューニング用ツール ツールの影響 showplan、statistics io などのコマンドは、ストアド・プロシージャが実 行されている間に出力を生成します。最適化の方式のテスト時に、テー ブル構造またはインデックスの確認のためにシステム・プロシージャを 使用すると、診断情報を表示するときに多量の出力が生成される場合が あります。この場合、テーブル・スキーマとインデックス情報のハード・ コピーを作成しておくと便利です。また、sp_helpindex などのシステム・ プロシージャを実行するウィンドウを別にしておく方法もあります。 より長いクエリおよびバッチの場合は、showplan と statistics io の出力 をファイル内に保存しておくと便利です。そのためには、isql に「エコー 入力」フラグを使用します。構文は次のとおりです。 isql -P password -e -i input_file -o outputfile showplan と noexec を同時に指定する showplan は set noexec on とともに使用されることが多く、これにより SQL 文が実行されなくなります。showplan コマンド、または他の set コ マンドを発行してから、noexec コマンドを発行します。set noexec on が 発行された後に Adaptive Server が実行できるコマンドは set noexec off だ けです。次に、正しい順序の例を示します。 set showplan on set noexec on go select au_lname, au_fname from authors where au_id = "A137406537" go noexec と statistics io showplan と noexec の組み合わせはたいへん有効ですが、noexec は statistics io の出力をすべて停止します。statistics io コマンドは実ディス ク I/O をレポートします。noexec が有効になっていると、I/O が実行され ないため、レポートは表示されません。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 59 ツールとクエリ処理の関連 ツールとクエリ処理の関連 set コマンドなどのツールの多くは、オプティマイザの決定に影響を与え ます。showplan と dbcc traceon(302, 310) は、オプティマイザの意思決 定を表示します。dbcc traceon(302, 310) は、分析が実行されるときに中 間情報を表示し、dbcc traceon(310) は、最終的なプランの統計を表示し ます。showplan は、アクセス・メソッドとジョイン順の最終的な決定を 表示します。 statistics io と statistics time は、クエリが実行された方法についての情報 を提供します。statistics time は、解析の手順からクエリの完了までにか かった時間を測定します。 statistics io はクエリ実行中に実行された実際の I/O を出力します。 noexec を使用すると、実際にクエリを実行しないで showplan または dbcc traceon(302,310) などの出力情報を取得できます。 60 Adaptive Server Enterprise 第 5 章 1 つのテーブルに対するアクセス・ メソッドとクエリ・コスト計算 この章では、Adaptive Server がテーブル内のローにアクセスするのに使 用する方法について説明します。1 つのテーブルに対するクエリの種類、 使用できるアクセス・メソッド、関連のコストについて説明します。 トピック名 テーブル・スキャンにかかるコスト ページ 63 ローからページへ 66 インデックス・アクセスにかかるコストを評価する 69 order by を使ったクエリのコスト見積もり 77 アクセス・メソッドと or 句および in 句のコスト計算 84 集合関数の最適化方法 89 更新オペレーションの実行方法 91 「第 2 章 オプティマイザの概要」では、オプティマイザが、探索引数と ジョイン句を使用して、クエリが返すロー数を見積もる仕組みについて説 明しました。この章では、オプティマイザが、ロー数の見積もりやその他 の統計値を使用して、クエリで読み込むページの数と、論理 I/O と物理 I/O の回数を見積もる仕組みについて説明します。 この章では、単一のテーブルに影響を与えるクエリを扱います。 複数のテーブルに影響するクエリについては、 「第 6 章 ジョインとサブク エリのアクセス・メソッドとコスト計算」を参照してください。 並列クエリについては、 「第 8 章 並列クエリ最適化」を参照してください。 この章では、以下の方法でクエリ処理について説明します。 • さまざまな種類のクエリを処理するのに Adaptive Server が使う各ア クセス・メソッドの概要について、図やクエリ例を交えた説明。特定 のクエリの実行方法や、クエリで使用されるカラムにインデックスま たは統計値を追加することでクエリ・パフォーマンスを向上させる方 法について理解するために役立ちます。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 61 • オプティマイザがクエリに対する論理 I/O と物理 I/O を見積もる仕組 みについての説明。個別のクエリに対して I/O の使用と応答時間が妥 当であるかどうかを理解するために役立ちます。これらの説明では、 次のチューニング・ツールを使います。 • optdiag を使って、テーブル、インデックス、カラム値に関する 情報を表示する。 詳細については、 『パフォーマンス&チューニング・ガイド:モ ニタリングと分析』の「第 6 章 統計テーブルおよび optdiag を 使った統計の表示」を参照してください。 • showplan は、クエリに対するアクセス・メソッド ( テーブル・ スキャン、インデックス・スキャン、OR 方式など ) を表示する。 詳細については、 『パフォーマンス&チューニング・ガイド:モ ニタリングと分析』の「第 5 章 set showplan の使用」を参照して ください。 • • statistics io は、クエリで使用されているテーブルごとに論理 I/O と物理 I/O を表示する。 Adaptive Server が実際に使用する計算式に非常に近い、正確な計算式。 この計算式は、チューニング・ツールと併用して使用します。詳細に ついては、『パフォーマンス&チューニング・ガイド:モニタリング と分析』を参照してください。 • optdiag を使用して、計算式を適用する必要のある統計値を表示 する。詳細については、 「第 6 章 統計テーブルおよび optdiag を 使った統計の表示」を参照してください。 • dbcc traceon(302) は、論理 I/O の見積もりに使うサイズ、密度、 選択性、クラスタ率を表示する。dbcc traceon(310) は、各テー ブルについての最終的なクエリ・コストを表示する ( 物理 I/O の 見積もりも含む )。詳細については、「第 7 章 診断ツール dbcc traceon を使用するチューニング」を参照してください。 多くの場合、問題があるクエリのデバッグを行うときにだけ、これら の計算式が必要になります。or クエリがテーブル・スキャンを行う 理由や、有効と思われたインデックスをクエリが利用しない理由を見 つけることが必要な場合などです。 この章は、特定のクエリについて、どこまでパフォーマンスの向上を図れ ばよいかを知るためにも役立ちます。それには一定の数のインデックス・ ページとデータ・ページを読み込む必要があることと、カバーリング・イ ンデックスを追加するという方法で I/O の回数をこれ以上減らすことがで きないことがわかった場合、クエリ分析とインデックス選択によって得ら れる最善のパフォーマンスに達したことがわかります。キャッシュ設定、 並列クエリ・オプション、オブジェクト配置など他の問題についても検討 することが必要な場合もあります。 62 Adaptive Server Enterprise 第5章 1 つのテーブルに対するアクセス・メソッドとクエリ・コスト計算 テーブル・スキャンにかかるコスト クエリがテーブル・スキャンを要求する場合、Adaptive Server はディスク からデータ・キャッシュにテーブルの各ページを読み込み、データ値を確 認し (where 句がある場合 )、条件を満たすローを返します。 テーブル・スキャンは次の場合に実行されます。 • 検索句で使われているカラムにインデックスがないとき。 • テーブル・スキャンを実行するより、インデックスを使う方がコス トがかかる、とオプティマイザが判断したとき。インデックス・ペー ジを読み込んでから各ローのデータ・ページを読み込んでローを返 すより、データ・ページを直接読み込む方がコストが少なくて済む、 とオプティマイザが判断することがあります。 テーブル・スキャンにかかるコストは、テーブルと I/O のサイズによって 異なります。 注意 大容量 I/O への参照は、論理ページ・サイズが 2K のサーバに基づき ます。ページ・サイズが 8K のサーバでは、I/O の基本単位は 8K になり ます。ページ・サイズが 16K のサーバでは、I/O の基本単位は 16K にな ります。 全ページロック・テーブルのスキャンにかかるコスト 全ページロック・テーブルで 2K I/O を使ったテーブル・スキャンを実行 したときの I/O コストは、テーブルの各ページにつき 1 回の物理 I/O と 1 回の論理 I/O です。 テーブル・スキャンにかかるコスト = ページ数 * 18 + ページ数 * 2 テーブルが大容量の I/O にキャッシュを使う場合、ページ数を I/O のサイ ズで除算し、データ・ページのクラスタ率に基づいた係数を掛ける ( 処理 する必要のある大容量 I/O の回数を見積もるため ) ことで、物理 I/O の回 数が見積もられます。アロケーション・ユニットの最初のエクステントに あるデータ・ページに対しては、大容量の I/O は実行できないため、この ようなデータ ページは、2K I/O で読み込む必要があります。 論理 I/O のコストは、テーブルの各ページに対して 1 回の論理 I/O となり ます。計算式は次のとおりです。 テーブル・スキャンにかかるコスト = ( ページ数 / IO あたりのペー ジ数 ) * クラスタ率に基づいた調整 * 18+ ページ数 * 2 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 63 テーブル・スキャンにかかるコスト クラスタ率の詳細については、 「クラスタ率が大容量 I/O に与える影響」 (67 ページ ) を参照してください。 注意 Adaptive Server は、全ページロック・テーブルに使用されているア ロケーション・ユニットの最初のエクステントにあるページ数を追跡し ません。したがって、オプティマイザは、このためのわずかな回数の I/O を見積もりに含めません。 データオンリーロック・テーブルのスキャンにかかるコスト データオンリー・ロックを使用するテーブルには、全ページロック・テー ブルのようなページ・チェーンがありません。データオンリーロック・ テーブルに対してテーブル・スキャンを実行するために、Adaptive Server は次の作業を行います。 • テーブルの OAM ( オブジェクト・アロケーション・マップ ) ページ を読み込む。 • OAM ページ上のポインタを使用して、アロケーション・ページにア クセスする。 • アロケーション・ページ上のポインタを使用して、テーブルが使うエ クステントの位置を特定する。 • エクステント内のページで、大容量 I/O または 2K I/O のいずれかを 実行する。 データオンリーロック・テーブルに対するテーブル・スキャンの合計コ ストには、テーブル内の全ページに対する論理 I/O と 物理 I/O、および OAM ページとアロケーション・ページに対する論理 I/O と 物理 I/O が含 まれます。 図 5-1 は、OAM ページからアロケーション・ページを指すポインタと、ア ロケーション・ページからエクステントを指すポインタを示しています。 64 Adaptive Server Enterprise 第5章 1 つのテーブルに対するアクセス・メソッドとクエリ・コスト計算 図 5-1: OAM スキャンのためのポインタ・シーケンス OAM ページ 0 256 オブジェクトが 使用するページ 0 1 2 8 9 10 11 12 13 14 15 3 4 5 6 7 アロケーション・ ページ 16 17 18 19 20 21 22 23 その他のページ 24 25 26 27 28 29 30 31 .. . 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 .. . 504 505 506 507 508 509 510 511 2K I/O を使用する OAM スキャンにかかるコストの計算式は、次のとおり です。 OAM スキャンにかかるコスト = (OAM アロケーション・ページ数 + ページ数 ) * 18 + (OAM アロケーション・ページ数 + ページ数 ) * 2 大容量 I/O が使用できる場合、オプティマイザは、標準のエクステント内 のページに対して 16K I/O の実行にかかるコストに、各アロケーション・ ユニットの最初のエクステントにあるページに対して 2K I/O の実行にか かるコストを加えます。物理 I/O の回数は、テーブルのページ数に、テー ブルのデータ・ページのクラスタ率に基づきクラスタ調整を行ったものに なります。 クラスタ率の詳細については、 「クラスタ率が大容量 I/O に与える影響」 (67 ページ ) を参照してください。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 65 ローからページへ 論理 I/O のコストは、テーブル内の 1 ページにつき 1 回の I/O と、OAM と アロケーション・ページを読み込む論理 I/O のコストを加えたものです。 大容量 I/O を使用する OAM スキャンにかかるコストの計算式は、次のと おりです。 OAM スキャンにかかるコスト = + + + + OAM アロケーション・ページ数 * 18 最初のエクステントのページ数 * 18 他のエクステントのページ数 / IO あたりのページ数 * クラスタ調整 * 18 OAM アロケーション・ページ数 * 2 テーブルに含まれるページ数 * 2 optdiag では、ページ数が、必要とされる値それぞれに分けてレポートさ れます。 データオンリーロック・テーブルに、転送されたローがある場合、転送さ れたローの読み込みにかかる I/O コストが、テーブル・スキャンにかかる 論理 I/O と 物理 I/O に加えられます。 ローの転送の詳細については、 『パフォーマンス&チューニング・ガイド: 基本』の「全ページロック・ヒープ・テーブル」(164 ページ ) を参照して ください。 ローからページへ オプティマイザが、クエリ解析のために、インデックスの使用にかかるコ ストを計算するとき、まず条件を満たすローの数を見積もり、次に、読み 込む必要があるページの数を見積もります。 「第 2 章 オプティマイザの概要」の例は、Adaptive Server が統計値を使っ て探索引数またはジョインに対するロー数を見積もる方法を示したも のです。ロー数が見積もられると、オプティマイザは、読み込む必要が あるデータ・ページ数とインデックスのリーフ・ページ数を以下の方法 に従って見積もります。 • テーブルの場合、テーブル内のロー数をページ数で除算し、データ・ ページの平均ロー数を求める。 • インデックスのリーフ・レベルでのページの平均ロー数を見積もる 場合、テーブル内のロー数をインデックス内のリーフ・ページ数で 除算する。 ページ数が見積もられたら、データ・ページとインデックス・ページのクラ スタ率を使用して、大容量の I/O を使うクエリに対するページ数の見積りを 調整します。また、データ・ローのクラスタ率を使用して、非カバーリン グ・インデックスを使うクエリに対するデータ・ページ数を見積もります。 66 Adaptive Server Enterprise 第5章 1 つのテーブルに対するアクセス・メソッドとクエリ・コスト計算 クラスタ率が大容量 I/O に与える影響 クラスタ率が高い場合、大容量 I/O が効果的です。クラスタ率が下がると、 大容量 I/O の効果は急速に下がります。I/O の見積りの精度を高めるため、 オプティマイザはクラスタ率を使用します。 • テーブルの場合、データ・ページのクラスタ率によって、エクステン ト上のページのパック状態と順序付け状態が計測される。 • インデックスの場合、データ・ページのクラスタ率によって、このイ ンデックスを使うテーブルへのアクセスに対する大容量の I/O の効 果が測定される。 • インデックス・ページのクラスタ率によって、インデックスのエクス テントにあるリーフ・レベル・インデックス・ページのパック状態と 順序付け状態が計測される。 注意 クエリ最適化で使うその他のクラスタ率には、データ・ローの クラスタ率があります。これは、特定のインデックスを使うスキャン の間にアクセスする必要があるデータ・ページ数を見積もるのに使い ます。大容量 I/O の見積もりには使いません。 テーブルとインデックスのクラスタ率は、optdiag を実行すると表示され ます。 データ・ページ・クラスタ率 テーブルに対するデータ・ページのクラスタ率によって、テーブル・ス キャンに対する大容量 I/O の効果が測定されます。ロック・スキームに よって、データ・ページのクラスタ率の使用方法が少しずつ異なります。 全ページロック・テーブルの場合 全ページロック・テーブルの場合、テーブル・スキャンまたはクラス タード・インデックスを使った多数ページのスキャンは、各データ・ペー ジにある次ページ・ポインタをたどります。クラスタード・インデック スが作成された直後のデータ・ページのクラスタ率は 1.0 で、ページの 順序はエクステントのページ番号順になっています。しかし、更新や ページ分割の後では、ページ・チェーンはページ・チェーン内で断片化 することがあります。図 5-2 の例では、ページ 10 が分割されています。 ページ・ポインタは、ページ 10 から他のエクステント上のページ 26 を 指し、そこからページ 11 を指しています。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 67 ローからページへ 図 5-2: 全ページロック・テーブルのエクステント上にまたがるページ・チェーン 0 1 2 8 9 10 11 12 13 14 15 3 4 5 6 7 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 .. . オブジェクトが使用する ページ OAM ページ アロケーション・ページ その他のページ 248 249 250 251 252 253 254 255 全ページロック・テーブルでは、データ・ページのクラスタ率によって、 テーブル・スキャンとクラスタード・インデックス・スキャンの両方に対 する大容量 I/O の効果が測定されます。 データオンリーロック・テーブルの場合 データオンリーロック・テーブルでは、データ・ページ・クラスタ率はエ クステント上にどの程度ページがうまくパックされているかを示します。 クラスタ率が 1.0 の場合、エクステントがページ・チェーン順で完全に パックされていることを示します。エクステント上に未使用のページがあ る場合、データ・ページのクラスタ率は 1.0 より小さくなります。 クラスタード・インデックスを持つ、データオンリーロック・テーブル の場合、optdiag では、データ・ページに対して 2 種類のクラスタ率がレ ポートされます。テーブルについてレポートされた値は、テーブル・ス キャンに使用されます。クラスタード・インデックスについてレポート された値は、そのインデックスを使うスキャンに使用されます。 インデックス・ページ・クラスタ率 データオンリーロック・テーブル上のノンクラスタード・インデックスと クラスタード・インデックスについては、インデックス・ページのクラス タ率によって、エクステント上のリーフレベル・インデックス・ページの パック状態と順序付け状態が計測されます。複数のリーフ・ページを読み 込む必要があるクエリの場合、インデックスのリーフ・レベルは次ページ・ ポインタまたは前ページ・ポインタを使ってスキャンされます。多数の リーフ・ローを読み込む必要がある場合は、リーフ・ページに対して 16K I/O を使うことで、一度に 1 つのエクステントが読み込まれることがあり ます。インデックス・ページのクラスタ率によって、リーフ・レベル・イ ンデックス・ページのページ・チェーンの断片化状態が計測されます。 68 Adaptive Server Enterprise 第5章 1 つのテーブルに対するアクセス・メソッドとクエリ・コスト計算 インデックス・アクセスにかかるコストを評価する クエリに、有効なインデックスに対する探索引数がある場合、そのクエリ は探索引数と一致するローを含んだインデックス・ページとデータ・ペー ジだけにアクセスします。Adaptive Server は、インデックス・ページと データ・ページの I/O の合計コストとテーブル・スキャンの実行コストを 比較して、最もコストが少ない方法を使用します。 単一のローを返すクエリ インデックスを使って単一のローを返すクエリは、各インデックス・レベ ルごとに 1 回の I/O を実行し、さらにデータ・ページを 1 回読み込みます。 オプティマイザでは、インデックス・ページまたはデータ・ページ 1 ペー ジにつき、1 回の物理 I/O と 1 回の論理 I/O として、合計コストが見積も られます。ポイント・クエリのコストは、次のとおりです。 ポイント・クエリのコスト = ( インデックス・レベルの数 + データ・ページの数 ) * 18 + ( インデックス・レベルの数 + データ・ページの数 ) * 2 optdiag 出力は、インデックス・レベルの数を表示します。 使用頻度の高いインデックスのルート・ページと中間ページは、キャッ シュ内で見つかる確率が高くなります。この場合、実際の物理 I/O は読み 込み 1 回分または 2 回分だけ少なくなります。 多数のローを返すクエリ 多数のローを返すクエリは、インデックスの種類や返されるロー数によっ てまったく異なる方法で最適化されます。たとえば、次のような場合があ ります。 • 多数の値に一致する探索引数を持つクエリの場合 select title, price from titles where pub_id = "P099" • 範囲クエリの場合 select title, price from titles where price between $20 and $50 インデックスの先行キーを使用して多数のローを返すクエリの場合、クラ スタード・インデックスやカバーリング・ノンクラスタード・インデック スが非常に効率的です。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 69 インデックス・アクセスにかかるコストを評価する • テーブルが全ページ・ロックを使用していて、探索引数に使用された クラスタード・インデックスを持つ場合。そのクラスタード・イン デックスは、条件に合う最初のローにスキャンを位置付けするために 使用されます。条件に合うローの残りは、データ・ページのスキャン を続行すると読み込まれます。 • データオンリーロック・テーブル上のノンクラスタード・インデック スまたはクラスタード・インデックスがクエリをカバーする場合。イ ンデックスは、インデックスのリーフ・ページ上で条件に合う最初の ローにスキャンを位置付けするために使用されます。条件に合うロー の残りは、リーフ・レベル・インデックス・ページのスキャンを続行 すると読み込まれます。 インデックスがクエリをカバーしない場合、データオンリーロック・テー ブル上のクラスタード・インデックスまたはノンクラスタード・インデッ クスを使用すると、そのインデックスに関する探索引数と一致したイン デックス・ローごとに、それに対応するデータ・ページにアクセスする ことが必要になります。一致するローは、多数のデータ・ページにわたっ て分散していることもあれば、特に、インデックスが、データオンリー ロック・テーブル上のクラスタード・インデックスである場合など、非 常に少ない数のページに集中していることもあります。オプティマイザ はデータ・ローのクラスタ率を使って、条件に合うすべてのデータ・ペー ジの読み込みに要求される物理 I/O と論理 I/O の回数を見積もります。 クラスタード・インデックスを使う範囲クエリ ( 全ページ・ロック ) 全ページロック・テーブル上のクラスタード・インデックスを使う範囲ク エリに必要な物理 I/O の回数を見積もるために、オプティマイザは、各イ ンデックス・レベルのための物理 I/O と論理 I/O、および必要なデータ・ ページを読み込むための物理 I/O と論理 I/O を加算します。データ・ペー ジはページ・チェーンに沿った順序で読み込まれるため、大容量 I/O の効 果の見積もりにはクラスタ調整が役立ちます。計算式は次のとおりです。 データ・ページ数 = 条件に合うローの数 / ページあたりのデータ・ローの数 範囲クエリのコスト = インデックス・レベルの数 * 18 + データ・ページ数 / IO あたりのページ数 * クラスタ調整 * 18 + インデックス・レベルの数 * 2 + データ・ページ数 * 2 クエリが 500 ローを返し、テーブルには 1 ページあたり 10 ローある場合、 クエリは 50 データ・ページと各インデックス・レベルにつき 1 つのイン デックス・ページを読み込まなくてはなりません。クエリが 2K I/O を使 う場合には、データ・ページに I/O が 50 回必要です。クエリが 16K I/O を 使う場合は、50 データ・ページを読み込むのに I/O が 7 回必要です。 70 Adaptive Server Enterprise 第5章 1 つのテーブルに対するアクセス・メソッドとクエリ・コスト計算 クラスタ調整では、テーブルのエクステント上にあるデータ・ページ記憶 領域の断片化状態に基づき、テーブルに対する大容量 I/O の見積りの精度 を高めるために、データ・ページのクラスタ率を使います。 図 5-3 は、クラスタード・インデックスを使用する範囲クエリによって、 データ・ページ上で最初に一致するローに検索が位置付けされる様子を示 します。次のページのポインタを使用して、一致しないローに出会うまで データ・ページを前方方向にスキャンします。 図 5-3: 全ページロック・テーブルのクラスタード・インデックスを使った範囲 クエリ select fname, lname, id from employees where lname between "Greaves" and "Highland" Clustered index on lname キー キー ポインタ Page 1001 Bennet 1007 Karsen 1009 Smith 1062 ポインタ Page 1007 Bennet 1132 Greane 1133 Green 1144 Hunter 1127 Page 1009 Karsen 1009 Page 1132 Bennet Chan Dull Edwards Page 1133 Greane Greaves Greco Page 1144 Green Greene Highland Hopper Page 1127 Hunter Jenkins ルート・ページ 中間 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン データ・ページ 71 インデックス・アクセスにかかるコストを評価する カバーリング・インデックスを使う範囲クエリ カバーリング・インデックスを介した範囲クエリは、次の理由から、非常 に効率よく動作します。 • インデックスが、リーフ・レベル・インデックス・ページ上で条件に 合う最初のローに検索を位置付けするために使用される。 • 各インデックス・ページは、対応するデータ・ローよりも多くのロー を格納するため、読み込むページ数が少なくてすむ。 • インデックス・ページはデータ・ページよりも長くキャッシュ内にと どまる傾向があるため、必要な物理 I/O の数が少なくなる。 • インデックスが使用するキャッシュが大容量 I/O 用に設定されてい る場合、1 回の I/O で最大 8 リーフ・ページまで読み込むことがで きる。 • データ・ページにアクセスする必要がない。 データオンリーロック・テーブルのノンクラスタード・インデックスとク ラスタード・インデックスは、どちらもデータ・レベルの上にリーフ・レ ベルがあります。したがって、どちらもインデックス・カバーリングが利 用できます。 カバーリング・インデックスを使うコストは、 次のものから決定されます。 • インデックス・レベルの数 ( ただし、リーフ・レベルは除く ) • クエリが返すロー数 • インデックスのリーフ・レベルでのページあたりのロー数 • 1 回の I/O で読み込まれるリーフ・ページ数 • インデックス・ページがエクステント上に連続して格納されていない 場合に大容量 I/O の調整に使用される、インデックス・ページのクラ スタ率 次の計算式は、コストを示します。 リーフ・ページ数 = 条件に合うローの数 / リーフ・レベルのページあたり のロー数 範囲クエリのコスト =インデックス・レベルの数 * 18 + ( リーフ・ページ数 / IO あたりのページ数 ) * デー タ・ページのクラスタ調整 * 18 + インデックス・レベルの数 * 2 + リーフ・ページ数 * 2 たとえば、あるクエリが 1,200 リーフ・ページの読み込みを必要とし、リー フレベルのページあたり 40 ローがある場合、30 リーフレベル・ページの 読み込みがそのクエリに必要です。大容量 I/O を使用する場合、4 回の I/O が必要です。挿入によって、インデックスのリーフ・ページが分割された 場合、クラスタ調整によって大容量 I/O の回数の見積もりが多くなります。 72 Adaptive Server Enterprise 第5章 1 つのテーブルに対するアクセス・メソッドとクエリ・コスト計算 非カバーリング・インデックスを使う範囲クエリ データオンリーロック・テーブル上のノンクラスタード・インデックスま たはクラスタード・インデックスがクエリをカバーしない場合、Adaptive Server は次の手順を実行します。 • インデックスを使用して、ノンクラスタード・インデックスのリーフ・ レベルにある、条件に合う最初のローを位置付ける。 • そのインデックスに対するデータ・ページを指すポインタをたどって、 ページを読み込む。 • インデックス・ページの次のローを検索してデータ・ページを位置付 ける。すべての一致するキーを使用するまでこの処理を繰り返す。 後続の各キーに対するデータ・ローは、前のキーに対するローと同じペー ジにある場合もあれば、同じテーブル内の別のページにある場合もあり ます。各インデックスに対するキー値のクラスタ状態は、 「データ・ロー のクラスタ率」という値によって測定されます。データ・ローのクラス タ率は、論理 I/O と物理 I/O の回数の見積もりに適用されます。 データ・ローのクラスタ率が 1.0 の場合、クラスタの度合いは非常に高く なっています。クラスタード・インデックスを作成した直後に高いクラス タ率がみられます。このような場合のクラスタ率は、1.00000 または .999997 などです。データ・ページ上のローは、インデックス内のローと 同じ順序で格納されています。データ・ページで必要な論理 I/O と物理 I/O の回数は基本的に、返されるローの数を、ページあたりのロー数で除算し た数です。ページあたり 10 ローであるテーブルの場合、データ・ローの クラスタ率が 1 であると、500 ローを返す必要のあるクエリは 50 ページ を読み込む必要があります。 データ・ローのクラスタ率が非常に低い場合、データ・ローはキーの順序 とは関係なくデータ・ページ上に分散しています。ノンクラスタード・イ ンデックスでは、データ・ローのクラスタ率が低いことはよくあります。 これは、インデックス・キーの順序とデータ・ページ上のデータ・ローの 順序との間に関係がないためです。データ・ローのクラスタ率が 0 または 0 に近い場合、必要な物理 I/O と 論理 I/O の回数が、返されるローごとに データ・ページの I/O が 1 回となることもあります。500 ローを返す必要 のあるクエリの場合、データ・ローのクラスタ率が 0 に近い値で、かつ ローがデータ・ページに広く分散していると、500 ページかそれに近い ページ数の読み込みが必要です。巨大なテーブルであれば、この方法でも 十分なパフォーマンスが得られます。しかし 500 ページ以下のテーブルの 場合、よりコストの低い方法であるテーブル・スキャンがオプティマイザ によって選択されます。 物理 I/O の計算には、データ・キャッシュのサイズも使用されます。デー タ・ローのクラスタ率が非常に低く、キャッシュのサイズが小さい場合は、 ページが再使用される前にキャッシュからフラッシュされる可能性があ ります。キャッシュのサイズが大きい場合、オプティマイザは、キャッ シュ内でみつかるページがあると見積もります。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 73 インデックス・アクセスにかかるコストを評価する 結果セットのサイズとインデックスの使用 少数のローを返す範囲クエリは、インデックスを使うと効率よく実行され ますが、多数のローを返す範囲クエリの場合、インデックスを使用しない ことがあります。これは、多数のインデックス・ページとデータ・ページ に対して論理 I/O と物理 I/O を実行すると、コストが高くなることがある ためです。データ・ローのクラスタ率が低いほど、インデックスを使うと コストが高くなります。 データオンリーロック・テーブル上のノンクラスタード・インデックスま たはクラスタード・インデックスのリーフ・レベルでは、キーはシーケン シャルに格納されます。ある探索引数と一致する値を持つ 100 ローがある 場合、インデックスのリーフ・レベルにあるローはおそらく 1 ページから 2 ページに収まっています。実データ・ローがすべて異なるデータ・ペー ジにある場合もあります。次のクエリは、データ・ローのクラスタ率の違 いが I/O の見積もりに与える影響を示します。authors テーブルは、デー タロー・ロックを使用し、次のインデックスを持ちます。 • クラスタード・インデックス au_lname • ノンクラスタード・インデックス state 下記のクエリはそれぞれ約 100 ローを返します。 select au_lname, phone from authors where au_lname like "E%" select au_id, au_lname, phone from authors where state = "NC" 次の表に、各インデックスに対するデータ・ローのクラスタ率と、返され るロー数および要求されるページ数のオプティマイザによる見積もりを 示します。 探索引数 au_lname データ・ロー・クラスタ率 .999789 ローの見積もり 101 ページの見積もり 8 データ I/O のサイズ 16K state .232539 103 83 2K この表の基本的な情報は、次のとおりです。 74 • テーブル内のページ数は 262 • テーブル内のデータ・ページあたりのロー数は 19 Adaptive Server Enterprise 第5章 1 つのテーブルに対するアクセス・メソッドとクエリ・コスト計算 各クエリには有効な探索引数形式の検索句があり、各句は 1 つのインデッ クスと一致していますが、最初のクエリだけがこのインデックスを使用し ます。その他のクエリについては、インデックスを使うよりテーブル・ス キャンを行う方がコストが低くなります。 ページ数が 262 のテーブルでは、 テーブル・スキャンにかかるコストは次のとおりです。 テーブル・スキャンにかかるコスト = (262 /8) = 37 * 18 =666 + 262 * 2 =524 ____ 1190 探索引数のコスト見積もり詳細 テーブル、クラスタ率、探索引数をより詳しく検証すると、テーブル・ス キャンが選択される理由がわかります。 • • au_lname 上のクラスタード・インデックスの見積もりには、以下の 内訳により、合計 8 回の物理 I/O が含まれる。 • データ・ページに対する 6 回の I/O (16K I/O を使用 )。これは、デー タ・ローのクラスタ率が高いクラスタ状態を示しているため。 • インデックス・ページに対する 2 回の I/O ( リーフ・ページあたり 128 ロー )。リーフ・レベル・インデックス・ページに対しては、 16K I/O も使用される。 データ・ローのクラスタ率が低いため、state で探索引数を使うクエ リは、さらに多くのデータ・ページを読み込む必要がある。オプティ マイザはデータ・ページに対して 2K I/O を選択します。83 回の 物理 I/O は、テーブル・スキャンで必要な物理 I/O (16K I/O を使用 ) の 2 倍 以上です。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 75 インデックス・アクセスにかかるコストを評価する 非カバーリング・インデックスのコスト見積もり クエリが非カバーリング・インデックスを介してデータにアクセスする場 合の I/O を見積もる基本的な式は、次のとおりです。 リーフ・ページ数 = 条件に合うローの数 / リーフ・レベルのページあたりのロー数 データ・ページ数 = 条件に合うローの数 * データ・ローのクラスタ調整 スキャンにかかるコスト = インデックス・レベル ( ただし、リーフ・レベルは除く ) の数 * 18 + ( リーフ・ページ数 IO / あたりのページ数 ) * データ・ページのクラスタ調整 * 18 + ( データ・ページ数 / IO あたりのページ数 ) * データ・ページのクラスタ調整 * 18 + インデックス・レベル ( ただし、リーフ・レベルは除く ) の数 * 18 + リーフ・ページ数 * 2 + 条件に合うローの数 * データ・ローのクラスタ調整 * 2 転送されたローによるコスト カバーされていないインデックス・スキャンでは、データオンリーロッ ク・テーブルに転送されたローがある場合、転送されたローにアクセスす るための追加の I/O にかかるコストの見積もりが追加されます。テーブル 内の転送されたロー数と、クエリによってテーブルから返されるローの パーセンテージを乗算して、コストが計算されます。追加されるコストは 次のとおりです。 転送されたローのコスト = 返されるローのパーセンテージ * テーブル内の転送されたローの数 76 Adaptive Server Enterprise 第5章 1 つのテーブルに対するアクセス・メソッドとクエリ・コスト計算 order by を使ったクエリのコスト見積もり order by 句に対してソートを実行するクエリは、インデックス順に従って ローを返すためのインデックスの作成やソートを行ったり、そのようなイ ンデックスを使ったりします。たとえば、オプティマイザは、order by 句 のあるクエリについて次のアクセス・メソッドのいずれかを選択します。 • 有効な探索引数がない場合 - テーブル・スキャンを使用。続いてワー クテーブルをソートする。 • order by 句と一致しないインデックスを使った、選択性のある探索引 数またはジョインがある場合 - インデックス・スキャンを使用。続 いてワークテーブルをソートする。 • order by 句と一致するインデックスを使った探索引数またはジョイン がある場合 - このインデックスを使うインデックス・スキャン。ワー クテーブルの作成やソートはしない。 結果セットのカラムがインデックス・キーのスーパーセットである場合、 結果セットには必ずソートが必要です。たとえば、authors のインデック スに au_fname と au_lname があり、order by 句にも au_id がある場合は、 クエリにソートが必要となります。 order by 句と一致するインデックスを使った探索引数と、要求された順序 をサポートしていないインデックスを使った探索引数がある場合、オプ ティマイザは両方のアクセス・メソッドのコストを見積もります。ワーク テーブルやソートが必要な場合、インデックス・スキャンにかかるコスト には、これらのオペレーションに対する I/O の実行にかかるコストが加算さ れます。ソートの回避にインデックスが有効な可能性がある場合、探索引 数やジョイン引数のコスト見積もりが発生していても dbcc traceon(302) に よってメッセージが表示されます。 詳細については、 『パフォーマンス&チューニング・ガイド:モニタリン グと分析』マニュアルの「ソート回避メッセージ」(167 ページ ) を参照し てください。 使用できるインデックスの有無以外にも、主な 2 つの要因によって、イン デックスを考慮するかどうかが決定されます。 • order by 句に、インデックス・キーのプレフィクス・サブセットの指 定が必要 • order by 句とインデックスに、互換性のある昇順または降順のキー順 序が必要 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 77 order by を使ったクエリのコスト見積もり プレフィクス・サブセットとソート インデックスを使ってソート手順を回避するクエリの場合、order by 句で 指定されたキーはインデックス・キーのプレフィクス・サブセットである 必要があります。たとえば、インデックスがキーを A,B,C,D と指定した場 合は次のようになります。 • • 次の order by 句は、インデックスを使用できる。 • A • A, B • A, B, C • A, B, C, D その他のカラムの組み合わせは、インデックスを使用できない。たと えば、次のカラム・セットは、プレフィクス・サブセットではありま せん。 • A, C • B, C, D キー順序とソート order by 句とインデックスを作成するコマンドは、どちらも順序の条件付 け asc または desc ( 昇順または降順 ) を使用できます。 • インデックスを作成する場合、asc および desc による修飾で、イン デックスにキーを格納する順序を指定する。 • order by 句では、順序の条件付けによって出力に返すカラムの順序を 指定する。 特定のインデックスを使う場合にソートを回避するには、order by 句内の asc または desc による条件付けを、インデックスの作成に使用した条件 付けとまったく同じにするか、まったく逆にします。 78 Adaptive Server Enterprise 第5章 1 つのテーブルに対するアクセス・メソッドとクエリ・コスト計算 インデックス・キーの昇順/降順を指定する order by order by 句内で昇順と降順を混合で使うクエリでも、次の場合は 通常と同様のソートが実行されます。それは、order by 句で指定されて いる昇順/降順の組み合わせとまったく同じ昇順/降順の組み合わせで インデックスが作成されているか、あるいはまったく逆の順序で作成さ れている場合です。インデックスは、インデックスのリーフ・レベルの ページ・チェーン・ポインタをたどりながら、前後にスキャンされます。 たとえば、次のコマンドは pub_id を昇順、pubdate を降順とするインデッ クスを titles テーブルに作成します。 create index pub_ix on titles (pub_id asc, pubdate desc) ローは、図 5-4 のようにページに並べられます。クエリ内の昇順や降順が、 インデックス作成時の順序と一致した場合は、前方スキャンとなります。イ ンデックスの最初または条件に合う最初のローからスキャンが開始され、 各ページから順にローを返し、次ページ・ポインタをたどって後続のペー ジを読み込みます。 クエリ内での順序がインデックス作成時の順序と正反対の場合は、後方ス キャンとなります。インデックス最後のページまたは条件に合う最後の ローを含むページからスキャンが開始され、各ページから逆の順番でロー を返し、前ページ・ポインタをたどります。 図 5-4: インデックスの前方スキャンと後方スキャン 前方スキャン:ページの順序で ローをスキャンしてから、 次ページ・ポインタをたどる 後方スキャン:ページの逆順で ローをスキャンしてから、 前ページ・ポインタをたどる P066 P066 P066 P073 Page 1132 12/20/93 11/11/93 10/4/93 11/26/93 P073 P087 P087 P087 Page 1133 10/14/93 12/01/93 10/4/93 9/7/93 P066 P066 P066 P073 Page 1132 12/20/93 11/11/93 10/4/93 11/26/93 P073 P087 P087 P087 Page 1133 10/14/93 12/01/93 10/4/93 9/7/93 図 5-4 に示したインデックスを使う次のクエリは、前方スキャンを実行し ます。 select * from titles order by pub_id asc, pubdate desc パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 79 order by を使ったクエリのコスト見積もり 図 5-4 に示したインデックスを使う次のクエリは、後方スキャンを実行し ます。 select * from titles order by pub_id desc, pubdate asc 同じテーブルに対する次の 2 つのクエリの場合、プランにはソート手順が 必要です。これは、order by 句がインデックスに指定された順序と一致し ないためです。 select * from titles order by pub_id desc, pubdate desc select * from titles order by pub_id asc, pubdate asc 注意 並列ソート・オペレーションの最適化は、分割テーブルの場合には 大きく異なります。詳細については、 「第 9 章 並列ソート」を参照してく ださい。 オプティマイザがソート・オペレーションのコストを計算する仕組み Adaptive Server がソートを必要とするクエリを最適化する場合は、次のよ うに実行します。 • 必要なソート順と一致するインデックスが存在する場合は、そのイン デックスを使用した場合のコストを計算する。 • ワークテーブルの作成と、インデックス順がソート順と一致していな いインデックスのソートの実行にかかる、物理 I/O と論理 I/O のコス トを計算する。テーブル・スキャンの実行、ワークテーブルの作成、 ソートの実行にかかる、物理 I/O と論理 I/O のコストを計算する。 インデックスへのアクセスにかかるコストに、ワークテーブルの作成と ソートにかかるコストを加算するので、order by 句をサポートするイン デックスを使用する方が有利に見えるかも知れません。しかし、非常に 高い選択性を持つが順序付けられていないインデックスと、選択性を持 たないが順序付けられたインデックスとを比較する場合、次のようにな ります。 80 • 選択性が高い方のインデックスの場合、アクセスにかかるコストは 低く、ソート・コストも同様に低くなる。 • 選択性が低い方のインデックスの場合、アクセスにかかるコストは 高く、より高い選択性を持つインデックスとソートを使った場合の コストを超える場合がある。 Adaptive Server Enterprise 第5章 1 つのテーブルに対するアクセス・メソッドとクエリ・コスト計算 クラスタード・インデックスのある全ページロック・テーブル クラスタード・インデックスのある全ページロック・テーブルの場合、イ ンデックス・キーと一致する order by クエリは、次の場合に効率的です。 • インデックスを使う探索引数もあり、そのインデックス・キーに よって、データ・ページ上では条件に合う最初のローに検索が位置 付けされる。 • 条件に合うローがすべて見つかるまで、次ページ・ポインタをたどっ てスキャンが行われる。 • ソートの必要がない。 図 5-5 の例では昇順でインデックスが作成され order by 句で順序が指定 されていません。このため、デフォルトでは昇順が使用されます。 図 5-5: クラスタード・インデックスを使う order by クエリ ( 全ページ・ロック ) select fname, lname, id from employees where lname between "Dull" and "Greene" order by lname Page 1132 Bennet Chan Dull Edwards Clustered index on lname キー キー ポインタ Page 1001 Bennet 1007 Karsen 1009 Smith 1062 ポインタ Page 1007 Bennet 1132 Greane 1133 Green 1144 Hunter 1127 Page 1009 Karsen 1009 Page 1133 Greane Greaves Greco Page 1144 Green Greene Highland Page 1127 Hunter Jenkins ルート・ページ 中間 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン データ・ページ 81 order by を使ったクエリのコスト見積もり 降順のソートを必要とするクエリ ( たとえば、order by title_id desc) は、 ページを逆順にスキャンすることでソートを回避できます。where 句のな いクエリのためにテーブル全体が必要なときは、Adaptive Server は最後の ページまでインデックス・ポインタをたどり、そこから 1 つ前のページの ポインタを順番に使用して逆方向にスキャンします。インデックス・キー に where 句がある場合は、このインデックス・キーを使用して検索を位 置付けし、図 5-6 に示すようにページを逆方向にスキャンします。 図 5-6: クラスタード・インデックスを使う order by desc クエリ select fname, lname, id from employees where lname <= "Highland" order by lname desc Clustered index on lname Page 1132 Bennet Chan Dull Edwards キー キー ポインタ Page 1001 Bennet 1007 Karsen 1009 Smith 1062 ポインタ Page 1007 Bennet 1132 Greane 1133 Green 1144 Hunter 1127 Page 1009 Karsen 1009 Page 1133 Greane Greaves Greco Page 1144 Green Greene Highland Page 1127 Hunter Jenkins ルート・ページ 82 中間 データ・ページ Adaptive Server Enterprise 第5章 1 つのテーブルに対するアクセス・メソッドとクエリ・コスト計算 インデックスがクエリをカバーする場合のソート インデックスがクエリをカバーし、かつ order by カラムがインデックス・ キーのプレフィクス・サブセットを構成する場合、ローはノンクラスター ド・インデックスのリーフ・ページから直接返されます。カラムがイン デックス・キーのプレフィクス・サブセットではない場合は、ワークテー ブルが作成されてソートされます。 authors テーブルの au_lname、au_fname、au_id にノンクラスタード・ インデックスが設定されている場合、次のクエリはリーフ・ページから直 接データを返します。 select au_id, au_lname from authors order by au_lname, au_fname ソートと非カバーリング・インデックス 非カバーリング・インデックスを使用する際には、Adaptive Server は、順 序の要件を満たすインデックスの使用にかかるコストが、テーブル・ス キャンやより選択性の高いインデックスを使用してワークテーブルを作 成しソートするコストより低いかどうかを考慮します。インデックスを使 うコストは、ロー数やデータ・ローのクラスタ率によって異なります。 後方スキャンとジョイン 2 つ以上のテーブルがジョインされており、ジョインされたテーブルのイ ンデックス・キーについて order by 句で降順を指定している場合、関連 した各テーブルと各インデックスを後方スキャンすることで、ワークテー ブルとソートにかかるコストを避けることができます。ある 1 つのテーブ ルのカラムがすべて昇順で、それ以外のテーブルのカラムがすべて降順の 場合は、前者のテーブルは昇順でソートされ、後者のテーブルは降順で ソートされます。 デッドロックと降順スキャン 降順スキャンが、昇順スキャンを使用して更新オペレーションを実行する クエリと、ページ分割とページ・シュリンクを実行するクエリでデッド ロックを起こす可能性があります。ただし、トランザクション独立性レベ ル 0 で逆方向のスキャンを実行する場合を除きます。 allow backward scans 設定パラメータによって、オプティマイザが逆方向 のスキャン方式を使うかどうかを制御できます。デフォルト値の 1 は、降 順スキャンを許可します。 このパラメータの詳細については、 『システム管理ガイド』を参照してく ださい。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 83 アクセス・メソッドと or 句および in 句のコスト計算 また、実行される昇順スキャンと降順スキャンの数の詳細については、 「イ ンデックス・スキャン」(72 ページ ) を、デッドロックの検出の詳細につ いては、 『パフォーマンス&チューニング・ガイド:モニタリングと分析』 の「ロックのタイプごとのデッドロック」(82 ページ ) を、それぞれ参照 してください。 アクセス・メソッドと or 句および in 句のコスト計算 1 つのテーブルにあるクエリに or 句または in (values_list) 句がある場合、 インデックスの有無、探索引数の選択性、その他の探索引数の有無、重複 するローが返されるかどうか、などによって最適化の方法が異なります。 or 構文 クエリで or 句を使用する場合、オプティマイザはテーブル・スキャンに 対してだけでなく、カバード・インデックス・スキャンに対しても、より コストの高い OR 方式を選択することがあります。これは、この方式に よってロックの同時実行性が向上するためです。 or 句の形式は次のとおりです。 where column_name1 = <value> or column_name1 = <value> ... または where column_name1 = <value> or column_name2 = <value> ... in (values_list) から or 処理への変換 前処理として、in リストを or 句に変換します。 select title_id, price from titles where title_id in ("PS1372", "PS2091","PS2106") 変換後は、次のようになります。 select title_id, price from titles where title_id = "PS1372" or title_id = "PS2091" or title_id = "PS2106" 84 Adaptive Server Enterprise 第5章 1 つのテーブルに対するアクセス・メソッドとクエリ・コスト計算 or 句に対する処理の仕組み or 句を含むシングルテーブル・クエリは、複数のクエリを結合したもの です。複数の条件と一致するローがあっても、そのローは 1 回だけ返され ます。or クエリは、インデックスやクエリ句に応じた次のいずれかの方 法で解析されます。 • or によってリンクされた句のいずれかにインデックスがない場合、 テーブル・スキャンが使用される。type にインデックスがあり advance にはない場合は、テーブル・スキャンが行われます。 select title_id, price from titles where type = "business" or advance > 10000 • 1 つ以上の or 句が同じローにある値と一致する可能性がある場合、 「OR 方式」を使ってクエリが解析される。これは、 「動的インデック ス」を使用する方式としても知られています。OR 方式では一致する ローのロー ID を選択してワークテーブルに入れ、ワークテーブルを ソートして重複するロー ID を削除します。たとえば、両方の条件が 真であるローのある場合があります。 select title_id from titles where pub_id = "P076" or type > "business" pub_id、type にそれぞれインデックスがある場合、OR 方式が使用さ れます。 詳細については、 「動的インデックス (OR 方式 )」(87 ページ ) を参照 してください。 注意 OR 方式 ( 複数のマッチング・インデックス・スキャン ) は、等号 述部に対してのみ当てはまります。他の条件が満たされる場合でも、 範囲述部には不適切です。たとえば、select 文に次のものが含まれる 場合、 where bar between 1 and 5 or bar between 10 and 15 これは OR 方式とはみなされません。 • or 句が同じローを選択する可能性がない場合、複数のマッチング・イ ンデックス・スキャンでクエリが解析される。これは、 「特殊 OR 方 式」としても知られています。特殊 OR 方式では、ワークテーブルと ソートが必要ありません。このクエリ内の or 句は、同じローを 2 回選 択することができません。 select title_id, price from titles where pub_id = "P076" or pub_id = "P087" パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 85 アクセス・メソッドと or 句および in 句のコスト計算 pub_id にインデックスがある場合、このクエリは 2 種類のマッチン グ・インデックス・スキャンを使って解析されます。 詳細については、 「複数のマッチング・インデックス・スキャン ( 特殊 OR 方式 )」(88 ページ ) を参照してください。 • 各 or 句のインデックス・アクセスにかかるコストが合算され、必要 に応じてソートにかかるコストも加算される。これらのコストの合計 がテーブル・スキャンよりも大きい場合、テーブル・スキャンが選択 されます。たとえば、pub_id における全インデックス・スキャンに かかるコストの合計がテーブル・スキャンよりも大きくなる場合、こ のクエリはテーブル・スキャンを使用します。 select title_id, price from titles where pub_id in ("P095", "P099", "P128", "P220", "P411", "P445", "P580", "P988") • クエリに、インデックス・カラムを使った他の探索引数がある場合、 述部の変形によって最適化できる探索引数が追加され、最適化の選択 肢が増える。選択肢となったすべてのアクセス・メソッドの使用のコ ストが比較され、最もコストが低いメソッドが選択されます。次のク エリには type に関する探索引数が含まれており、句は or でリンクさ れています。 select title_id, type, price from titles where type = "business" and (pub_id = "P076" or pubdate > "12/1/93") 各探索引数に別個のインデックスがある場合、オプティマイザは最も コストが低いアクセス・メソッドを使用します。 • type のインデックス • pub_id と pubdate の OR 方式 or クエリにテーブル・スキャンを使用する場合 or 句または in (values_list) 句を含むクエリは、次の条件の 1 つが真である 場合にテーブル・スキャンを使います。 86 • どのインデックス・アクセスにかかるコストも、テーブル・スキャン のコストより大きい場合 • インデックスを持たないカラムが 1 つ以上指定されているため、そ のクエリ条件を解析する手段が、テーブル・スキャンの実行しかな い場合 Adaptive Server Enterprise 第5章 1 つのテーブルに対するアクセス・メソッドとクエリ・コスト計算 動的インデックス (OR 方式 ) クエリが重複するローを返すので OR 方式を使う場合、各 or 句を満たす ローの ID を取得するために適切なインデックスが使用されます。各 or 句 に対するロー ID は、ワークテーブルに格納されます。ワークテーブルに はロー ID しかないため、これを「動的インデックス」といいます。次に Adaptive Server はワークテーブルをソートして、重複するロー ID を削除 します。ロー ID は、ベース・テーブルからローを取り出すときに使用し ます。クエリの合計コストには、次のものが含まれます。 • インデックス・アクセスの合計。つまり、各 or 句における、インデッ クスのリーフ・ページ ( 全ページロック・テーブルのクラスタード・ インデックスの場合は、データ・ページ ) 上のロー ID にアクセスす るためにかかるコスト。 • ワークテーブルの読み込みとソートの実行にかかるコスト。 • データ・ページにアクセスするためのロー ID の使用にかかるコスト。 図 5-7 は、2 つの異なるカラムにある or クエリの動的インデックスを構 築し、ソートする処理を示します。 図 5-7: OR 方式を使った or クエリの解析 select title_id, price from titles where price <= $15 or title like "Compute%" インデックス・リーフ・ ページでローを検出 結果をワーク・ テーブルに保存 ソートして重複 するものを削除 Page 1441 Tricks ... $23 Computer... $29 Garden... $20 Best... $50 title_id_ix Page 1239 Backwards... 1527, 4 Computer... 1441,4 Computer... 1537,2 Optional... 1923, 7 price_ix $14 $15 $15 $15 $16 Page 1473 1427, 8 1941, 2 1537, 2 1822, 5 1445,6 データ・ページ上の ローにアクセス Page 1441 1537 1941 1537 1822 Row 4 2 2 2 5 Page 1441 1537 1537 1822 1941 Row 4 2 2 5 2 Page 1537 Using ... $27 Computer... $15 New... $18 Home... $44 ( ページ 1882 へ ) ( ページ 1941 へ ) パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 87 アクセス・メソッドと or 句および in 句のコスト計算 図 5-7 に示すように、オプティマイザによって、それぞれの句が別のイン デックスを使用するようにできます。 OR 方式を使っている場合、showplan によって “Using Dynamic Index”、 “Positioning by Row IDentifier (RID)” が表示されます。 詳細については、 『パフォーマンス&チューニング・ガイド:モニタリン グと分析』マニュアルの「動的インデックスのメッセージ (OR 方式 )」(99 ページ ) を参照してください。 カーソル内のクエリは、OR 方式を使うことはできないので、テーブル・ スキャンを実行しなければなりません。しかし、カーソル内のクエリでも、 複数のマッチング・インデックス・スキャンを使うことはできます。 OR 方式使用中のクエリのロックは、テーブルのロック・スキームによっ て異なります。 複数のマッチング・インデックス・スキャン ( 特殊 OR 方式 ) or 句が同じテーブルにあり、かつ or 句が重複したローを返す可能性がな い場合、Adaptive Server は複数のマッチング・インデックス・スキャンを 使用します。たとえば、次のクエリは重複したローを返しません。 select title from titles where title_id in ("T6650", "T95065", "T11365") このクエリは、title_id のインデックスを使った複数のマッチング・イン デックス・スキャンを使用して解析されます。クエリの合計コストは、実 行された複数のインデックス・アクセスの合計となります。title_id のイ ンデックスに レベルが 3 つある場合、各 or 句にはインデックス読み込み 3 回とデータ・ページ読み込み 1 回が必要です。したがって、各句の合計 コストは 4 回の論理 I/O および 4 回の物理 I/O となり、合計クエリ・コス トの見積もりは 12 回の論理 I/O および 12 回の物理 I/O となります。 オプティマイザは、or 句または in (values_list) 句にある値のそれぞれにつ いて別々にコストを計算し、使用するインデックスを決定します。句に指 定されている各カラムにインデックスがある場合、句または値のそれぞれ について異なるインデックスを使用できます。特殊 OR 方式が使用されて いる場合、showplan は、メッセージ “Using N Matching Index Scans” を表 示します。 詳細については、 『パフォーマンス&チューニング・ガイド:モニタリン グと分析』の「マッチング・インデックス・スキャンのメッセージ」(98 ページ ) を参照してください。 88 Adaptive Server Enterprise 第5章 1 つのテーブルに対するアクセス・メソッドとクエリ・コスト計算 集合関数の最適化方法 集合関数は、次の 2 つの手順で処理されます。 • まず、適切なインデックスを使って適切なローが検索されるか、テー ブル・スキャンが実行されます。ベクトル ( グループ化 ) 集合関数の 場合は、結果はワークテーブル内に置かれます。スカラ集合関数の場 合は、結果はメモリ内で変数として計算されます。 • 次に、ベクトル集合関数の場合はワークテーブルがスキャンされて、 結果が戻されます。または内部変数から結果が返されます。 ベクトル集合関数は、集合カラムとグループ化カラムに対して複合イン デックスがあれば、テーブル・スキャンでなくカバーリング複合インデッ クスを使用することができます。たとえば、titles テーブル内の type、price にノンクラスタード・インデックスが設定されている場合、次のクエリは ノンクラスタード・インデックスのリーフ・レベルをスキャンして結果を 検索します。 select type, avg(price) from titles group by type スカラ集合関数も、カバーリング・インデックスを使用して I/O を減らす ことができます。たとえば、次のクエリは、type、price への複合インデッ クスを使用できます。 select min(price) from titles 表 5-1 は、集合関数を含むクエリ (where 句、having 句、group by 句はあ りません ) に対して、オプティマイザが選択できるアクセス・メソッドを 示します。 表 5-1: 集合関数の特殊なアクセス・メソッド 集合関数 min インデックスの説明 アクセス・メソッド スカラ集合関数は先行カラム インデックスのルート・ページの最初の値を使う。 max 全ページロック・テーブルのクラス タード・インデックス ルート・ページの最後のポインタと、データ・ペー ジまでの中間ページをたどって、最後の値を返す。 データオンリーロック・テーブルの クラスタード・インデックス ルート・ページの最後のポインタと、リーフ・ペー ジまでの中間ページをたどって、最後の値を返す。 あらゆるノンクラスタード・イン デックス count(*) データオンリーロック・テーブルの ノンクラスタード・インデックスま たはクラスタード・インデックス count(col_name) データオンリーロック・テーブルの カラム名を含むインデックスの、最も小さなリー カバーリング・ノンクラスタード・ フ・レベル内にあるすべての null 以外の値をカウン インデックスまたはカバーリング・ トする。 クラスタード・インデックス インデックスのリーフ・レベル内で、最もページ番 号が小さいページにあるすべてのローをカウント する。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 89 集合関数の最適化方法 集合関数 max と min の組み合わせの処理 先行インデックスを持つカラムに対して、集合関数の max と min を別々 に実行すると、クエリ内に where 句がない場合には、次のような特別な 処理が行われます。 • min 集合関数は、インデックスのルート・ページの最初の値を検索し、 読み込みを 1 回実行して値を見つける。 • max 集合関数は、リーフ・レベルに到達するまでは、各インデック ス・レベルの最終ページの最終エントリをたどる。 しかし、min と max を同時に使用すると、これらの最適化は使用されま せん。インデックスのリーフ・レベル全体がスキャンされて最初の値と最 後の値が配置されます。 次の場合には、min および max 最適化を適用できません。 • max 関数または min 関数の内部の式がカラムではない場合。 numeric_col にノンクラスタード・インデックスが設定されている場合、 次の処理が行われます。 • max(numeric_col*2) は、カラムの演算を含むため、リーフ・レ ベル・インデックス・ページのスキャンを実行する。 • max(numeric_col)*2 は、関数の結果に対して乗算が実行されてい るため、max 最適化を使っている。 • クエリに別の集合関数がある場合。 • group by 句がある場合。 min と max の両方を使用するクエリ 最適化可能な max と min 集合関数がある場合は、これらの集合関数を 別々のクエリで使用することで、パフォーマンスがかなり向上します。た とえば、先行キーとして price にインデックスがある場合でも、次のクエ リでは、結果としてインデックスのリーフ・レベル全体のスキャンが行わ れます。 select max(price), min(price) from titles この関数を別々にした場合、Adaptive Server では、リーフ・レベル全体が スキャンされる代わりに、2 つのクエリのどちらにも 1 回ずつインデック スが使用されます。次に 2 つのクエリの例を示します。 select max(price) from titles select min(price) from titles 90 Adaptive Server Enterprise 第5章 1 つのテーブルに対するアクセス・メソッドとクエリ・コスト計算 更新オペレーションの実行方法 Adaptive Server は、ローを位置付けるのに使われるインデックスとデー タに対する変更内容に応じて、さまざまな方法で更新を処理します。更 新は、「遅延更新」と「直接更新」の 2 種類に大別できます。Adaptive Server は、可能なかぎり直接更新を実行します。 直接更新 Adaptive Server は直接更新を 1 つのステップで処理します。具体的には次 のとおりです。 • 更新の影響が及ぶインデックス・ローとデータ・ローを位置付ける。 • 変更に対するログ・レコードをトランザクション・ログに書き込む。 • データ・ページと影響が及ぶインデックス・ページを更新する。 直接更新には、次の 3 つの手法があります。 • 置き換え更新 • 低コストの直接更新 • 高コストの直接更新 直接更新は、遅延更新よりもオーバヘッドが少なくて済み、一般的に処理 速度も高速です。これは、Adaptive Server がページを再フェッチしてロ グ・レコードに基づいて修正を実行する必要がないため、直接更新によっ てログ・スキャン数が限定され、ログの採取を少なくし、インデックスの B ツリーの検索 ( ロック競合も減少する ) と I/O 回数を節約するためです。 置き換え更新 Adaptive Server は、できるかぎり置き換え更新を実行します。 Adaptive Server が置き換え更新を実行するときには、ページ上にある後続 のローは移動しません。ロー ID は変わらず、ロー・オフセット・テーブ ル内のポインタも変更されません。 置き換え更新を実行するには、次の条件がすべて満たされている必要があ ります。 • 変更対象のローの長さが変更後も変わらない場合。 • 更新対象のカラムが、全ページロック・テーブルのクラスタード・イ ンデックスのキーかキーの一部ではない場合。全ページロック・テー ブルのクラスタード・インデックス内のローはキー順に格納される ため、キーを変更するとほとんどの場合ローの位置が変わります。 • 1 つまたは複数のインデックスがユニークであり、重複した値が許さ れていなければならない場合。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 91 更新オペレーションの実行方法 • 更新文が「ジョインによる更新モードの制限」(97 ページ ) に挙げら れた条件を満たしている場合。 • 更新の影響を受けるカラムが、参照整合性の対象でない場合。 • カラムにトリガを設定していない場合。 • テーブルを (Replication Server を介して ) 複写していない場合。 置き換え更新は更新方法の中で最も速い方法です。これは、データ・ペー ジに対して変更が 1 つだけ行われるためです。置き換え更新の影響を受け るすべてのインデックス・エントリは、古いインデックス・ローを削除し て新しいインデックス・ローを挿入する方法によって更新されます。置き 換え更新では、ページとローの位置が変更されないため、変更されるキー を持つインデックスだけが影響を受けます。 低コストの直接更新 Adaptive Server が置き換え更新を実行できない場合は、低コストの直接更 新を試みます。低コストの直接更新は、ローを変更し、ページ上の同じオ フセットにローを再度書き込みます。ページにある後続のローは前か後ろ に移動して、ページ上のデータを連続したままに保ちますが、ロー ID は 変わりません。ロー・オフセット・テーブル内のポインタは変更され、新 しい位置を指します。 低コストの直接更新は、次の条件を満たす必要があります。 • ロー内のデータの長さは変わるが、ローは更新前と同じデータ・ペー ジ上に収まる場合。またはローの長さは変わらないが、テーブルに トリガが設定されているか、テーブルが複写 ( レプリケート ) される 場合。 • 更新対象のカラムが、クラスタード・インデックスのキーかキーの一 部ではない場合。Adaptive Server はクラスタード・インデックス内の ローをキー順に格納するため、キーを変更するとほとんどの場合ロー の位置が変わります。 • 1 つまたは複数のインデックスがユニークであり、重複した値が許さ れていなければならない場合。 • 更新文が「ジョインによる更新モードの制限」(97 ページ ) に挙げら れた条件を満たしている場合。 • 更新の影響を受けるカラムが、参照整合性の対象でない場合。 低コストの直接更新は、置き換え更新とほぼ同じ速度で処理されます。必要 な I/O 数も同じですが、わずかに多くの CPU 処理を必要とします。データ・ ページには 2 つの変更 ( ローとオフセット・テーブル ) がなされます。変更 されたインデックス・キーは、古い値が削除され、新しい値が挿入されて更 新されます。ページとロー ID が変わらないため、変更されるキーを持つイ ンデックスだけが更新の影響を受けます。 92 Adaptive Server Enterprise 第5章 1 つのテーブルに対するアクセス・メソッドとクエリ・コスト計算 高コストの直接更新 データが同じページに収まらない場合は、Adaptive Server は、高コストの 直接更新が可能であれば、それを実行します。高コストの直接更新は、す べてのインデックス・エントリとデータ・ローを削除してから、修正され たローとインデックス・エントリを挿入します。 Adaptive Server は、テーブル・スキャンかインデックスを使って更新前 の位置にあるローを見つけ、ローを削除します。テーブルにクラスター ド・インデックスがある場合、Adaptive Server はクラスタード・インデッ クスを使ってローの新しい位置を決定します。クラスタード・インデッ クスがない場合は、Adaptive Server はヒープの終わりに新しいローを挿 入します。 高コストの直接更新は、次の条件を満たす必要があります。 • データ・ローの長さが変わるため、更新前と同じデータ・ページに収 まらなくなり、ローを別のページに移動しなければならない場合。ま たはクラスタード・インデックスのキー・カラムが更新の影響を受け る場合。 • ローを見つけるのに使われたインデックスが更新によって変更され ない場合。 • 更新文が「ジョインによる更新モードの制限」(97 ページ ) に挙げら れた条件を満たしている場合。 • 更新の影響を受けるカラムが、参照整合性の対象でない場合。 高コストの直接更新は、直接更新のなかで最も遅い更新です。削除が実 行されるデータ・ページと挿入が実行されるページが異なります。ロー・ ロケーションが変わるため、すべてのインデックス・エントリが更新さ れます。 遅延更新 Adaptive Server は、直接更新の条件が満たされない場合に、遅延更新を使 います。遅延更新は、更新のなかで最も遅い更新です。 遅延更新では、Adaptive Server は次のことを実行します。 • 更新対象のデータ・ローを位置付け、それと同時に、データ・ページ の遅延削除と遅延挿入に関するログ・レコードを書き込む。 • トランザクション用ログ・レコードを読み込み、データ・ページと、 更新の影響が及ぶすべてのインデックス・ローを削除する。 • ログを再度読み込み、データ・ページに対するすべての挿入を実行し、 更新の影響が及ぶすべてのインデックス・ローを挿入する。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 93 更新オペレーションの実行方法 遅延更新が必要な場合 次の場合には常に遅延更新が選択されます。 • セルフジョインを使う更新の場合。 • 自己参照整合性の対象であるカラムを更新する場合。 • 相関サブクエリ内で参照されるテーブルを更新する場合。 次の場合も、遅延更新が必要です。 • テーブル・スキャンまたはクラスタード・インデックスを介してテー ブルがアクセスされている間に、更新によってローが新しいページに 移動する場合。 • テーブルに重複するローが許されず、これを防ぐユニークなインデッ クスが存在しない場合。 • データ・ローを見つけるのに使われるインデックスがユニークでは なく、その更新によってクラスタード・インデックス・キーが変更 されるため、または新しいローがページ上に収まらないため、ロー が移動する場合。 遅延更新では、Adaptive Server がデータとインデックスに最終的な変更 を行うためにトランザクション・ログを再度読み込まなければならない ため、直接更新よりもオーバヘッドが高くなります。このため、余分な インデックス・ツリーの検索が必要になります。 たとえば、title にクラスタード・インデックスが設定されている場合、次 のクエリは遅延更新を実行します。 update titles set title = "Portable C Software" where title = "Designing Portable Software" インデックスの遅延挿入 Adaptive Server は、テーブルへのアクセスに使用されるインデックスまた はユニーク・インデックス内のカラムに更新が影響する場合に、インデッ クスの遅延更新を実行します。この種類の更新では、Adaptive Server は次 の処理を行います。 94 • インデックスのエントリを直接モードで削除する。 • データ・ページを直接モードで更新し、そのインデックスに対する遅 延挿入レコードを書き込む。 • そのトランザクションに対するログ・レコードを読み込み、インデッ クスの新しい値を遅延モードで挿入する。 Adaptive Server Enterprise 第5章 1 つのテーブルに対するアクセス・メソッドとクエリ・コスト計算 インデックスの遅延挿入モードは、ローを見つけるのに使われるインデッ クスが更新によって変更される場合、またはユニークなインデックスが更 新の影響を受ける場合に使われます。どのクエリも 1 つの条件を満たす ローをただ一度だけしか更新できません。したがって、インデックスの遅 延更新モードは、インデックス・スキャン時にローが一度だけ見つかり、 早い時期に一意性制約に違反しないことを保証します。 次の更新の例 ( 図 5-8 を参照 ) では、姓だけが変更されますが、インデッ クス・ローが次のページに移動します。この更新では、Adaptive Server は 次の手順に従います。 1 インデックス・ページ 1133 を読み込み、このページから “Greene” を 表すインデックス・ローを削除し、遅延インデックス・スキャン・レ コードのログを採取します。 2 直接モードで、データ・ページ上の “Green” を “Hubbard” に変更しま す。次にインデックス・スキャンを続け、更新の必要があるローが他 にもあるかどうかを確認します。 3 スキャンが完了したら、ページ 1127 に “Hubbard” を表す新しいイン デックス・ローを挿入します。 図 5-8 は、遅延更新の操作が実行される前のインデックスとデータ・ペー ジ、および遅延更新によってデータとインデックス・ページが変更される 順序を示しています。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 95 更新オペレーションの実行方法 図 5-8: インデックスの遅延更新 update employee set lname = "Hubbard" where lname = "Green" キー ロー ID ポインタ 更新前 キー キー ロー ID ポインタ Page 1001 Bennet 1421,1 1007 Karsen 1411,3 1009 Smith 1307,2 1062 Page 1007 Bennet 1421,1 1132 Greane 1307,4 1133 Hunter 1307,1 1127 Page 1009 Karsen 1411,3 1315 ポインタ Page 1132 Bennet 1421.1 Chan 1129,3 Dull 1409,1 Edwards 1018,5 Page 1133 Greane 1307.4 Green 1421.2 Greene 1409,2 Page 1127 Hunter 1307.1 Jenkins 1242,4 ルート・ページ リーフ・ページ 手順 1:ログ・レコード を書き込んでから、 インデックス・ローを 削除する。 Page 1133 Greane 1307.4 Greene 1409,2 手順 2:データ・ページ を変更する。 手順 3:ログを読み込 んで、インデックス・ ローを挿入する。 96 Page 1242 O’Leary Ringer White Jenkins 14 15 16 17 Page 1307 Hunter Smith Ringer Greane 18 19 20 Page 1421 Bennet Green Yokomoto 21 22 23 Page 1409 Dull Greene White データ・ページ n Gree 更新手順 中間 10 11 12 13 18 19 20 Page 1421 Bennet Hubbard Yokomoto Page 1127 Hubbard 1421,2 Hunter 1307.1 Jenkins 1242,4 Adaptive Server Enterprise 第5章 1 つのテーブルに対するアクセス・メソッドとクエリ・コスト計算 titles テーブルにも、次のような同様の更新が実行されるとします。 update titles set title = "Computer Phobic’s Manual", advance = advance * 2 where title like "Computer Phob%" このクエリには、次のような問題が起こる可能性があります。title カラム 上 の ノ ン ク ラ ス タ ー ド・イ ン デ ッ ク ス を 使 っ た ス キ ャ ン に よ っ て “Computer Phobia Manual” が見つかったため、本のタイトルを変更し、前 払い金額を 2 倍した後で、新しいインデックス・ロー “Computer Phobic’s Manual” が見つかり、前払い金額を 2 倍したとすると、前払い金額は非常 に現実離れしたものになります。 スキャンする必要のあるログ・レコードの数とログ・ページがキャッシュ 内にとどまるかどうかによって、遅延モードでのインデックスの削除は、 高コストの直接更新よりも速くなる場合と遅くなる場合があります。 データ・ローの遅延更新時には、インデックス・ローを削除してから新し いインデックス・ローを挿入するまでにかなりの時間的な間が生じること があります。この合間には、データ・ローに対応するインデックス・ロー はありません。この間に独立性レベル 0 でプロセスがインデックスをス キャンした場合、データ・ローの新しい値も古い値も返されません。 ジョインによる更新モードの制限 更新対象のテーブルが、ジョイン順で最も外側のテーブルの場合、または ジョイン順で先行する他のテーブルが条件を満たすローを 1 ローしか持た ない場合、ジョインが関係する更新と削除は、直接モード、deferred_varcol モード、または deferred_index モードのいずれかで実行されます。 更新文と削除文内のジョインとサブクエリ Transact-SQL の、ANSI SQL に対する拡張の 1 つとして、update 文および delete 文でのジョインの実行に from 句を使用できます。更新と削除には、 ジョインの代わりに ANSI SQL 形式のサブクエリを使用できます。 from 構文を使ってジョインを実行する例を次に示します。 update t1 set t1.c1 = t1.c1 + 50 from t1, t2 where t1.c1 = t2.c1 and t2.c2 = 1 次の例は、サブクエリを使った同じ更新を示します。 update t1 set c1 = c1 + 50 where t1.c1 in (select t2.c1 from t2 where t2.c2 = 1) パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 97 更新オペレーションの実行方法 ジョイン・クエリに使う更新モードは、更新テーブルがジョイン順で最も 外側のクエリであるかどうかによります。更新テーブルが最も外側のテー ブルではない場合、更新は遅延モードで実行されます。サブクエリを使っ た更新は常に、直接更新、deferred_varcol 更新、deferred_index 更新のいず れかで実行されます。 from 構文を含み、ジョイン順のために遅延更新を実行するクエリの場合、 showplan と statistics io を使って、 サブクエリを使ったクエリに書き直すこ とでパフォーマンスが改善されるかどうかを判断してください。ただし、 from 構文を使用するすべてのクエリが、サブクエリを使用する形に書き換 え可能ではありません。 トリガ内での更新/削除と参照整合性 deleted または inserted テーブルとユーザ・テーブルとをジョインするト リガは、遅延モードで実行されます。参照整合性を実現するためだけにト リガを使用し、更新と削除をカスケードしない場合、トリガの代わりに宣 言型の参照整合性を使うことによって、トリガ内での遅延更新のペナル ティを回避することができます。 更新の最適化 showplan の出力は、更新が直接モードと遅延モードのどちらで実行され るかに関する情報を示します。直接更新が実行できない場合は、Adaptive Server はデータ・ローを遅延モードで更新します。しかし、直接モードと 遅延モードのどちらが実行されるかをオプティマイザが判断できない場 合があり、この場合のために次の 2 つの showplan の出力が用意されてい ます。 • “deferred_varcol” の出力は、更新対象が可変長カラムであるため、更 新によってローの長さが変更される可能性があることを示す。更新後 のローがページに収まる場合は、更新は直接モードで実行され、更新 後のローがページに収まらない場合は、遅延モードで実行される。 • “deferred_index” の出力は、データ・ページへの変更とインデックス・ ページからの削除は直接モードで実行され、インデックス・ページへ の挿入は遅延モードで実行されることを示す。 直接更新のうちどの更新が実行されるかは、実行時にしかわからない情報 に基づいて決まります。たとえば、ローがページに収まるかどうかを判断 するには、ページを実際にフェッチして調べなければなりません。 98 Adaptive Server Enterprise 第5章 1 つのテーブルに対するアクセス・メソッドとクエリ・コスト計算 直接更新に向けた設計 アプリケーションを設計およびコーディングするときには、どのような条 件の違いが遅延更新を引き起こすかについて注意を払ってください。次の ガイドラインに従って可能なかぎり遅延更新を避けてください。 • テーブルに少なくとも 1 つのユニーク・インデックスを作成して、直 接更新が行われやすいようにする。 • あるキーを更新するときは、可能なかぎり、where 句内ではそのキー 以外のカラムを使う。 • カラムに null 値を使用しない場合は、create table 文でこれらのカラ ムを not null と宣言する。 インデックス設定と更新の種類 表 5-2 は、異なる 3 つの更新での更新モードに対するインデックスによる 影響を示します。いずれの場合も重複するローは許されていません。イン デックスが設定されている場合は、インデックスは title_id にあります。 次に、3 つの更新の種類を示します。 • 可変長キー・カラムの更新 update titles set title_id = value where title_id = "T1234" • キー・カラム以外の固定長カラムの更新 update titles set pub_date = value where title_id = "T1234" • キー・カラム以外の可変長カラムの更新 update titles set notes = value where title_id = "T1234" 表 5-2 は、ユニーク・インデックスが、同じキーに対して、ユニークでな いインデックスよりもいかに効果的な更新を行えるのかを示しています。 表で網掛けされた部分について、直接更新の場合と遅延更新の場合との相 違点には、特に注意してください。たとえば、ユニーク・クラスタード・ インデックスを使用すると、更新はすべて直接モードで実行されますが、 インデックスがユニークでない場合は遅延モードで実行されます。 ユニークでないクラスタード・インデックスのあるテーブルでも、テーブ ル内の他のいずれかのカラムにユニーク・インデックスがあれば、更新の パフォーマンスは向上します。場合によっては、テーブルに IDENTITY カ ラムを追加して、ユニークでないインデックスの中のキーとしてカラムを 取り込むことができます。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 99 更新オペレーションの実行方法 表 5-2: 更新モードのインデックス設定の種類 変更対象 インデックス 可変長キー 固定長カラム インデックスなし なし 直接 可変長カラム deferred_varcol ユニーク・クラスタード・インデックス 直接 直接 直接 ユニークでないクラスタード・インデックス 遅延 遅延 ユニークでないクラスタード・インデックス ( 他の カラムにユニーク・インデックスあり ) 遅延 直接 遅延 deferred_varcol ユニーク・ノンクラスタード・インデックス deferred_varcol 直接 ユニークでないノンクラスタード・インデックス deferred_varcol 直接 直接 deferred_varcol インデックスのキーが固定長である場合は、ノンクラスタード・インデッ クスのときに限り、この表に示されている更新モードとの違いが唯一生じ ます。ユニークでないノンクラスタード・インデックスの場合、キーの更 新に対する更新モードは deferred_index になります。ユニークなノンクラ スタード・インデックスの場合は、キーの更新に対する更新モードは直接 モードになります。 varchar または varbinary の実際の長さが最大長に近い場合は、代わりに char または binary を使います。可変長カラムが 1 つあるごとにロー・オー バヘッドが加わり、遅延更新が実行される可能性が高くなります。 max_rows_per_page を使ってページあたりに格納可能なロー数を減らす と、直接更新が実行される可能性が増えます。これは、可変長カラムの長 さを増やす更新も同じページに収まり続けるためです。 max_rows_per_page の使用方法については、 『パフォーマンス&チューニ ング・ガイド:基本』の「全ページロック・テーブルでの max_rows_per_page の使用」(199 ページ ) を参照してください。 更新をチューニングする場合の sp_sysmon の使用 showplan を使用して、更新が遅延更新または直接更新のどちらであるか を調べることができます。しかし、showplan では、遅延更新または直接 更新の種類について、詳しい情報は得られません。sp_sysmon、または Adaptive Server Monitor は、サンプル間隔中の更新の種類について、詳細 な統計情報を提供します。 更新をチューニングするときに sp_sysmon を実行し、遅延更新、ロック、 I/O の数が減少したことを確認してください。 詳細については、 『パフォーマンス&チューニング・ガイド:モニタリン グと分析』マニュアルの「トランザクションの詳細」(54 ページ ) を参照 してください。 100 Adaptive Server Enterprise 第 6 章 ジョインとサブクエリのアクセス・ メソッドとコスト計算 この章では、1 つのクエリで複数のテーブルが使用される場合に、Adaptive Server がテーブル内のローにアクセスする方法と、オプティマイザがアク セスをコスト計算する方法を説明します。 トピック名 ジョインのコスト計算と最適化 ページ 101 ネストループ・ジョイン 107 ソートマージ・ジョインのアクセス・メソッドとコスト計算 111 マージ・ジョインを有効または無効にする 124 再フォーマット方式 125 サブクエリの最適化 126 ジョイン内の or 句と union 136 複数テーブルのクエリのコストを決定するには、Adaptive Server は「第 5 章 1 つのテーブルに対するアクセス・メソッドとクエリ・コスト計算」で 説明した式の大半と同じ式を使用します。 ジョインのコスト計算と最適化 ジョインは、2 つ以上のテーブルから情報を引き出します。2 つのテーブ ル間のジョインでは、1 つのテーブルが外部テーブルとして扱われ、もう 1 つのテーブルが内部テーブルになります。Adaptive Server は、外部テー ブルを対象にクエリ条件を満たす外部テーブルのローを探します。条件を 満たす外部テーブルのローが見つかるたびに、Adaptive Server は内部テー ブル内で、ジョイン・カラムが一致する各ローを調べます。 クエリのジョイン・カラムを最適化することは非常に重要です。リレー ショナル・データベースはジョインを多用します。複数のテーブルを対象 にジョインを実行するクエリは特に重要です。詳細については、以降の項 で説明します。 showplan の出力では、“FROM TABLE” メッセージの順序によって、Adaptive Server がジョイン・テーブルを選択する順序が示されます。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 101 ジョインのコスト計算と最適化 3 つのテーブルをジョインする例については、『パフォーマンス&チュー ニング・ガイド:モニタリングと分析』マニュアルの「FROM TABLE メッセージ」(69 ページ ) を参照してください。サブクエリの一部もジョ インに変換されます。 詳細については、 「in、any、exists サブクエリのフラット化」(126 ページ ) を参照してください。 処理 デフォルトでは、Adaptive Server はネストループ・ジョインを使用し、マー ジ・ジョイン機能がサーバワイドまたはセッション・レベルで有効である 場合は、マージ・ジョインも検討します。 マージ・ジョインが有効である場合、Adaptive Server はネストループ・ ジョインとマージ・ジョインのどちらかを使用して 2 つ以上のテーブルが 関係するクエリを処理できます。各ジョインについて、オプティマイザは 両方の方法のコストを計算します。3 つ以上のテーブルが関係するクエリ については、オプティマイザはマージ・ジョインとネストループ・ジョイ ンのクエリ・コストを調べ、最もコストが低いマージ・ジョインとネスト ループ・ジョインの組み合わせを選択します。 インデックス密度とジョイン オプティマイザは、ジョイン実行時に「総密度」という統計値を使用して、 特定の値に一致する、ジョインされたテーブル内のロー数を見積もります。 詳細については、 「密度値とジョイン」(23 ページ ) を参照してください。 クエリ・オプティマイザは、総密度を使って、ジョインの内部テーブルを スキャンするたびに返されるロー数を見積もります。たとえば、オプティ マイザが 250,000 ローのテーブルがあるネストループ・ジョインを検討し、 そのテーブルの密度が .0001 である場合、 外部テーブルで条件を満たすロー 1 つにつき、平均で内部テーブルの 25 ローが一致すると見積もります。 optdiag は、統計値を作成済みの各カラムについて、総密度をレポートし ます。dbcc traceon(302) 出力では、ジョインで使用される総密度も参照 できます。 102 Adaptive Server Enterprise 第6章 ジョインとサブクエリのアクセス・メソッドとコスト計算 複数カラムの密度 Adaptive Server は、複合インデックス内にあるカラムの各プレフィクス・ サブセットの総密度を管理します。複合インデックスの複数の先行カラム 上で 2 つのテーブルがジョインされると、オプティマイザはインデックス に適した密度を使用して、そのインデックスを使用するジョインのコスト を見積もります。ロー数が 10,000 のテーブルで 7 つのカラムにインデッ クスがある場合は、7 つのカラム・キー全体の密度が 1/10,000 であっても、 第 1 カラムの密度はわずか 1/2 で、5,000 ローが返されることを意味する ことがあります。 データ型の不一致とジョイン インデックスが設定されているテーブルに対するジョインを最適化するう えでよく起こる問題の 1 つが、ジョイン・カラムのデータ型の間に互換性 がないことです。これが発生した場合、データ型の一方はもう一方に変換 される必要があり、 インデックスはジョインの一方にしか使用できません。 詳細については、 「データ型の不一致とクエリの最適化」(24 ページ ) を参 照してください。 ジョイン順序 4 つ以下のテーブルをジョインする場合、Adaptive Server は、それらのテー ブルについて考えられるすべてのジョイン順序を検討します。ただし、 Adaptive Server のオプティマイザは反復的な性質を持っているため、5 つ 以上のテーブルのクエリでは、一度に 2 ~ 4 つのテーブルを組み合わせて、 ジョイン順序の組み合わせを調べます。このグループ化がジョイン順のコ スト計算時に使用されるのは、テーブルが追加されるごとに、考えられる ジョイン順序の数が増え、計算時間が長くかかるためです。オプティマイ ザがジョイン順序の決定に使う方法では、ほとんどのクエリで非常に良好 な結果が得られるうえ、あらゆる組み合わせについてすべての順列を調べ るよりも、はるかに少ない CPU 時間しか必要としません。 ジョイン内のテーブル数が 25 を超えると、Adaptive Server は一度に対象と するテーブル数を自動的に減らします。表 6-1 はデフォルト値を示します。 表 6-1: ジョイン時に一度に対象となるテーブル ジョインされるテーブル 4 – 25 一度に対象となるテーブル 4 26 – 37 3 38 – 50 2 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 103 ジョインのコスト計算と最適化 オプティマイザは、まず最初の 2 ~ 4 つのテーブルを対象として、これら のテーブルに最適なジョイン順を決定します。そして、調べたテーブルを 含む最適なプランの外部テーブルを覚えておき、テーブルの組み合わせか らそのテーブルを削除します。次に、残りのテーブルからテーブルの最適 な組み合わせを最適化します。上記の処理を続行し、2 ~ 4 つのテーブル が残るだけになった時点でそれらのテーブルを最適化します。 たとえば、select 文に次の from 句が指定されているとします。 from T1, T2, T3, T4, T5, T6 オプティマイザは、上の 6 つのテーブルから取り出した 4 つのテーブル について、可能な組み合わせすべてを検討します。6 つのテーブルすべて から、次の 15 通りの組み合わせを取り出せます。 T1, T1, T1, T1, T1, T1, T1, T1, T1, T1, T2, T2, T2, T2, T3, T2, T2, T2, T2, T2, T2, T3, T3, T3, T4, T3, T3, T3, T4, T4, T3, T3, T3, T4, T4, T5, T4, T4, T5, T5, T4, T4, T5, T5, T5, T4 T5 T6 T5 T6 T6 T5 T6 T6 T6 T5 T6 T6 T6 T6 組み合わせごとに、オプティマイザはすべてのジョイン順序 ( 順列 ) を検 討します。4 つ 1 組になったテーブルの集まりごとに、考えられるジョイ ン順は 24 存在します。つまり、順列の合計は 360 (24 * 15) になります。 たとえば、T2、T3、T5、T6 テーブルの組み合わせでは、オプティマイ ザは、考えられるこれらの 24 の順序 ( 次に示します ) を検討します。 T2, T2, T2, T2, T2, T2, T3, T3, T3, T3, T3, T3, T5, T5, T5, 104 T3, T3, T5, T5, T6, T6, T2, T2, T5, T5, T6, T6, T2, T2, T3, T5, T6, T3, T6, T3, T5, T5, T6, T2, T6, T2, T5, T3, T6, T2, T6 T5 T6 T3 T5 T3 T6 T5 T6 T2 T5 T2 T6 T3 T6 Adaptive Server Enterprise 第6章 T5, T5, T5, T6, T6, T6, T6, T6, T6, T3, T6, T6, T2, T2, T3, T3, T5, T5, T6, T2, T3, T3, T5, T2, T5, T2, T3, ジョインとサブクエリのアクセス・メソッドとコスト計算 T2 T3 T2 T5 T3 T5 T2 T3 T2 ここで、最適ジョイン順が次の順序だとします。 T5, T3, T6, T2 この時点で、T5 がこのクエリの最外部テーブルに指定されます。 次のステップでは、外から 2 番めのテーブルを選びます。オプティマイ ザは、ジョイン順の残りを選ぶときに T5 を検討対象から除外します。つ まり、オプティマイザは T1、T2、T3、T4、T6 の間で残りのジョイン順 序を決定しなければなりません。これらの 5 つのテーブルから 4 つのテー ブルを選んでできるすべての組み合わせを検討します。具体的には次の 組み合わせがあります。 T1, T1, T1, T1, T2, T2, T2, T2, T3, T3, T3, T3, T4, T4, T4, T4 T6 T6 T6 T6 オプティマイザは、T5 がジョインの最外部テーブルであることを覚え ておき、上の組み合わせ 1 つずつに対してすべてのジョイン順を検討し ます。T5 以外のテーブルをジョインするのに最適な順序が、次のとお りであるとします。 T3, T6, T2, T4 オプティマイザは、T3 を、クエリ全体のジョイン順序の中で T5 の次の テーブルとして選びます。T3 は、残りのジョイン順を選ぶときに検討対 象から除外されます。 残りのテーブルは次のとおりです。 T1, T2, T4, T6 残りのテーブルが 4 つになったので、オプティマイザは残りのテーブルに 対してすべてのジョイン順を検討します。次のジョイン順が最適であると します。 T6, T2, T4, T1 つまり、クエリ全体のジョイン順は次のとおりです。 T5, T3, T6, T2, T4, T1 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 105 ジョインのコスト計算と最適化 外部ジョインとジョイン順序 外部ジョインは、可能なジョイン順の組み合わせを制限します。外部ジョ インの内部メンバが外部メンバと比較される場合、外部メンバのジョイン 順は内部メンバより先である必要があります。外部ジョインで検討対象と なるジョイン順序は、この条件を満たすものだけです。たとえば、次の 2 つのクエリは、1 番めのクエリが ANSI SQL 構文を、2 番めのクエリが Transact-SQL 構文を使用して外部ジョインを実行します。 select T1.c1, T2.c1, T3.c2, T4.c2 from T4 inner join T1 on T1.c1 = T4.c1 left outer join T2 on T1.c1 = T2.c1 left outer join T3 on T2.c2 = T3.c2 select T1.c1, T2.c1, T3.c2, T4.c2 from T1 , T2, T3, T4 where T1.c1 *= T2.c1 and T2.c2 *= T3.c2 and T1.c1 = T4.c1 検討されるジョイン順は、T1 を T2 の外側に、T2 を T3 の外側に置くもの だけです。オプティマイザの検討対象となるジョイン順は次のとおりです。 T1, T1, T1, T4, 106 T2, T2, T4, T1, T3, T4, T2, T2, T4 T3 T3 T3 Adaptive Server Enterprise 第6章 ジョインとサブクエリのアクセス・メソッドとコスト計算 ネストループ・ジョイン ジョイン・カラム上でテーブルにインデックスが設定されている場合は、 ネストループ・ジョインを行うと効率的なアクセスができます。ネスト ループ・ジョインの結果集合を作成する処理は、テーブルをネストし、外 部テーブルの条件を満たすローごとに内部テーブルのスキャンを繰り返 し実行することです。図 6-1 は、その過程を示しています。 図 6-1: ネストループ・ジョイン時のテーブルのネスト TableA 内の条件を満たすローに対し 内部 TableB のスキャン TableB 内の条件を満たすローに対し 最も内側の TableC のスキャン 図 6-1 では、ジョイン対象となるテーブルへのアクセスが次のようにネス トされます。 • TableA は 1 回アクセスされます。テーブルに有効なインデックスが ない場合、テーブル・スキャンが実行されます。I/O コストを削減で きるようなインデックスがある場合は、そのインデックスがローの位 置付けに使用されます。 • TableB は、TableA 内の条件を満たすローごとに 1 回ずつアクセスさ れます。つまり、TableA の 15 ローがクエリの条件に一致する場合、 TableB は 15 回アクセスされます。TableB のジョイン・カラムに有効 なインデックスがある場合、各スキャン用のデータ・ページの読み込 みに 3 回の I/O が必要であり、それに加えて各データ・ページ用に 1 回の I/O が必要です。TableB にアクセスするコストは 60 回の論理 I/O となります。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 107 ネストループ・ジョイン • TableC は、TableB がアクセスされるたびに、TableB 内の条件を満た すローごとに 1 回アクセスされます。TableB の 10 ローが TableA の 各ローに一致する場合、TableC は 150 回スキャンされます。TableC へのアクセスのたびにデータ・ローの位置付けに 3 回の I/O が必要で ある場合、TableC へのアクセスのコストは 450 回の論理 I/O です。 TableC のサイズが小さいか、有効なインデックスが設定されている場合、 I/O の回数は妥当な低い値になります。TableC のサイズが大きくて、ジョ イン・カラムに有効なインデックスが設定されていない場合、オプティマ イザはソートマージ・ジョイン、または再フォーマット方式の使用を選択 して、過剰な I/O の実行を回避する場合があります。 コスト計算式 2 つのテーブルがあるネストループ・ジョインでは、コストの見積もりの 式は次のとおりです。 ジョインのコスト = A のアクセスにかかるコスト + A の条件を満たすローの数 * 条件を満たす各ローに対してスキャンする B のページ数 テーブルを追加した場合のネストループ・ジョインのコストは、次のとお りです。 + + + 外部テーブルのアクセスにかかるコスト ( 外部テーブルの条件を満たすローの数 ) * ( 内部テーブルのアクセスにかかるコスト ) ... ( 最も内部よりも 1 つ外側にあるテーブルの条件を満たすローの数 ) * ( 最も内部のテー ブルのアクセスにかかるコスト ) 内部テーブルと外部テーブルの決定方法 外部テーブルとは、一般的には次のいずれか、または両方があてはまる テーブルです。 • 条件を満たすローの数が最小である。 • ローの位置付けに必要な読み込み回数が最大である。 内部テーブルとは、一般的には次のいずれか、または両方があてはまる テーブルです。 108 • 条件を満たすローの数が最大である。 • ローの位置付けに必要な読み込み回数が最小である。 Adaptive Server Enterprise 第6章 ジョインとサブクエリのアクセス・メソッドとコスト計算 たとえば、サイズが大きくインデックスのないテーブルを、ジョイン・ キーにインデックスのあるサイズの小さいテーブルとジョインする場合、 オプティマイザは次のように選択します。 • サイズの大きいテーブルを、スキャンを 1 回だけにするため、外部テー ブルとして選択する。 • 内部テーブルにアクセスするたびにわずか数回の読み込みだけで ローが見つかるように、インデックスが設定されているテーブルを内 部テーブルとして選択する。 セルフジョイン このジョインは、テーブルのカラム内の値を比較するために使用されます。 この操作ではこのテーブル自身のジョインも行われるので、テーブルには テンポラリ名を 2 つ与えるか、相関名を与えます。これらの名前は、クエ リ後部でカラム名を修飾するのに使用します。 更新時に直接モードが使用できる条件に対して最適化を指定します。適切 な更新プロジェクトを使用すると、セルフジョインが含まれる更新は常に 遅延モードで行われます。次に例を示します。 update t1 set t1.c1 = t1.c1 + 1 FROM t1 a, t1 b where a.c1 = b.c2 and delete t1 FROM t1 a, t1 b WHERE a.c1 = b.c2 これは常に遅延モードで処理されます。このルーチンでは、次の規則が チェックされます。直接モードで更新を実行する場合の必要条件として、 これらの規則を遵守する必要があります。 1 セルフジョインは存在しないが、クエリが FROM リスト内の複数の テーブルを参照する場合、更新は直接モードで実行される可能性が ある。 2 更新クエリについては、クエリが FROM リスト内の複数のテーブル を参照する場合に、読み込みカーソル・テーブルがジョイン順で最初 のテーブルであるかどうかを次の手順でチェックする。 • 読み込みカーソルがジョイン順で最初のテーブルである場合は、 すべての下流のテーブルが存在ジョインでスキャンされるため、 直接モードで更新を実行できる。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 109 セルフジョイン • 読み込みカーソルがジョイン順の最初のテーブルでない場合は、 ジョイン順でその前に存在するすべてのテーブルがフラット化さ れたサブクエリのテーブルであるかどうかをチェックする。 フラッ ト化されたサブクエリに対して、オプティマイザは、1 つのローだ けが最終ジョイン・プランに取り込まれるようにするために、さま ざまな方法 ( ユニーク・ジョイン、タプルのフィルタ、ユニークな 再フォーマット ) のいずれか 1 つを適用している。 • 読み込みカーソル・テーブルの前にあるすべてのテーブルが外 部クエリ・ブロックに属しており、1 つのローを返すことが判明 している場合は、読み込みカーソル・テーブルのローはそれぞ れ 1 回だけ条件を満たす。 これによって、ターゲット・テーブルのローは 1 回だけ条件を満 たすことになります。 3 削除クエリの場合は、ターゲット・テーブルがジョイン順で最初の テーブルである必要はない。これは、ターゲット・テーブルのローが ジョイン条件に従って複数回条件を満たさなければならないことに なっていても、直接削除を行うことで、 「最初に」条件を満たしたロー が削除され、後続の条件は「見つからなかったロー」の条件になるた めである。 次のクエリは、これらの規則が適用されるときに、直接更新モードで実行 できる可能性があります。 例 1:この例では、フラット化されないサブクエリがメイン ROOT ノード で 3 のテーブル・カウントを生成します。 update t1 set t1.c1 = t1.c1 + 1 where t1.c2 NOT IN (select t2.c2 from t2) 例 2:これは、フラット化されたサブクエリの例です。 update t1 set t1.c1 = t1.c1 + 1 FROM t1 where t1.c2 IN (select t2.c2 from t2) どちらの場合でもメイン ROOT ノードのテーブル・カウントは 3 を示し ていますが、これらのクエリは直接更新モードで実行できる可能性があり ます。 例 3: update t1 set t1.c1 = t1.c1 + 1 FROM t1, t2 where t1.c1 = t2.c1 出力: Data is: 110 t1 --1 1 t2 --1 2 Adaptive Server Enterprise 第6章 ジョインとサブクエリのアクセス・メソッドとコスト計算 ジョイン順が t2 -> t1 であり、直接モードで更新を行う場合、t1 のローは 次のようになります。 [(1), (1)] -> [(2), (2)] ソートマージ・ジョインのアクセス・メソッドとコスト計算 マージ・ジョインは、次の 4 つの方法で実行できます。 • フルマージ・ジョイン - ジョインされた 2 つのテーブルには、ジョ イン・カラム上に有効なインデックスが設定される。テーブルのソー トは必要ないが、インデックスを使用してマージできる。 • 左マージ・ジョイン - 内部テーブルをジョイン順にソートし、次に 左の外部テーブルとマージする。 • 右マージ・ジョイン - 外部テーブルをジョイン順にソートし、次に 右の内部テーブルとマージする。 • ソートマージ・ジョイン - 両方のテーブルをソートしてから、マー ジする。 マージ・ジョインは常に、ユーザ・テーブルまたはマージ・ジョイン用 に作成されたワークテーブルのいずれかのストアド・テーブルに対して 実行されます。ワークテーブルがマージ・ジョインに必要な場合、ジョ イン・キー上で順にソートされ、次にマージ手順が実行されます。ソー トが実行されるマージ・ジョインのコスト計算には、ワークテーブルの 作成とソートの I/O コストの見積もりが含まれます。フルマージ・ジョイ ンについては、含まれるコストはテーブルのスキャンだけです。 図 6-2 は、マージ・ジョインのタイプの図です。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 111 ソートマージ・ジョインのアクセス・メソッドとコスト計算 図 6-2: マージ・ジョインのタイプ フルマージ・ジョイン (FMJ) ステップ 1 FMJ T1 左マージ・ジョイン (LMJ) ステップ 1 T2 ステップ 2 Worktable1 LMJ ソート T2 右マージ・ジョイン (RMJ) ステップ 1 T1 Worktable1 ステップ 2 Worktable1 RMJ ソート T1 ソートマージ・ジョイン ステップ 1 (SMJ) Worktable1 Worktable1 ステップ 2 T2 ステップ 3 Worktable2 SMJ ソート T1 112 T2 Worktable1 ソート Worktable2 Adaptive Server Enterprise 第6章 ジョインとサブクエリのアクセス・メソッドとコスト計算 フルマージ・ジョインの実行方法 Table1 と Table2 の両方のジョイン・キーのインデックスが設定されてい る場合、次のクエリはフルマージ・ジョインを使用できます。 select * from Table1, Table2 where Table1.c1 = Table2.c2 and Table1.c1 between 100 and 120 両方のテーブルがクラスタード・インデックスを持つ全ページロック・ テーブルであり、Table1 が外部テーブルとして選択されると、インデッ クスが使用されて値に 100 を持つローのデータ・ページに探索開始位置が 位置付けられます。Table2 でも同様にインデックスが使用されて、ジョ イン・カラムの値に 100 を持つ Table2 で最初のローにスキャン開始位置 が位置付けられます。この時点から、両方のテーブルのデータ・ページが スキャンされつつ、ローが返されていきます。 図 6-3: クラスタード・インデックスのある 2 つのテーブル上の逐次マージ・ スキャン Table1 Page 1037 98 99 100 101 102 Table2 Page 3423 93 100 102 105 113 122 Page 1040 105 109 113 117 122 マージ・ジョインは、ノンクラスタード・インデックスを使用しても実 行できます。インデックスは、インデックスのリーフ・ページ上で最初 に一致する値にスキャンを位置付けするのに使用されます。一致する ローごとに、データ・ページへのアクセス用にインデックス・ポインタ が使用されます。図 6-4 は、内部テーブルでノンクラスタード・インデッ クスを使用するフルマージ・スキャンを示します。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 113 ソートマージ・ジョインのアクセス・メソッドとコスト計算 図 6-4: 内部テーブルでノンクラスタード・インデックスを使用する フルマージ・スキャン Table1 Table2 Page 1037 98 99 100 101 102 Page 1040 105 109 113 117 122 Page 1903 57 623 100 93 100 102 105 113 122 Page 3423 1955,1 1903,3 1752,2 1907,1 1752,3 2409,4 Page 1907 105 842 113 472 Page 1752 102 823 113 29 データ・ページ リーフ・ページ データ・ページ 右マージ・ジョインと左マージ・ジョインの実行方法 右マージ・ジョインと左マージ・ジョインは常に、ユーザ・テーブルと、 マージ・ジョイン用に作成されたワークテーブルとの間で実行されます。 これは次の 2 つのステップからなります。 114 1 テーブルまたはテーブルの組み合わせがスキャンされ、結果がワーク テーブルに挿入されます。 2 ワークテーブルがソートされ、次にインデックスを使用してジョイン に存在する他のテーブルとマージされます。 Adaptive Server Enterprise 第6章 ジョインとサブクエリのアクセス・メソッドとコスト計算 ソートマージ・ジョインの実行方法 ソートマージ・ジョインへの入力は両方ともソートされたワークテーブル であるため、ソートマージ・ジョインは次の 3 つのステップからなります。 1 テーブルまたはテーブルの組み合わせがスキャンされ、その結果が 1 つのワークテーブルに挿入されます。このテーブルがマージの外部 テーブルになります。 2 別のテーブルがスキャンされ、結果が別のワークテーブルに挿入され ます。これはマージの内部テーブルになります。 3 各ワークテーブルがソートされ、次に 2 つのソートされた結果がマー ジされます。 混合ジョインの例 次のクエリは、マージとネストループ・ジョインを混合して実行します。 select pub_name, au_lname, price from titles t, authors a, titleauthor ta, publishers p where t.title_id = ta.title_id and a.au_id = ta.au_id and p.pub_id = t.pub_id and type = ’business’ and price < $25 Adaptive Server は、このクエリを 3 つのステップで実行します。 • ステップ 1 では 3 つのワーカー・プロセスを使用します。外部テーブ ルとして titles をスキャンし、titleauthor とのフルマージ・ジョインを 実行し、次に authors とのネストループ・ジョインを実行します。フ ルマージ・ジョインにはソートの必要はありません。titles には、title_id にクラスタード・インデックスがあります。titleauthor、ta_ix 上のイ ンデックスは、title_id と au_id を含むため、インデックスはクエリを カバーします。結果は、ステップ 3 で実行されるソートマージ・ジョ インで使用するため、Worktable1 に格納されます。 • ステップ 2 では publishers テーブルをスキャンし、必要なカラム (pub_name と pub_id) を Worktable2 に保存します。 • ステップ 3 は次のとおりです。 • Worktable1 が、 pub_id 上でジョイン・カラム順にソートされます。 • Worktable2 が pub_id 上で順にソートされます。 • ソートされた結果がマージされます。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 115 ソートマージ・ジョインのアクセス・メソッドとコスト計算 図 6-5 は、この 3 つのステップを示します。 図 6-5: マージ・ジョイン処理のステップ Worktable1 ステップ 1 authors FMJ titleauthor ステップ 3 SMJ ソート Worktable1 116 Worktable2 publishers NLJ titles ステップ 2 ソート Worktable2 Adaptive Server Enterprise 第6章 ジョインとサブクエリのアクセス・メソッドとコスト計算 ソートマージ・ジョインに対する showplan メッセージ マージ・ジョインのタイプごとに、showplan メッセージが次のような特 定の組み合わせで表示されます。 • フルマージ・ジョイン - “FROM TABLE Worktable” のメッセージは なく、クエリ内のベース・テーブル用に “inner table” と “outer table” のメッセージのみがある。 • 右マージ・ジョイン - “outer table” が常にワークテーブルである。 • 左マージ・ジョイン - “inner table” が常にワークテーブルである。 • ソートマージ・ジョイン - 両方のテーブルがワークテーブルである。 詳細については、 『パフォーマンス&チューニング・ガイド:モニタリン グと分析』マニュアルの「アクセス・メソッド、キャッシュ、I/O コスト を説明するメッセージ」(86 ページ ) を参照してください。 マージ・ジョインのコスト計算 マージ・ジョインの合計コストは次の点に応じて異なります。 • マージ・ジョインのタイプ • フルマージ・ジョインには、ソートやワークテーブルは必要あり ません。 • 右マージ・ジョインと左マージ・ジョインでは、ジョインの一方 が選択されてワークテーブルに入り、ソートされます。 • ソートマージ・ジョインでは、両方のジョインが選択されてワー クテーブルに入り、各ワークテーブルがソートされます。 • マージのステップ実行中にテーブルのスキャンに使用されるイン デックスのタイプ • 基本となるテーブルのロック・スキーム。多くの場合、全ページ・ ロックの方がデータオンリー・ロックよりもコスト計算モデルの違 いが顕著に出ます。データオンリー・ロック・テーブルへのクラス タード・インデックスを使用したアクセス・コストは、ノンクラス タード・アクセスのコストとあまり変わりません。 • クエリが逐次モードまたは並列モードで実行されるかどうか • 外部テーブルでジョイン・キーの値が重複しているかどうか 一般に、同じテーブルで同じインデックスを使用して、ネストループ・ ジョインとマージ・ジョインのコストを比較する場合、外部テーブルのコ ストは同じです。内部テーブルへのアクセスは、マージ・ジョインの方が 低くなります。これは、一致する値が返されるとスキャンはリーフ・ペー ジ上に置かれたままになり、ルート・ページからインデックスを毎回ス キャンする場合と比べて、論理 I/O コストが少なくてすむからです。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 117 ソートマージ・ジョインのアクセス・メソッドとコスト計算 ユニークな値がある場合のフルマージ・ジョインのコスト計算 フルマージ・ジョインが逐次モードで実行され、テーブルのソートが必要 ない場合、すべてのジョイン値がユニークであるかぎり、T1 と T2 上の マージ・ジョインのコストは、両方のテーブルのスキャンのコストを合計 したものになります。 マージ・ジョインのコスト = T1 のスキャンにかかるコスト + T2 のスキャンにかかるコスト 次のような場合に、ネストループ・ジョインに比較してマージ・ジョイン のコストが削減されます。 • ネストループ・ジョインでは、ジョインの内部テーブルへのアクセ スは、条件を満たす外部テーブルの各ローのインデックスのルート・ ページから開始する。 • フルマージ・ジョインでは、インデックスの上位レベルが最初のアク セスに使用され、次のようにスキャンの位置付けを行う。 • データオンリーロック・テーブル上のノンクラスタード・イン デックスとクラスタード・インデックスの場合、インデックスの リーフ・ページ上 • 全ページロック・テーブル上にクラスタード・インデックスがあ る場合、データ・ページ上 上位レベルのインデックスは、一致する外部ローごとに読み込む必要 がありません。 例:クラスタード・インデックスのある全ページロック・テーブル クラスタード・インデックスを使用してスキャンされる全ページロック・ テーブルでは、インデックスの探索引数は、各テーブルの最初の一致する ローに、スキャンを位置付けるのに使われます。クエリの合計コストは、各 テーブルのデータ・ページ上で前方スキャンをするコストです。たとえば、 t1(c1) と t2(c1) 上のクラスタード・インデックスを使用すると、2 つの全 ページロック・テーブルに対するクエリはフルマージ・ジョインを使用で きます。 select t1.c2, t2.c2 from t1, t2 where t1.c1 = t2.c1 and t1.c1 >= 1000 and t1.c1 < 1100 118 Adaptive Server Enterprise 第6章 ジョインとサブクエリのアクセス・メソッドとコスト計算 t1 に 100 ロー、t2 に 100 ローの条件を満たすローがあり、これらのテーブ ルそれぞれに、ページあたり 10 ロー、高さ 3 のインデックスがある場合、 コストは次のとおりです。 • t1 の最初に一致するローにスキャンを位置付けるための 3 インデッ クス・ページ • t1 の 10 ページのスキャン • t2 の最初に一致するローにスキャンを位置付けるための 3 インデッ クス・ページ • t2 の 10 ページのスキャン 重複する値がある場合のフルマージ・ジョインのコスト計算 マージ・ジョインの外部テーブルに重複する値が存在する場合、内部テー ブルは重複する各値のインデックスのルート・ページからアクセスされな くてはなりません。次のクエリは前述の例と同じです。 select t1.c2, t2.c2 from t1, t2 where t1.c1 = t2.c1 and t1.c1 >= 1000 and t1.c1 < 1100 t1 が外部テーブルで、1000 と 1100 の間に 120 ローがあって重複する値が 20 あるというように、t1 のローに重複する値が存在する場合、重複する 値にアクセスがあるたびに、t2 のスキャンがインデックスのルート・ペー ジから再び開始されます。t2 の 1 つのローが t1 の各値に一致する場合、 このクエリの I/O コストは次のとおりです。 • t1 の最初に一致するローに位置付けるための 3 インデックス・ページ • t1 の 12 ページのスキャン • t2 の最初に一致するローに位置付けるための 3 インデックス・ページ と、データ・ページの読み込み用の I/O • 残りのローについては、次のとおりです。 • t1 の値が重複する値である場合、t2 のスキャンがインデックス のルート・ページから再び開始されます。 • t1 の重複しない値すべてについては、スキャンは t2 のリーフ・ レベルの位置にとどまります。外部テーブル内の次の重複する 値によってルート・ページからのスキャンの再開が必要となる までは、ローが返されても内部テーブルのスキャンはリーフ・ ページの位置にとどまります。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 119 ソートマージ・ジョインのアクセス・メソッドとコスト計算 次の式で、マージ・ジョインの内部テーブルのスキャンのコストが計算で きます。 内部テーブルのスキャンにかかるコスト = 重複する値の個数 * ( インデックスの高さ + スキャン・サイズ ) + 重複しない値の個数 * スキャン・サイズ スキャン・サイズ は、外部テーブルにある値ごとに内部テーブルから読 み込む必要があるページ数です。複数の内部ローが一致するテーブルの 場合、スキャン・サイズは外部ローごとに読み込む必要がある平均ペー ジ数です。 ソートのコスト計算 ソートマージ・ジョイン時のソートのコストは、次の点に応じて異なり ます。 • ワークテーブルのサイズ。選択されたカラム数とロー数に応じて異な ります。 • number of sort buffers 設定パラメータの設定。これは、使用できる キャッシュのページ数を決定します。 上記の変数は、ワークテーブルのソートに必要なマージ実行数に影響し ます。 ソートマージ・ジョインのワークテーブルのサイズ ソートが必要なマージ・ジョイン用ワークテーブルの作成時には、結果 セットと、クエリ実行後のジョインに必要なカラムだけが選択されて ワークテーブルに入ります。 titles テーブルのワークテーブルが図 6-5 (116 ページ ) に示すジョイン用に作成される場合は、次のようになります。 • Worktable1 には、price、authors.state、pub_id が含まれます。price と authors.state は結果セットの一部であり、pub_id は後続のジョイ ンに必要だからです。 • Worktable2 には、publishers.state カラムと pub_id が含まれます。 publishers.state カラムは結果セットの一部であり、pub_id はマージ のステップに必要だからです。 type カラムは、titles のローの選択時に探索引数として使用されます。た だし、その後はそのクエリまたは結果セットでは使用されないため、ワー クテーブルには含まれません。 120 Adaptive Server Enterprise 第6章 ジョインとサブクエリのアクセス・メソッドとコスト計算 マージ・ジョインに対して実行された各ソートは、ソートの中間ステップ で number of sort buffers を使用できます。ワークテーブルのソート・バッ ファは、tempdb で使用されるキャッシュから割り付けられます。ソート されるページ数が number of sort buffers より少ない場合、ソート用に確 保されるバッファ数がワークテーブル内のページ数になります。 マージ・ジョインが使用できない場合 マージ・ジョインは、次のものについては使用できません。 • ジョイン・カラム上で <、>、<=、>=、!= を使用するジョイン • 外部ジョイン、つまり *= または =*、left join、right join を使用するクエリ • select リストまたは where 句内の text または image カラム、または Java オブジェクト・カラムを含むクエリ • 並列クエリ内の、フラット化または実体化されていないサブクエリ • 次のような複数テーブルの更新と削除 update R set a = 5 from R, S, T where ... • insert、update、delete コマンドに対して参照整合性チェックを実行 するジョインの場合。これらのジョインは、カラム値の存在をチェッ クするために内部的に生成されます。通常、参照テーブルから 1 つ の値を返すジョインがこれらのジョインに関係します。ほとんどの 場合、これらのジョインはインデックスによってサポートされます。 制約チェックにマージ・ジョインを使用しても効果はありません。 • ワークテーブルのローのバイト数がページ・サイズの制限値 (ユーザ・ データの 1960 バイト)またはカラム数上の制限値 (1024) を超える場合。 select リストとジョインに必要なジョイン・カラムが、これらの制限値 のいずれかを超えるワークテーブルを作成すると、オプティマイザはク エリ・プランのその時点でのマージ・ジョインの実行を検討対象からは ずします。 • マージ・ジョインのためにワークテーブルを使用すると、1 つのクエ リに許容されるワークテーブルの最大数 (14) 以上のワークテーブル が必要になる場合。 マージ・ジョインには、ジョイン順の中で使用できる場所に制約があります。 • マージ・ジョインは、存在ジョインの前にだけ実行できます。一部の distinct クエリは存在ジョインに変わりますが、それらにはマージ・ ジョインは使用されません。 • フルマージ・ジョインと左マージ・ジョインは、ジョイン順の最外部 のテーブルでのみで実行できます。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 121 ソートマージ・ジョインのアクセス・メソッドとコスト計算 ワーカー・プロセスの使用 並列処理が有効である場合、マージ・ジョインは複数のワーカー・プロセ スを使用して、次のことを実行できます。 • ワークテーブルに入れるローを選択するスキャン • ワークテーブルのソート・オペレーション • マージ・ジョインと、その後のステップで実行されるジョイン 詳細については、 「並列レンジベース・スキャン」(180 ページ ) を参照し てください。 マージの実行パフォーマンス向上のための推奨事項 ソートマージ・ジョインの実行パフォーマンスの向上には、次のような操 作が役立ちます。 • ワークテーブルのサイズを小さくするには、マージ・ジョインで使 用されるテーブルに必要なカラムだけを選択します。テーブルのす べてのカラムが必要なとき以外は、select * の使用を避けます。これ によって、tempdb への負荷と結果テーブルのソートのコストが減り ます。 • マージ・ジョインのパフォーマンス低下や tempdb での領域の問題が 心配な場合は、このマニュアルの「第 14 章 抽象プランの概要」を参 照してください。お使いのシステム上で、どのクエリでマージ・ジョ インを使用するかを決定する際に役立つ、抽象クエリ・プランについ て説明しています。 • インデックス・カバーリングが実現するようにします。例としては、 次のような形式のジョインを含むクエリがあります。 select t1.c3, t3.c4 from t1, t2, t3 wehre t1.c1 = t2.c1 and t2.c2 = t3.c2 and ... そして、t2 のカラムが select リストになく、ジョイン・カラムだけが select リストに存在するとします。ジョイン・カラム上のインデック スである t2(c1, c2) はクエリをカバーし、マージ・ジョインが t2 の データ・ページへアクセスするのを回避できます。 122 Adaptive Server Enterprise 第6章 • ジョインとサブクエリのアクセス・メソッドとコスト計算 マージ・ジョインは、2 つのテーブルが次のように複数のカラム上で ジョインされる場合、昇順または降順で作成されたインデックスを使 用できます。 A.c1 = B.c1 and A.c2 = B.c2 and A.c3 = B.c3 インデックスに指定されたカラム順は、ジョインのコスト計算とデー タのアクセス時にジョイン述語として使用されるすべてのカラムに 対して、完全に一致するか、完全に逆順である必要があります。2 番 目のカラムやそれ以降のカラムの順序付けに不一致がある場合、一致 するカラムはジョインに使用され、残りのカラムはローが検索された 後の結果を制限するのに使用されます。次の表は、前述のクエリの例 を示しています。 インデックス作成順 A(c1 asc, c2 asc, c3 asc) B(c1 asc, c2 asc, c3 asc) 3 つの句すべて ジョイン述語として使用する句 A(c1 asc, c2 asc, c3 asc) B(c1 desc, c2 desc, c3 desc) 3 つの句すべて A(c1 asc, c2 asc, c3 asc) B(c1 desc, c2 desc, c3 asc) 最初の 2 つのジョイン句は、ジョイン 述語として使用され、3 番めの句は結 果の制限として評価される。 A1(c1 asc, c2 desc, c3 desc) B1(c1 desc, c2 desc, c3 asc) 最初のジョイン句だけがジョイン述語 として使用される。残りの 2 つの句は 結果セットの制限として評価される。 インデックス・キーの順序付けは一般に、order by クエリのソート・ コストをなくすために選択されます。頻繁にジョインするテーブルに 対して互換性のある順序付けを使用すると、ジョイン・コストを減ら すこともできます。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 123 マージ・ジョインを有効または無効にする マージ・ジョインを有効または無効にする サーバ・レベルとセッション・レベルで set sort_merge を使用するか、 サーバ・レベルで設定パラメータ enable sort-merge joins and JTC を使用 して、マージ・ジョインを有効にしたり、無効にしたりできます。この設 定パラメータはジョイン推移閉包も有効または無効にできます。 サーバ・レベル サーバワイドにマージ・ジョインを有効にするには、enable sort-merge joins and JTC を 1 に設定します。デフォルト値は 0 で、マージ・ジョイ ンが考慮されないことを示します。この値が 1 に設定されると、マージ・ ジョインと推移閉包は等価ジョインに対して検討されます。マージ・ジョ インがサーバ・レベルで無効になっている場合、set sort_merge を使用す ると、マージ・ジョインをセッションで有効にできます。 set jtc on を使用すると、ジョイン推移閉包をセッション・レベルで独立 して有効にできます。 詳細については、 「ジョイン推移閉包の有効化と無効化」(52 ページ ) を参 照してください。 設定パラメータは動的であり、サーバを再起動することなくリセットでき ます。 セッション・レベル セッションのマージ・ジョインを有効にするには、次のコマンドを使い ます。 set sort_merge on セッションのマージ・ジョインを無効にするには、次のコマンドを使い ます。 set sort_merge off セッションの設定はサーバワイドの設定に優先します。マージ・ジョイン がサーバワイド・レベルで無効になっている場合でも、セッションまたは ストアド・プロシージャでマージ・ジョインを使用できます。 124 Adaptive Server Enterprise 第6章 ジョインとサブクエリのアクセス・メソッドとコスト計算 再フォーマット方式 テーブルのサイズが大きく、ジョインに有効なインデックスがない場合、 オプティマイザはソートマージ・ジョインを検討しますが、同時にワーク テーブルを作成、ソートして、ネストループ・ジョインを使用することも 検討します。 クラスタード・インデックスのあるワークテーブルを生成してネストルー プ・ジョインを実行する処理は、「再フォーマット」と呼ばれます。 ソートマージ・ジョインと同様に、再フォーマットではテーブルをスキャ ンし、条件を満たすローをワークテーブルにコピーします。ただし、マー ジ・ジョインで使用されるソートとマージの代わりに、Adaptive Server は、 ジョイン・カラム上に一時的な内部テーブル用クラスタード・インデック スを作成します。クラスタード・インデックスを作成して使用する方が、 ソートマージ・ジョインよりコストが低くなる場合もあります。 再フォーマット方式のステップは次のとおりです。 • ワークテーブルを作成する。 • 条件を満たすローから必要なカラムを挿入する。 • ワークテーブルのジョイン・カラム上にクラスタード・インデックス を作成する。 • ジョイン・カラムのクラスタード・インデックスを使って各テーブル から条件を満たすローを検索する。 再フォーマット方式の主なコストは、ワークテーブルを作成し、ワーク テーブルにクラスタード・インデックスを構築するために必要な時間と I/O です。Adaptive Server は、再フォーマットのコストが、マージ・ジョ インのコストまたはテーブル・スキャンを繰り返し実行するコストよりも 低い場合にだけ、再フォーマット方式を使用します。 showplan のメッセージには、Adaptive Server がいつ再フォーマット方式 を使用しているのかが示されます。また、ワークテーブルを構築するス テップを示す他のメッセージも出力されます。 詳細については、 『パフォーマンス&チューニング・ガイド:モニタリン グと分析』の「再フォーマット・メッセージ」(101 ページ ) を参照してく ださい。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 125 サブクエリの最適化 サブクエリの最適化 サブクエリは、次の特別な最適化を使ってパフォーマンスを向上させます。 • フラット化 - サブクエリをジョインに変換すること • 実体化 - サブクエリ結果をワークテーブル内に保管すること • ショート・サーキット効果 - サブクエリを実行順序の最後に置くこと • サブクエリ結果のキャッシュ - 実行の結果を記録すること これらの方式については、以降の項で説明します。 サブクエリ処理に対応する showplan メッセージの詳細については、『パ フォーマンス&チューニング・ガイド:モニタリングと分析』の「サブク エリに対する showplan メッセージ」(111 ページ ) を参照してください。 in、any、exists サブクエリのフラット化 Adaptive Server は、一部の限定述語サブクエリをフラット化してジョイン できます。限定述語サブクエリは、in、any、または exists に続きます。 サブクエリの条件が TRUE と評価されると、外部クエリの各結果ローは 1 回だけ返されます。 フラット化が実行できるとき • サブクエリのネストのすべてのレベル。次に例を示します。 select au_lname, au_fname from authors where au_id in (select au_id from titleauthor where title_id in (select title_id from titles where type = "popular_comp") ) • 外部クエリの複数のサブクエリ。次に例を示します。 select title, type from titles where title in (select title from titles, titleauthor, authors where titles.title_id = titleauthor.title_id and titleauthor.au_id = authors.au_id and authors.state = "CA") and title in (select title from titles, publishers where titles.pub_id = publishers.pub_id and publishers.state = "CA") 126 Adaptive Server Enterprise 第6章 ジョインとサブクエリのアクセス・メソッドとコスト計算 フラット化の例外 in、any、または exists に続くサブクエリは、次の条件のうち 1 つが真で ある場合はフラット化できません。 • サブクエリが相関サブクエリであり、1 つまたは複数の集合関数を 持つ。 • サブクエリが、select リストまたは update 文の set 句にある。 • サブクエリが or によって外部クエリに接続されている。 • サブクエリが isnull 述語の一部である。 • サブクエリが、case 式の最外部のサブクエリである。 サブクエリがスカラ集合関数を計算する場合、フラット化ではなく実体化 が使用されます。 詳細については、「サブクエリの結果を実体化する」(131 ページ ) を参照 してください。 フラット化メソッド Adaptive Server は、次のいずれかのフラット化メソッドを使用して、ジョ インを使う限定述語サブクエリを解析します。 • 通常のジョイン - サブクエリの一意性が、 サブクエリの結果がユニー クな結果セットになることを意味する場合、サブクエリはフラット化 され、通常のジョインが使用できます。 • 存在ジョイン ( セミジョイン ) - テーブルをスキャンしてすべての一 致する値を返す代わりに、存在ジョインは最初の一致する値を見つけ て処理を停止するときに TRUE を返します。一致する値が見つからな い場合は、FALSE を返します。 • ユニークな再フォーマット - サブクエリの結果セットが選択され てワークテーブルに入り、ソートによって重複が削除され、クラス タード・インデックスがワークテーブル上に構築されます。クラス タード・インデックスは、通常のジョインを実行するのに使用され ます。 • 重複削除ソート最適化 - サブクエリは、結果を選択してワークテー ブルに入れる通常のジョインにフラット化され、次にそのワークテー ブルがソートされて、重複するローが削除されます。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 127 サブクエリの最適化 ジョイン順とフラット化メソッド フラット化メソッドを選ぶ主な要因は、可能なジョイン順のコストに応じ て異なります。たとえば、t1、t2、t3 のジョインでは、次のとおりです。 select * from t1, t2 where t1.c1 = t2.c1 and t2.c2 in (select c3 from t3) 最もコストが低いジョイン順が t1、t2、t3 または t2、t1、t3 の場合、通常 のジョインまたは存在ジョインが使用されます。ただし、外部テーブルと して t3 を使ったジョインを実行する方が低コストである場合、たとえば t3、t1、t2 というような順の場合は、ユニークな再フォーマットまたは重 複削除ソートが使用されます。 フラット化されたジョインには、ネストループ・ジョインまたはマージ・ ジョインを含むことができます。存在ジョインを使用する場合、マージ・ ジョインは存在ジョインの前にのみ実行できます。 通常のジョインとして実行される、フラット化されたサブクエリ 限定述語サブクエリは、サブクエリの結果セットがユニークな値のセット で あ る と き に 通 常 の ジ ョ イ ン と し て 実 行 で き ま す。た と え ば、 publishers.pub_id にユニーク・インデックスが存在する場合、次に示すよ うに、このシングルテーブル・サブクエリが確実にユニークな値のセット を返すことが保証されます。 select title from titles where pub_id in (select pub_id from publishers where state = "TX") publishers.city にユニークでないインデックスがある場合、このクエリは 通常のジョインを使っても実行できます。 select au_lname from authors a where exists (select city from publishers p where p.city = a.city) publishers.city のインデックスがユニークでなくても、そのインデックス がクエリから重複したローをフィルタするのに使用される場合は、ジョイ ンは通常のジョインにフラット化できます。 サブクエリが通常のジョインにフラット化されるとき、showplan 出力は 通常のジョインを示します。フィルタを使用した場合も、showplan の出 力に違いはありません。唯一の診断メッセージは、dbcc traceon(310) の 出力にあり、そのテーブルの method が “NESTED ITERATION with Tuple Filtering” を示します。 128 Adaptive Server Enterprise 第6章 ジョインとサブクエリのアクセス・メソッドとコスト計算 存在ジョインとして実行される、フラット化されたサブクエリ in、any、exists クエリのすべては、条件を満たす値が存在するかどうか を調べて、一致するローが見つかるとすぐに TRUE を返します。 オプティマイザは次のようなサブクエリを存在ジョインに変換します。 select title from titles where title_id in (select title_id from titleauthor) and title like "A Tutorial%" 存在ジョインのクエリは次に示す通常のジョインのように見えますが、返 す結果は異なります。 select title from titles T, titleauthor TA where T.title_id = TA.title_id and title like "A Tutorial%" pubtune データベース内で、title の 2 冊の本が検索文字列に一致します。 それぞれの本は複数の作家による共著であるため、titleauthor には複数の エントリがあります。通常のジョインは 5 つのローを返しますが、このサ ブクエリは最初の一致するローでジョインの実行を終了するため、サブク エリが返すローは title_id ごとに 1 つ、合計で 2 つだけです。 サブクエリがフラット化され存在ジョインが使用されるとき、showplan 出力は、サブクエリのテーブルのジョイン・タイプとして “EXISTS TABLE: nested iteration” というメッセージを入れて、ジョインの出力を表示します。 ユニークな再フォーマットを使用して実行されたフラット化したサブクエリ Adaptive Server は、次の処理によってユニークな再フォーマットを実行し ます。 • ローを選択してワークテーブルに入れ、ワークテーブルをソートし、 重複削除を行ってジョイン・キー上にクラスタード・インデックスを 作成する。 • ワ ー ク テ ー ブ ル を ジ ョ イ ン 順 の 次 の テ ー ブ ル と ジ ョ イ ン す る。 publishers.pub_id 上にユニークでないインデックスがある場合、次の クエリはユニークな再フォーマット方式を使用できます。 select title_id from titles where pub_id in (select pub_id from publishers where state = "TX") パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 129 サブクエリの最適化 このクエリは次のように実行されます。 select pub_id into #publishers from publishers where state = "TX" ソートが重複を削除し、クラスタード・インデックスを作成した後は、次 のとおりです。 select title_id from titles, #publishers where titles.pub_id = #publishers.pub_id ユニークな再フォーマットに対する showplan メッセージは、ステップ 1 で “Worktable created for REFORMATTING”、ステップ 2 ではワークテー ブルに対して “Using Clustered Index” を表示します。 dbcc traceon(310) は、publishers テーブルに対するメソッドについて、 “REFORMATTING with Unique Reformatting” を表示します。 重複削除を使用する、フラット化されたサブクエリ サブクエリ・テーブルをジョイン順で外部テーブルとして配置する方がコ ストが低い場合、クエリは次のように実行されます。 • 外部クエリにフラット化されたサブクエリを使用して通常のジョイ ンを実行し、結果をワークテーブルに配置する。 • ワークテーブルをソートして重複を削除する。 たとえば、salesdetail は title_id に対して重複する値を持ち、次のサブク エリで使用されます。 select title_id, au_id, au_ord from titleauthor ta where title_id in (select ta.title_id from titles t, salesdetail sd where t.title_id = sd.title_id and ta.title_id = t.title_id and type = ’travel’ and qty > 10) このクエリの最適ジョイン順が salesdetail、titles、titleauthor の場合、この 最適ジョイン順が次のように使用されます。 130 • すべてのクエリ結果を選択してワークテーブルに入れる。 • ワークテーブルから重複を削除し、ユーザに結果を返す。 Adaptive Server Enterprise 第6章 ジョインとサブクエリのアクセス・メソッドとコスト計算 ソートを実行する、フラット化されたサブクエリに対する showplan メッ セージ showplan 出力には、通常のジョインとソートを使用するサブクエリにつ いて 2 つのステップが含まれます。最初のステップは、“Worktable1 created for DISTINCT” とフラット化されたジョインを示します。2 番めのステッ プでは、ワークテーブルのソートと、そこからの選択を示します。 dbcc traceon(310) は、限定述語サブクエリからの 1 つまたは複数のテー ブルが最初にジョイン順に配置されるときに、各ジョイン順序についての メッセージを出力します。上記のクエリに使用されたジョイン順を対象と した出力は、次のとおりです。 2 - 0 - 1 This join order created while converting an exists join to a regular join, which can happen for subqueries, referential integrity, and select distinct. 式サブクエリのフラット化 式サブクエリとは、クエリの select リスト内に含まれているサブクエリ、 または、>、>=、<、<=、=、!= に続くサブクエリです。Adaptive Server は、 次の場合に式サブクエリを「等価ジョイン」に変換、すなわちフラット化 します。 • サブクエリがユニークなカラムでジョインする場合、またはユニーク なカラムを返す場合 • カラムにユニークなインデックスがある場合 サブクエリの結果を実体化する サブクエリは、次の 2 つの手順で処理される場合があります。はじめに、 内部クエリの結果が「実体化」、つまりテンポラリ・ワークテーブルまた は内部変数に格納されてから、外部クエリが実行されます。サブクエリは 1 つのステップで実行され、この実行結果は、格納後に次のステップで使 用されます。Adaptive Server は、次のようなサブクエリを実体化します。 • 相関を持たない式サブクエリ • having 句に相関条件がある集合関数を含む限定述語サブクエリ パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 131 サブクエリの最適化 相関を持たない式サブクエリ 相関を持たない式サブクエリは、1 つの値を返します。サブクエリが相関 を持たない場合は、外部クエリで処理されるローに関係なく、このサブク エリが同じ値を返します。このクエリは次のように実行されます。 • サブクエリを実行し、結果を内部変数に格納する。 • 外部クエリ内のサブクエリでその結果の値を置き換える。 次のクエリには、相関を持たない式サブクエリがあります。 select title_id from titles where total_sales = (select max(total_sales) from ts_temp) Adaptive Server はこのクエリを次のように変形させます。 select <internal_variable> = max(total_sales) from ts_temp select title_id from titles where total_sales = <internal_variable> この変形の 2 番目のステップにある検索句は最適化できます。具体的に は、total_sales にインデックスがあれば、クエリはそのインデックス を使えます。実体化された式サブクエリの合計コストは、2 つの別々の クエリのコストを合計したものです。 集合関数を含む限定述語サブクエリ ベクトル ( グループ化 ) 集合関数を含むサブクエリのうちいくつかは、実 体化できます。具体的には、次のサブクエリです。 • 相関を持たない限定述語サブクエリ • having 句においてだけ相関を持つ、限定述語サブクエリ サブクエリの実体化は、次の 2 つのステップで処理されます。 132 • Adaptive Server は、まずサブクエリを実行し、結果をワークテーブル に格納する。 • Adaptive Server は、外部テーブルとワークテーブルを存在ジョインと してジョインする。ワークテーブルの統計値は使用できないため、ほ とんどの場合このジョインは最適化できない。 Adaptive Server Enterprise 第6章 ジョインとサブクエリのアクセス・メソッドとコスト計算 実体化すると、テーブルのローごとに 1 回ずつ集合関数を評価するコスト を削減できます。たとえば、次のクエリを例に考えます。 select title_id from titles where total_sales in (select max(total_sales) from titles group by type) 次のステップが実行されます。 select maxsales = max(total_sales) into #work from titles group by type select title_id from titles, #work where total_sales = maxsales 限定述語サブクエリの実行のコスト合計は、2 つのステップのクエリ・コ ストの合計です。 サブクエリだけでなく where 句も存在する場合、Adaptive Server は、サブ クエリを最後に実行することにより、必要のないサブクエリの実行を省き ます。クエリに指定される句の種類によっては、そのローを返すべきかど うかを次のように低コストの句によって決定し、サブクエリの実行を省け る場合があります。 • いずれかの and 句が FALSE ( 偽 ) であると評価される場合は、 そのロー は返されない。 • いずれかの or 句が TRUE ( 真 ) であると評価される場合は、そのロー は返される。 いずれの場合も、ある 1 つの句の評価によってそのローのステータスが決 定された時点で、他の句をそのローに適用する必要がなくなります。これ によって高コストのサブクエリの実行回数が少なくてすむため、パフォー マンスが向上します。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 133 サブクエリの最適化 and 句に続くサブクエリ and によって句が連結されている場合は、いずれかの句が FALSE である と判断された時点で一連の句の評価が終了します。そのローはスキップさ れます。 次のクエリには、相関したサブクエリと 2 つの and 句があります。 select au_fname, au_lname, title, royaltyper from titles t, authors a, titleauthor ta where t.title_id = ta.title_id and a.au_id = ta.au_id and advance >= (select avg(advance) from titles t2 where t2.type = t.type) and price > $100 and au_ord = 1 Adaptive Server は、実行ステップの順序を並べ変えて、price と au_ord の 条件を評価してから、サブクエリを最後に評価します。ローがいずれかの and 条件を満たさない場合、Adaptive Server は、その他の and 条件を調べ ずにこのローを破棄し、次のローの評価に移ります。このため、ローがす べての and 条件を満たす場合にだけサブクエリが処理されます。クエリ 式に使用できる AND の最大数は 1024 です。 or 句に続くサブクエリ クエリの where 句が or で接続されている場合、どれか 1 つが TRUE であ ると評価されると評価が終了し、ローが返されます。 次のクエリには、サブクエリと 2 つの or 句があります。 select au_fname, au_lname, title from titles t, authors a, titleauthor ta where t.title_id = ta.title_id and a.au_id = ta.au_id and (advance > (select avg(advance) from titles t2 where t.type = t2.type) or title = "Best laid plans" or price > $100) Adaptive Server は、クエリ・プランの条件を並べ替えて、サブクエリを最 後に評価します。ローが or 句の条件を満たすと、Adaptive Server はサブ クエリを処理せずにそのローを返し、次のローの評価に進みます。クエリ 式に使用できる OR の最大数は 1024 です。 134 Adaptive Server Enterprise 第6章 ジョインとサブクエリのアクセス・メソッドとコスト計算 サブクエリ結果のキャッシュ サブクエリをフラット化も実体化もできない場合は、Adaptive Server は メモリ中のキャッシュを使ってサブクエリの判断ごとの結果を格納し ます。クエリ実行時に、Adaptive Server は必要とするサブクエリの結果 がキャッシュ内で何回見つかったかを記録します。これを「キャッシュ・ ヒット率」といいます。キャッシュ・ヒット率が高い場合は、キャッ シュによりサブクエリの実行回数が少なくなっています。キャッシュ・ ヒット率が低い場合は、キャッシュの効果が低く、クエリが実行される につれてキャッシュのサイズが小さくなります。 サブクエリをキャッシュすると、ジョイン・カラムまたは相関カラム内に 重複する値がある場合は、パフォーマンスが向上します。インデックスを 使うクエリ内にある場合のように、値が順序付けられていると、パフォー マンスはさらに高まります。重複する相関値がない場合には、キャッシュ はパフォーマンスを向上させません。 サブクエリ・キャッシュ情報を表示する set statistics subquerycache on コマンドは、サブクエリごとに、キャッ シュ・ヒット数、キャッシュ・ミス数、キャッシュ内に存在するロー数を 表示します。次は、サブクエリ・キャッシュの統計を示す例です。 set statistics subquerycache on select type, title_id from titles where price > all (select price from titles where advance < 15000) Statement: 1 Subquery: 1 cache size: 75 misses: 75 hits: 4925 union の両側にサブクエリがある文の場合は、サブクエリは union の両側 を通して順に番号付けされます。 サブクエリを最適化する サブクエリを持つクエリがフラット化も実体化もされない場合は、次のよ うに最適化されます。 • 外部クエリとフラット化されていないサブクエリが 1 度に 1 つずつ 最適化される。 • いちばん内側のサブクエリ ( 最も深くネストされたサブクエリ ) が最 初に最適化される。 • 各サブクエリの予想バッファ・キャッシュ使用率が外側に伝えられ、 I/O コストと外部クエリの方式を評価しやすくする。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 135 ジョイン内の or 句と union サブクエリを持つ多くのクエリでは、サブクエリは外部テーブルのスキャ ンの 1 つに、2 つのステップから成る処理によって「付着」されます。オ プティマイザは、まずジョイン順の中で、すべての相関カラムが使用可能 となる順序を見つけます。次に、オプティマイザはその順序から検索を開 始して、条件を満たすローの数が最も少ないテーブル・アクセスを見つけ、 このテーブルにサブクエリを付着させます。サブクエリは、この時点でネ スト対象のテーブルの条件を満たすローごとに実行されます。 ジョイン内の or 句と union Adaptive Server は、or で連結されているジョイン句は最適化できず、直積 を実行してクエリを処理します。 注意 Adaptive Server は、or で連結されている探索引数を最適化します。こ の項の説明はジョイン句だけに適用されます。 たとえば、Adaptive Server は次のクエリを処理するときに、あるテーブル のローごとに別のテーブルのすべてのローを参照しなければなりません。 select * from tab1, tab2 where tab1.a = tab2.b or tab1.x = tab2.y union を使用すると、次のように union の両側が別々に最適化されます。 select * from tab1, tab2 where tab1.a = tab2.b union all select * from tab1, tab2 where tab1.x = tab2.y 重複を削除する必要がある場合は union all の代わりに union を使えますが、 union はすべての重複を削除します。書き直されたクエリから同じ重複の セットが収集される可能性はありません。 Adaptive Server は、union でリンクされているジョインでの選択を最適化 できます。or の結果は union の結果と似ていますが、次のように、重複す るローと空のテーブルの処理方法が異なります。 136 • union は ( ソート・ステップで ) 重複するローをすべて削除する。union all は重複を削除しない。or を使った比較可能なクエリは、重複する ローを返すことがある。 • 空のテーブルがあるジョインは、ローを返さない。 Adaptive Server Enterprise 第 7 章 並列クエリ処理 この章では、並列クエリの最適化や並列ソートなど、並列クエリを扱うと きに必要な基本概念と用語について紹介し、並列クエリで使用するコマン ドの概要について説明します。 トピック名 並列処理のメリットを利用できるクエリの種類 ページ 138 Adaptive Server のワーカー・プロセス・モデル 139 並列データ・アクセスのタイプ 143 並列度の制御 148 分割されたテーブルを操作するためのコマンド 155 リソースの配分とパフォーマンス 157 並列クエリ設定のガイドライン 159 システム・レベルの影響 164 並列クエリの結果が異なる場合 165 並列処理の特定のトピックについては、他の章で詳細に説明します。 • Adaptive Server のオプティマイザが並列実行の適性とコストを判断 する方法については、「第 8 章 並列クエリ最適化」を参照。 • 並列ソートのトピックについて理解するには、「第 9 章 並列ソート」 を参照。 • 並列パフォーマンスに対するオブジェクト配置の詳細については、 『パフォーマンス&チューニング・ガイド:基本』の「パフォーマン スのためにテーブルを分割する」(95 ページ ) を参照。 • 並列クエリ処理中のロック動作の詳細については、 『システム管理ガ イド』を参照。 • showplan メッセージの詳細については、『パフォーマンス&チュー ニング・ガイド:モニタリングと分析』マニュアルの「並列クエリ に対する showplan メッセージ」(106 ページ ) を参照。 • Adaptive Server が複数のエンジンを使用する方法について理解す るには、『パフォーマンス&チューニング・ガイド:モニタリング と分析』マニュアルの「第 4 章 エンジンと CPU の使用方法」を参照。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 137 並列処理のメリットを利用できるクエリの種類 並列処理のメリットを利用できるクエリの種類 Adaptive Server が並列クエリを処理するように設定されている場合、オプ ティマイザはそれぞれのクエリを評価して、それが並列実行に適している かどうかを調べます。並列処理に適しており、並列クエリ・プランの方が 逐次プランよりも高速になるとオプティマイザが判断した場合、クエリは コンポーネントに分割され、同時に処理されます。結果は結合してからク ライアントに渡され、そのクエリを 1 つのコンポーネントとして逐次処理 した場合よりも短時間で完了します。 並列クエリ処理を実行すると、次の種類のクエリでパフォーマンスが向上 します。 • 次のように、多くのページをスキャンするが比較的少ないローを返す select 文。 • グループ化された集約またはグループ化されていない集約の場 合の、テーブル・スキャンまたはクラスタード・インデックス・ スキャン。 • 多くのページをスキャンするが、where 句によってローのごく一 部だけを返すテーブル・スキャンまたはクラスタード・インデッ クス・スキャン。 • union、order by、または distinct が含まれる select 文。これらのクエリ の場合、ワークテーブルを並列で移植でき、並列ソートを利用できる。 • マージ・ジョインを使用する select 文。並列処理を使用して、テーブ ルをスキャンし、ソートおよびマージの手順を実行できる。 • オプティマイザによって再フォーマッティング方式が選択された場 合の select 文。これらはワークテーブルを並列で移植でき、並列ソー トを利用できる。 • create index 文、および unique のインデックスと primary key のイン デックスを作成する alter table...add constraint 句。 • dbcc checkstorage コマンド。 ジョイン・クエリは、1 つまたは複数のテーブルで並列処理を使用できます。 ソートされていない大きな結果セットを返すコマンドの場合は、ネット ワークの制約のため、並列処理のメリットを最大限に利用できません。結 果は、ほとんどの場合、マージされてネットワーク経由でクライアント に返されるときよりも、データベースから返されるときの方が高速にな ります。 データを修正するコマンド (insert、update、delete) とカーソルは、並列 で実行できません。また、サブクエリを含むクエリの、ネストされた内部 ブロックは並列で実行できませんが、外部ブロックは並列実行できます。 138 Adaptive Server Enterprise 第7章 並列クエリ処理 巨大なテーブルにアクセスしてサマリ情報を返す DSS (意思決定支援シス テム ) のクエリの場合、並列クエリ処理の最も大きなメリットを利用でき ます。一般的にアクセスするローもジョインするテーブルも比較的少ない OLTP ( オンライン・トランザクション処理 ) クエリの場合、並列クエリの 割り付けと管理でのオーバヘッドのため、並列実行の効率は低下します。 サーバが並列処理用に設定されているとき、20 以上のデータ・ページに アクセスするクエリだけで並列処理が有効になるため、ほとんどの OLTP クエリは逐次処理で動作します。 Adaptive Server のワーカー・プロセス・モデル Adaptive Server では、クエリを並列で実行するときに、1 つの「コーディ ネーティング・プロセス」と複数の「ワーカー・プロセス」を使用します。 8 つのワーカー・プロセスを並列で実行するクエリは、8 つの逐次クエリが テーブルの 1/8 ずつにアクセスしているようなものです。また、このとき、 コーディネーティング・プロセスはこの対話を監視すると同時に、結果を クライアントに返すプロセスを管理しています。各ワーカー・プロセスは、 ユーザ接続とほぼ同じ量のメモリを使用します。各ワーカー・プロセスは、 エンジン上でスケジューリングする必要のあるタスクとして動作し、デー タ・ページをスキャンして、ディスク I/O をキューイングします。また、 サーバ上の他のタスクと同じようにさまざまな方法で動作します。主な違 いは、コーディネーティング・プロセスが、クエリ処理の最終段階で、結 果のマージとクライアントへの戻りを管理し、ワーカー・プロセスを調整 することです。 図 7-1 は、並列クエリ処理で発生するイベントを示します。 1 クライアントがクエリを送信します。 2 クエリを実行するために割り当てられているクライアントのタスクが、 並列クエリ処理のコーディネーティング・プロセスになります。 3 コーディネーティング・プロセスが、ワーカー・プロセスのプールに 4 つのワーカー・プロセスを要求します。コーディネーティング・プ ロセスは、ワーカー・プロセスとセットで「ファミリ」と呼ばれます。 4 ワーカー・プロセスがクエリを並列で実行します。 5 コーディネーティング・プロセスが、すべてのワーカー・プロセスに よって作成された結果を返します。 図 7-1 の右下にある逐次クライアントは、逐次処理されるクエリを送信し ます。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 139 Adaptive Server のワーカー・プロセス・モデル 図 7-1: ワーカー・プロセス・モデル Adaptive Server ワーカー・プロセスのプール 4. ワーカー・プロセス がテーブルを並列に スキャン 2. クエリ ク コ ライ ー プ デ アン ロ ィ ト セ ネ ・ ス ー タ に テ ス 変 ィ ク 化 ン が グ・ 1. 並列クライアント 3. ワーカー・ プロセスの 要求 5. 結果 逐次 クライアント タスク 1 クエリ 結果 クエリの処理中、タスクはシステム・テーブル内でファミリ ID (fid) によ り追跡されます。ファミリのそれぞれのワーカー・プロセスには、同じ ファミリ ID のほか、ユニークなサーバ・プロセス ID (spid) を持ちます。 sp_who や sp_lock などのシステム・プロシージャは、並列クエリの fid と spid を表示するため、これを使ってファミリのすべてのプロセスの動作を 監視できます。 140 Adaptive Server Enterprise 第7章 並列クエリ処理 並列クエリの実行 図 7-2 は、逐次処理で動作する同じクエリと比較して、並列クエリ処理で どのように応答時間が短縮されるかを示します。並列実行では、3 つの ワーカー・プロセスがデータ・ページをスキャンします。それぞれのワー カー・プロセスで要求される時間は、それぞれのプロセスがアクセスする データの容量により変化します。また、他のユーザがデータ・ページを ロックしている場合など、スキャンが一時的にブロックされることもあり ます。すべてのデータが読み込まれたとき、各ワーカー・プロセスからの 結果は、コーディネーティング・プロセスによって設定された 1 つの結果 セットにマージされ、クライアントに返されます。 図 7-2: 逐次処理の場合と並列処理の場合のクエリ実行の相対実行時間 解析、 データ・アクセス 最適化、 結果の 戻り コンパイル group by クエリ の逐次実行 コーディネーティング・ プロセス 3 つのワーカー・ プロセスによる 同じクエリの 並列実行 時間 ワーカー・プロセス ワーカー・プロセス ワーカー・プロセス 解析、 データ・ 最適化、 アクセス マージと 結果の戻り コンパイル 並列動作のクエリによって実行された作業の合計量は、逐次動作のクエ リによって実行された作業量より大きくなりますが、応答時間は短くな ります。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 141 Adaptive Server のワーカー・プロセス・モデル 並列クエリからの結果の戻り 並列クエリからの結果は、次の 3 つのマージ方式のいずれか、または最終 ソート手順を使用して返されます。最終ソート手順がない並列クエリの場 合は、次のマージ方式のいずれかを使用します。 • ベクトル ( グループ化された ) 集約を含むクエリでは、ワークテーブ ルを使用して一時的な結果を保管する。コーディネーティング・プロ セスは、これらを 1 つのワークテーブルにマージして、結果をクライ アントに返す。 • スカラ ( グループ化されていない ) 集約を含むクエリでは、内部変数 を使用し、コーディネーティング・プロセスが最終的な計算を実行 して、結果をクライアントに返す。 • 集約を含まないクエリ、および最終ソートを要求しないクエリの場合、 テーブルのスキャン時に結果をクライアントに返す。各ワーカー・プ ロセスは、結果を結果バッファに保管し、アドレス・ロックを使用し て、そのタスクのネットワーク・バッファへの結果の転送を調整する。 クエリで複数のステップまたは複数のワークテーブルが使用される場合、 マージの種類を複数使用できます。 マージ・メッセージの詳細については、 『パフォーマンス&チューニング・ ガイド:モニタリングと分析』の「並列クエリに対する showplan メッセー ジ」(106 ページ ) を参照してください。 order by 句、distinct、union などを含む並列クエリの場合、結果は tempdb のワークテーブルに保管されます。ソートが並列ソートのメリットを利用 する場合は、並列ソートが使用され、ソートによって実行される最終マー ジ手順のときに結果がクライアントに返されます。 並列ソートが実行される方法の詳細については、 「第 9 章 並列ソート」を 参照してください。 注意 データ・ページをスキャンするときに並列クエリは複数のプロセス を使用するため、集約を使用しないクエリと最終ソート手順を含まないク エリは、逐次クエリとは異なる順序で結果を返すことがあります。また、 set rowcount が有効になっているクエリやローカル変数を選択するクエ リでは異なる結果を返すこともあります。 詳細と解決法については、 「並列クエリの結果が異なる場合」(165 ページ ) を参照してください。 142 Adaptive Server Enterprise 第7章 並列クエリ処理 並列データ・アクセスのタイプ Adaptive Server は、並列でデータにアクセスするとき、さまざまな方法を 使用します。使用する方法は、設定パラメータの設定、テーブルが分割さ れているかどうか、インデックスが使用できるかどうかなどによって異な ります。複数のテーブルまたは複数のステップを持つクエリの場合、オプ ティマイザは、逐次方式と並列方式を組み合わせて選択できます。並列方 式には、次のようなものがあります。 • ハッシュベース・テーブル・スキャン • ハッシュベース・ノンクラスタード・インデックス・スキャン。 • フル・テーブル・スキャンまたはクラスタード・インデックスで配置 されたスキャンのうち、いずれかのパーティションベース・スキャン。 • マージ・ジョイン中のレンジベース・スキャン。 以降の項では、これらの方式のうちのいくつかについて説明します。 例については、「第 8 章 並列クエリ最適化」を参照してください。 図 7-3 は、1 つのタスクによって逐次処理で実行される全ページロック・ テーブル・スキャンを示します。タスクは、テーブルのページ・チェーン を追跡して各ページを読み込み、必要なページがキャッシュにない場合は 物理 I/O の実行を停止します。 図 7-3: 逐次タスクによるデータ・ページのスキャン 1 つのページ・チェーン 7T1 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 143 並列データ・アクセスのタイプ ハッシュベース・テーブル・スキャン 図 7-4 は、ハッシュベース・テーブル・スキャン時に、3 つのワーカー・ プロセスが全ページロック・テーブルからデータ・ページにアクセスす る作業を分ける方法を示します。各ワーカー・プロセスがすべてのペー ジについて論理 I/O を実行します。しかし、各プロセスは、下の図の網か けの部分が示すようにページにあるローの 1/3 だけを検査します。ハッ シュベース・テーブル・スキャンは、ジョインの外部クエリでだけ使用 されます。 1 つのワーカー・プロセスは、他のワーカー・プロセスが I/O を待機して いる間に実行することができるので、エンジンを 1 つだけ使用している場 合であっても、並列アクセスを使用するメリットがあります。複数のエン ジンがある場合、一部のワーカー・プロセスが同時に動作できます。 図 7-4: ワーカー・プロセスによる非分割テーブルのスキャン WP1 1 つのページ・チェーン WP2 WP3 複数のワーカー・プロセス ハッシュベース・テーブル・スキャンでは、それぞれのワーカー・プロセ スが、それぞれのページにアクセスしてページ ID でハッシュする必要が あるため、スキャンの論理 I/O が増加します。データオンリーロック・ テーブルの場合は、ハッシュベース・テーブル・スキャンがエクステント ID またはアロケーション・ページ ID でハッシュするため、1 つのワー カー・プロセスだけが 1 ページをスキャンし、論理 I/O は増加しません。 144 Adaptive Server Enterprise 第7章 並列クエリ処理 パーティションベース・スキャン 図 7-5 は、3 つの物理ディスク上で 3 つに分割されているテーブルをクエ リがスキャンする方法を示します。エンジンを 1 つだけ使用する場合、実 行できるワーカー・プロセスは 1 つだけで、他のプロセスは I/O または 別のプロセスが設定したロックが解放されるのを待つためスリープする ので、クエリは並列アクセスのメリットを利用します。複数のエンジン が使用できる場合、ワーカー・プロセスが同時に動作できます。この設 定では、I/O の並列処理が提供されるため、並列処理のパフォーマンスが 向上します。 図 7-5: 複数のワーカー・プロセスによる複数のパーティションへのアクセス 3 つに分割されて いるテーブル data_dev1 7 WP1 data_dev2 WP2 data_dev3 WP3 ハッシュベース・インデックス・スキャン 図 7-6 は、ハッシュベース・インデックス・スキャンを示しています。ハッ シュベース・インデックス・スキャンは、ノンクラスタード・インデック スまたはデータオンリーロック・テーブルのクラスタード・インデックス で実行されます。各ワーカー・プロセスは、高いレベルのインデックスを 操作し、インデックスのリーフレベル・ページを読み込みます。次に、各 ワーカー・プロセスがデータ・ページ ID またはキー値に基づいてハッシュ を行い、どのデータ・ページまたはデータ・ローを処理するか決定します。 すべてのリーフ・ページを読み込んでも、無視できる程度のオーバヘッド しか生成されません。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 145 並列データ・アクセスのタイプ 図 7-6: ハッシュベース・ノンクラスタード・インデックス・スキャン 7 WP1 WP2 WP3 インデックス・ ページ データ・ページ ワーカー・プロセス 1 が読み込んだページ ワーカー・プロセス 2 が読み込んだページ ワーカー・プロセス 3 が読み込んだページ ジョインによる 2 つのテーブルの並列処理 図 7-7 は、3 つに分割されているテーブルでパーティションベース・ス キャンを実行し、2 番めのテーブルで 2 つのワーカー・プロセスを持つ ハッシュベース・インデックス・スキャンを実行しているネストループ・ ジョイン・クエリを示します。並列アクセス・メソッドがネストループ・ ジョインの複数のテーブルで使用されているとき、必要なワーカー・プ ロセスの合計数は、ワーカー・プロセスとスキャンとの積になります。こ の場合、6 つのワーカーがクエリを実行しており、各ワーカー・プロセス が両方のテーブルをスキャンします。最初のテーブルではそれぞれの分 割ごとに 2 つずつワーカー・プロセスがあり、2 番めのテーブルでは 6 つ のワーカー・プロセスがすべてインデックス・ツリーをナビゲートして、 リーフ・ページをスキャンします。各ワーカー・プロセスは、そのハッ シュ値に対応するデータ・ページにアクセスします。 オプティマイザは、スキャンで 20 ページ以上が返されるときにかぎり、 テーブルで並列プランを選択します。これらのタイプのジョイン・クエ リでは、内部スキャンが並列で最適化されるために、内部テーブルのジョ イン・キーに対して 20 以上の一致が必要になります。 146 Adaptive Server Enterprise 第7章 並列クエリ処理 図 7-7: 各テーブルで異なる並列アクセス・メソッドを使用するジョイン・クエリ テーブル 1: 3 つのデバイスに 分割されたテーブル data_dev1 WP2 7 WP1 7 WP4 テーブル 2: 各ジョイン・キーに一致 するローが 20 以上ある ノンクラスタード・イン デックス data_dev2 data_dev3 WP3 WP5 WP6 インデックス・ ページ データ・ページ パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 147 並列度の制御 showplan メッセージ showplan は、テーブルが並列でアクセスされるたびに並列度を出力します。 次の例は、図 7-7 のジョインで使用される各テーブルに対応するメッセージ を示します。 Executed in parallel with a 2-way hash scan. Executed in parallel with a 3-way partition scan. showplan は、使用されているワーカー・プロセスの合計数を示すメッセー ジも出力します。図 7-7 のクエリの場合、次のようにレポートされます。 Executed in parallel by coordinating process and 6 worker processes. その他の例については、 「第 8 章 並列クエリ最適化」を参照してください。 詳細については、 『パフォーマンス&チューニング・ガイド:モニタリン グと分析』の「並列クエリに対する showplan メッセージ」(106 ページ ) を 参照してください。 並列度の制御 並列クエリの「並列度」は、クエリを実行するときに使用されるワーカー・ プロセスの数を示します。この数値は、さまざまな要因により影響を受け ます。 • 並列設定パラメータまたはセッションレベルの制限。 表 7-1 と表 7-2 を参照。 • テーブルの分割の数 ( パーティションベース・スキャンの場合 )。 • オプティマイザが提示する並列処理のレベル。 • クエリの実行時に使用できるワーカー・プロセスの数。 並列度には、次のような制限を設定できます。 148 • サーバワイド - sp_configure に表 7-1 のパラメータを付けて使用 する。sp_configure は、システム管理者だけが使用できる。 • セッション単位 - set コマンドに表 7-2 のパラメータを付けて使用 する。set はすべてのユーザが実行でき、ストアド・プロシージャ にも入れることができる。 • select クエリ内 - 「クエリの並列処理の制御」(153 ページ ) に示す 方法で parallel 句を使用する。 Adaptive Server Enterprise 第7章 並列クエリ処理 並列処理を制御するための設定パラメータ 表 7-1 は、サーバワイドの並列度を制御するための設定パラメータを示し ます。 表 7-1: 並列実行のための設定パラメータ パラメータ number of worker processes 説明 コメント すべての並列クエリで使用できるワーカー・プロセス の最大数。各ワーカー・プロセスは、ユーザ接続とほ ぼ同じ量のメモリを必要とする。 サーバの再起動が必要。 max parallel degree 1 つのクエリで使用できるワーカー・プロセスの数。 動的。再起動は不要。 この値は、number of worker processes の値以下で、 max scan parallel degree の値以上にする必要がある。 max scan parallel degree ハッシュ・スキャンで使用できるワーカー・プロセス の最大数。number of worker processes と max parallel degree の値以下にする必要がある。 動的。再起動は不要。 number of worker processes の設定は、データのサイズとプロシージャ・ キャッシュに影響するため、total memory の値も変更する必要があります。 詳細については、『システム管理ガイド』を参照してください。 max parallel degree または max scan parallel degree を変更すると、キャッ シュ内のすべてのクエリ・プランが無効になります。そのため、次にスト アド・プロシージャまたはトリガを実行すると、プランが再コンパイルさ れて、新しい値が使用されます。 クエリ・プランに制限を適用する方法 クエリが最適化されるときに、設定パラメータがクエリ・プランに与える 影響は次のとおりです。 • • max parallel degree は、次の値を制限する。 • パーティションベース・スキャンのワーカー・プロセスの数。 • ネストループ・ジョイン・クエリでのワーカー・プロセスの合計 結合数。複数のテーブルに対しては、並列アクセス・メソッドが 使用される。 • マージ・ジョインでマージおよびソートの手順に使用されるワー カー・プロセスの数。 • 並列ソート・オペレーションで使用できるワーカー・プロセス の数。 max scan parallel degree は、ハッシュベース・テーブル・スキャン とインデックス・スキャンでのワーカー・プロセスの数を制限する。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 149 並列度の制御 結合での制限の動作 複数の並列クエリが同時に動作できるようにするには、 number of worker processes を 50 に設定します。テーブルを分割する数を最大で 10 にし たい場合、max parallel degree を 10 に設定します。これによって、すべ ての select クエリについて、ワーカー・プロセスの最大数を 10 に制限し ます。ハッシュベース・スキャンは、2 ~ 3 のワーカー・プロセスの場合 に最も効率が良くなるため、 max scan parallel degree は 3 に設定します。 1 つのテーブル・クエリまたは他のテーブルの逐次アクセスに関連する ジョインの場合、これらの値による並列の可能性は次のようになります。 • 2 ~ 10 に分割されるテーブルの並列パーティション・スキャン。 • 最大で 3 つのワーカー・プロセスを持つハッシュベース・テーブル・ スキャン。 • 最大で 3 つのワーカー・プロセスを持つハッシュベース・ノンクラス タード・インデックス・スキャン。 1 つまたは複数のテーブルで並列方式が使用されるネストループ・ジョイ ンの場合、考えられる並列の選択肢は次のとおりです。 • 1 つのテーブルでハッシュベース・スキャンを使用し、2 ~ 3 に分割 されるテーブルでパーティションベース・スキャンを使用するジョ イン。 • 両方のテーブルでパーティションベース・スキャンを使用するジョ イン。たとえば、次のようなものがある。 • 分割テーブルの並列度が 3、ハッシュベース・スキャンの max scan parallel degree が 3 の場合、3 × 3 で 9 のワーカー・プロセ スが必要。 • 2 つに分割されるテーブルと 5 つに分割されるテーブル。両方の テーブルに対するパーティションベース・スキャンで 10 のワー カー・プロセスが必要。 • 4 ~ 10 に分割されるテーブルをジョインに組み込み、1 つまたは 複数のテーブルを逐次アクセスにすることができる。 マージ・ジョインの場合は、次のようになります。 • 150 フルマージ・ジョインの場合、ジョイン・キーの別個の値が 10 より 少ない場合を除いて、10 のワーカー・プロセスがベース・テーブル をスキャンするため、テーブルの分割の数が考慮されない。 Adaptive Server Enterprise 第7章 • 並列クエリ処理 テーブルをスキャンし、ローを選択してワークテーブルに入れるマー ジ・ジョインには、次のようなものがある。 • マージ・ジョインを優先するスキャンは、逐次または並列で実 行される。このようなクエリの並列度は、一般的な方法で決定 される。 • マージの場合、ジョイン・キーの別個の値が少ない場合を除いて 10 のワーカー・プロセスが使用される。 • ソートの場合、最大で 10 のワーカー・プロセスが使用できる。 パフォーマンスを向上させるため、10 に分割されるテーブルにクラス タード・インデックスを作成し、number of worker processes に 50 を設 定すると、create index コマンドで max parallel degree を 20 に設定でき ます。 ワーカー・プロセスでソートを設定する場合の詳細については、 「並列ソー ト中のワーカー・プロセスの稼働条件」(216 ページ ) を参照してください。 並列設定パラメータの設定例 次のコマンドにより、number of worker processes を設定します。 sp_configure "number of worker processes", 50 サーバを再起動してから、次のコマンドにより他の設定パラメータを設定 します。 sp_configure "max parallel degree", 10 sp_configure "max scan parallel degree", 3 これらのパラメータに対応する現在の設定を表示するときは、次のコマン ドを使用します。 sp_configure "Parallel Query" パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 151 並列度の制御 セッションの並列処理を制御するための set オプションの使用 2 つの set オプションにより、セッション単位、またはストアド・プロシー ジャやトリガの中で並列度を制限できます。これらのオプションは、並列 クエリでチューニングのテストをするときに使用すると便利です。また、 重要でないクエリを逐次処理で動作するよう制限し、ワーカー・プロセス を他のタスクで使えるようにするときにも使用できます。表 7-2 は、set オプションの要約を示します。 表 7-2: 並列実行のチューニングに使用する set オプション パラメータ parallel_degree scan_parallel_degree 機能 セッションのクエリ、ストアド・プロシージャ、またはトリガに対して、ワーカー・プロ セスの最大数を設定する。 max parallel degree 設定パラメータを上書きするが、 max parallel degree 以下の値にする必要がある。 特定のセッション、ストアド・プロシージャ、またはトリガの実行中のハッシュベース・ スキャンに対して、ワーカー・プロセスの最大数を設定する。max scan parallel degree 設 定パラメータを上書きするが、max scan parallel degree 以下の値にする必要がある。 set のどちらのオプションの場合も、指定する値が大きすぎると、対応する 設定パラメータの値が使用され、メッセージによって有効な値がレポート されます。 セッション中 set parallel_degree または set scan_parallel_degree が有効な間は、実行するストアド・プロシージャのプランはプロシージャ・ キャッシュに入れられます。これらのオプションを有効にして実行するプ ロシージャの場合、プランは必ずしも最適な状態にはなりません。 set コマンドの例 次の例では、現在のセッションで開始されるすべてのクエリでワーカー・ プロセスを 5 つに制限します。 set parallel_degree 5 このコマンドが有効な間、5 より多くの数に分割されるテーブルのクエ リは、パーティションベース・スキャンを使用できなくなります。 セッションの制限を削除するには、次のコマンドを使用します。 set parallel_degree 0 or set scan_parallel_degree 0 それ以降のクエリを逐次モードで実行するときは、次のコマンドを使用し ます。 set parallel_degree 1 or set scan_parallel_degree 1 152 Adaptive Server Enterprise 第7章 並列クエリ処理 クエリの並列処理の制御 select コマンドの from 句に parallel 拡張機能を指定することにより、 select 文で使用されるワーカー・プロセスの数を指定できます。並列度 には、sp_configure で設定した値、または set コマンドで制御するセッ ションでの制限値より大きい値を指定できません。大きい値を指定した 場合、その指定は無視され、set または sp_configure の制限値が使用さ れます。 select 文の構文は、次のようになります。 select ... from tablename [( [index index_name] [parallel [degree_of_parallelism | 1 ]] [prefetch size] [lru|mru] ) ] , tablename [( [index index_name] [parallel [degree_of_parallelism | 1] [prefetch size] [lru|mru] ) ] ... クエリ・レベルの parallel 句の例 1 つのクエリに並列度を指定するには、テーブル名の次に parallel を指定 します。次の例は、逐次処理で実行されます。 select * from huge_table (parallel 1) 次の例は、クエリで使用するインデックスを指定し、並列度を 2 に設定し ます。 select * from huge_table (index ncix parallel 2) 詳細については、 「クエリの並列度の指定」(53 ページ ) を参照してください。 ワーカー・プロセスの可用性とクエリの実行 実行時に、クエリ・プランで指定したワーカー・プロセスの数が使用で きない場合、Adaptive Server はクエリ・プランを調整し、より少ないワー カー・プロセスを使用してクエリを実行します。これは「実行時調整」 と呼ばれ、場合によっては結果的にクエリが逐次実行されることもあり ます。 実行時調整は、ときには瞬間的なボトルネックが随時発生することを示し ている可能性があります。実行時調整が頻繁に起こる場合は、その処理の 負荷に対して、システムで十分なワーカー・プロセスが設定されていない ことを示します。 詳細については、「ワーカー・プロセスの実行時調整」(202 ページ ) を参 照してください。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 153 並列度の制御 また、set process_limit_action オプションを使用して、クエリとストアド・ プロシージャのどちらが調整されたプランを暗黙的に使用するか、ユーザ に対する警告を表示するかどうか、最適なワーカー・プロセス数を使用で きない場合にコマンドが失敗するよう設定するかどうかなども制御でき ます。 詳細については、 「set process_limit_action の使用」(204 ページ ) を参照し てください。 実行時調整は、次の場合を除いて、エンド・ユーザに対して透過的に処理 されています。 • 通常、並列で実行されるクエリは、逐次処理では動作が非常に遅くな ることがある。 • set process_limit_action が有効な場合は、設定によって、警告が表示 されるかクエリがアボートされるかのいずれかになる。 並列処理で使用するその他の設定パラメータ 並列処理で使用するその他の設定パラメータには、次の 2 つがあります。 • number of sort buffers - 並列ソート・オペレーションがデータ・キャッ シュから使用できるバッファの最大数を設定する。 詳細については、 「キャッシュ、ソート・バッファ、並列ソート」(220 ページ ) を参照してください。 • memory per worker process - クエリの処理中にメッセージを出力 するためにすべてのワーカー・プロセスが使用するメモリのプールを 確立する。デフォルト値は、1 ワーカー・プロセスあたり 1024 バイ トだが、ほとんどすべての場合についてこの値で十分である。した がってこの値を再設定する必要はない。 この値のモニタリングとチューニングの方法については、 『パフォーマ ンス&チューニング・ガイド:モニタリングと分析』マニュアルの 「ワーカー・プロセス管理」(28 ページ ) を参照してください。 154 Adaptive Server Enterprise 第7章 並列クエリ処理 分割されたテーブルを操作するためのコマンド テーブルを分割する方法、そのテーブルを特定のデバイスに配置する方法、 並列バルク・コピーでデータをロードする方法の詳細な手順については、 『パフォーマンス&チューニング・ガイド:基本』の「第 6 章 データの物 理的配置の制御」を参照してください。分割されたテーブルを作成、管理、 保存するためのコマンドとタスクには、次のようなものがあります。 • alter database - デバイスをデータベースで使用できるようにする。 • sp_addsegment - デバイスにセグメントを作成する。他のデバイス へセグメントを拡張するには sp_extendsegment、データ・デバイス か ら ロ グ・セ グ メ ン ト や シ ス テ ム・セ グ メ ン ト を 削 除 す る に は sp_dropsegment を使用する。 • create table...on segment_name - セグメントにテーブルを作成する。 • alter table...partition と alter table...unpartition - テーブルに分割を追 加または削除する。 • create clustered index - テーブルの分割にまたがってデータを均等 に分散する。 • bcp ( バルク・コピー ) - テーブル名のうしろに分割番号を付けるこ とにより、データを特定のテーブル分割にコピーする。 • sp_helpartition - 分割の数、およびその分割のデータの分配を表示 する。セグメントの各デバイスおよびセグメント全体で使用されて いる領域をチェックするときは sp_helpsegment を使用する。 図 7-8 は、新しい分割テーブルを作成するための概要を示します。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 155 分割されたテーブルを操作するためのコマンド 図 7-8: 新しい分割テーブルを作成してロードするときの手順 alter database を使用してデバイスをデー タベースで使用できるようにする。 sp_addsegment を使用してデバイスにセ グメントを作成し、sp_extendsegment を使用してセグメントを他のデバイス上に 拡張する。また、sp_dropsegment を使 用してデータ・デバイスからログ・セグメ ントやシステム・セグメントを削除する。 create table...on segment_name を使用し てセグメントにテーブルを作成する。 alter table...partition を使用してそれぞれ のデバイスに分割を作成する。 パラレル・バルク・コピーにより、 データが入力データ・ファイルか らそれぞれの部分にロードされる。 T10 cooking 6.95 T10001 cooking 42.95 T10007 cooking 47.95 T10023 cooking 46.95 T10029 cooking 74.95 T10032 fiction 35.95 T10035 cooking 49.95 T10038 cooking 12.95 T25355 business 69.95 T39076 psychology 10.95 T56358 UNDECIDED 39.95 T75542 romance 44.95 T10056 cooking 1.95 T25361 business 42.95 T39082 psychology 6.95 authentication for network mail 156 A Unified Approach to... Scheme for an internet... Internet Protocol Ha... Proposed change in P... System Summary for... Cyberpunk Achieving reliable coo... Reliable Recipes Plan and schedule Reallocation and Urb... New title Rosalie’s Romance Brave New Cookery Network Nuisance On the problem... Adaptive Server Enterprise 第7章 並列クエリ処理 リソースの配分とパフォーマンス 並列パフォーマンスを最大にするには、複数の CPU と複数の I/O デバイ スを使用して I/O の並列処理を実行する必要があります。通常のパフォー マンス設定では、並列システムが限界点に到達し、その点を超えると、リ ソースを追加してもパフォーマンスが向上しなくなります。 クエリが CPU 集約か I/O 集約かを判断し、同時にパフォーマンスが CPU の飽和または I/O のボトルネックでブロックされるタイミングを判断す る必要があります。CPU の使用率が低い場合は、テーブルをより多くの デバイスに分散したり、使用するワーカー・プロセスを増やしたりすると CPU の使用率が高くなるため、応答時間が改善されます。逆に CPU の使 用率が非常に高いにもかかわらず I/O システムが飽和状態になっていな い場合は、CPU の数を増やすとパフォーマンスが向上します。 CPU リソース 適切な数のエンジン (CPU リソース ) を使用しない場合、タスクとワー カー・プロセスが Adaptive Server エンジンへのアクセスを待たなければな らなくなるため、応答時間が遅くなります。たとえば、クエリが CPU 集 約か I/O 集約かなどの多くの要因によって、システムで必要なエンジンの 数が決まります。また、状況によっては次のような要因も考えられます。 • ワーカー・プロセスは、他のタスクが CPU でアクティブになってい る間、ディスク I/O と他のシステム・リソースを待機する傾向にある。 • ソートと集約を実行するクエリで、CPU 集約の傾向が強くなる。 • 並列の CPU 集約クエリで、実行クラスとエンジンの結び付きとがバ インドされて、システムに複雑な影響を与える。CPU が十分に存在 しない場合、逐次クエリと並列クエリの両方のパフォーマンスは低下 する可能性がある。 詳細については、 『パフォーマンス&チューニング・ガイド:基本』 マニュアルの「第 5 章 タスク間でのエンジン・リソースの分配」を 参照。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 157 リソースの配分とパフォーマンス ディスク・リソースと I/O ほとんどの場合、並列処理では、デバイス上のテーブルとインデックスの 物理レイアウトの設定が、パフォーマンスの鍵になります。次の条件をす べて満たしている場合、分割を別のディスクとコントローラに分散すると、 パーティションベース・スキャンでパフォーマンスが向上する可能性があ ります。 • データがさまざまなディスクに分散されている。 • これらのディスクが、さまざまなコントローラに分散されている。 • それぞれの分割にワーカー・プロセスを 1 つずつ割り当てられるだけ の十分なワーカー・プロセスを、実行時に使用できる。 チューニングの例:CPU と I/O の飽和 CPU 集約のクエリの実験において、I/O サブシステムが飽和状態になるま で CPU を追加していくと、そのパフォーマンスが線形スケーリングに近 い状態になりました。この状態では、CPU リソースを追加してもパフォー マンスは向上しませんでした。クエリは、16K I/O を使用して、30 に分割 される 800MB のテーブルに対してテーブル・スキャンを実行します。表 7-3 は、CPU のスケーリングを示します。 表 7-3: エンジンとワーカー・プロセスのスケーリング エンジン 1 経過時間(秒 ) 207 CPU の使用率 100% 飽和しない 1 秒あたりの 各デバイスの スループット 0.13MB 2 100 98.7% 飽和しない 0.27MB 4 50 98% 飽和しない 0.53MB 8 27 93% 100% 飽和 0.99MB 158 I/O の飽和 Adaptive Server Enterprise 第7章 並列クエリ処理 並列クエリ設定のガイドライン 並列処理では、システム・リソースの要件が同じクエリを逐次実行する場 合とは非常に異なります。並列処理のプランは、次の 2 つの要素で構成さ れます。 • システムで使用されている基本ハードウェアの機能についての理解 ( 特にディスク・ドライブとコントローラ )。 • 並列で実行するクエリのパフォーマンス目標の設定。 ハードウェアのガイドライン 次に、ハードウェア設定とディスク I/O 速度のガイドラインを示します。 • 各 Adaptive Server エンジンは、CPU 集約クエリで CPU 利用率の飽和 に達する前に、ほぼ 5 つのワーカー・プロセスをサポートできる。こ の割合でも CPU が飽和状態にならない場合で、並列クエリのパ フォーマンスをさらに向上させたい場合は、I/O 帯域幅がボトルネッ クになるまで、1 つのエンジンに対するワーカー・プロセスの割合を 高くする。 • 16K I/O を使用するテーブル・スキャンなどの逐次スキャンの場合、 1 デバイスあたり 1 秒間に 1.6MB、つまり 1 デバイスあたり 16K I/O を 100 回 (1 秒間に 800 ページ ) 達成できる。 • ノンクラスタード・インデックス・アクセスのように、ランダム・ア クセスを実行するクエリの場合、上記の値は 1 デバイスあたり 2K I/O が約 50 回 (1 秒間に 50 ページ ) になる。 • 1 つの I/O コントローラは 1 秒間で 10 ~ 18MB の転送率を維持で きる。これは、1 つの SCSI I/O コントローラが逐次スキャンを実行 するデバイスを 6 ~ 10 個サポートできることを示している。一部 のハイエンド・ディスク・コントローラでは、さらに高いスルー プットをサポートできる。計算する場合には、ハードウェアの仕様 をチェックし、ピーク時の転送率ではなく継続的に維持される率を 使用する。 • RAID ディスク・アレイのパフォーマンス特性は、RAID レベル、ス トライプ・セットのデバイス数、キャッシングなどの固有の機能に より大きく変動する。RAID デバイスでは、ストライピングのない同 数の物理ディスクに比べて、スループットに差が出ることもある。ほ とんどの場合、並列クエリをチューニングするときの最初の手段と して、これらのデバイスのテーブルの分割数をアレイのディスク数 に設定する。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 159 並列クエリ設定のガイドライン パフォーマンスの目標とハードウェア・ガイドライン 次に、前記のハードウェア・ガイドラインと表 7-3 の例を使用して、パ フォーマンスの目標を達成するために並列処理を使用する方法を示し ます。 • テーブルの分割数をデバイス数以下にする必要がある。表 7-3 にある エンジンとワーカー・プロセスのスケーリングを示す実験では、30 の デバイスが使用できたために 30 の分割が使用されている。パフォー マンスは、すべての分割が別々の物理デバイスに置かれた場合に最適 になる。 • 実現したい I/O のスループットに基づいて分割の数を決定する。ディ スクとコントローラがデバイス 1 つあたり 1 秒間に 1MB の転送率を 維持できる場合に、800MB のテーブルに対してテーブル・スキャン を 30 秒間で実行したいときは、1 秒間に約 27MB の合計スループッ トを達成する必要がある。そのため、最低でも 27 個のデバイスを用 意して、1 つのデバイスに 1 つの分割を割り当てると同時に、それぞ れの分割に対して、最低 27 個のワーカー・プロセスを用意する。こ れらの値は、表 7-3 の例に見られる I/O レートと非常に近い数字に なっている。 • 分割の数に基づいて CPU の数を見積もり、CPU 利用率と I/O 飽和の 両方を追跡することで最適な数を決定する。表 7-3 の例では、30 の分 割が使用できた。ハードウェア・ガイドラインでは、デバイス 5 個あ たり 1 つの CPU という指定になっているため、これに従い、CPU 集 約クエリで 6 つのエンジンを使用する。このレベルでは I/O が飽和状 態になっていないため、エンジンを追加することで、応答時間を改善 できる。 並列クエリのチューニングの例 次の例では、 「ハードウェアのガイドライン」(159 ページ ) で説明してい る I/O の機能を使用しています。 テーブル・スキャンのパフォーマンスの向上 次の例は、パフォーマンスの目標を達成するためにテーブルを分割する方 法を示します。テーブル全体をスキャンして一定数以下のローを返すクエ リは、並列処理のパフォーマンス向上のためによく使用される手段です。 例では、group by を含む次のクエリが使用されています。 select type, avg(price) from titles group by type 160 Adaptive Server Enterprise 第7章 並列クエリ処理 次に、パフォーマンスの統計とチューニングの目標を示します。 テーブル・サイズ 48,000 ページ アクセス・メソッド テーブル・スキャン、16K I/O 逐次応答時間 60 秒 ターゲットのパフォーマンス 6秒 次に、並列オペレーションを設定する手順を示します。 • テーブルについて 10 の分割を作成し、そのデータを分割の間で均等 に分散する。 • number of worker processes と max parallel degree 設定パラメータを 10 以上に設定する。 • 16K I/O 用に設定されたキャッシュをテーブルが使用することをチェッ クする。 逐次実行の場合、16K I/O を使用することで、60 秒間に 48,000 ページ がスキャンされます。並列実行では、各プロセスが、約 6 秒間で 1 つの 分割 ( 約 4,800 ページ ) をスキャンします。この場合も 16K I/O が使用 されます。 ノンクラスタード・インデックス・スキャンのパフォーマンスの改善 次の例は、ハッシュベース・スキャンの設定により、ノンクラスタード・ インデックス・スキャンを使用するクエリのパフォーマンスを向上する方 法を示します。次の表は、パフォーマンスの統計とチューニングの目標を 示します。 アクセスするデータ・ページ 1500 アクセス方式 ノンクラスタード・インデックス、2K I/O 逐次応答時間 30 秒 ターゲットのパフォーマンス 6秒 次に、並列オペレーションを設定する手順を示します。 • max scan parallel degree 設定パラメータを 5 に設定して、ハッシュ ベース・スキャンで 5 つのワーカー・プロセスを使用する。 • number of worker processes と max parallel degree を 5 以上に設定 する。 並列実行では、それぞれのワーカー・プロセスが、約 6 秒間で 300 ページ をスキャンします。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 161 並列クエリ設定のガイドライン 分割と並列度のガイドライン 次に、逐次クエリ実行から並列クエリ実行へ移行する場合と、すでに動作 している並列クエリに分割またはワーカー・プロセスを追加する場合に考 慮すべきガイドラインを示します。 162 • テーブルのキャッシュ・ヒット率が 90% を超える場合、テーブルを 分割しても、パフォーマンスはあまり向上しない。これは、必要な ページのほとんどがキャッシュ内にあるので、物理 I/O で並列処理を してもメリットが利用できないためである。 • CPU 利用率が 80% を超えていて、システムのクエリの大多数が並列 クエリを使用できる場合、並列度を高くすることによって CPU の飽 和が発生する。このガイドラインは、すべてが逐次的に実行される クエリ処理を、非常に多くのクエリが並列処理を使用するクエリ処 理に移行する場合にも当てはまる。このような場合、エンジンを追 加するか、最初に並列度を小さくすることを検討する。 • CPU 利用率が高く、大規模な DSS クエリを実行するユーザが少なく、 ほとんどのユーザが並列で動作しない OLTP クエリを実行している 場合、並列処理を有効にしたり増やしたりすることで、DSS クエリの 応答時間を改善できる。しかし、OLTP クエリの応答時間が重要であ る場合は、並列度を小さくするか、現在の並列度をあまり変更しない ようにする。 • CPU 利用率が低い場合、並列度を少しずつ高くする。2 つの CPU を 持ち、平均 CPU 利用率が 60% のシステムの場合、ワーカー・プロセ スを倍にすると CPU が飽和状態になる。 • デバイスの I/O が飽和状態よりもかなり少ない場合、 「1 つのデバイ スあたり 1 つの分割」のガイドラインを採用しないことにより、一 部のクエリについてパフォーマンスを向上できる。この場合、RAID デバイスを除いて、分割に対応するセグメントの論理デバイス数の 倍数を常に使用する。つまり、4 つのデバイスを持つセグメントの テーブルでは 8 つの分割を使用する。デバイスあたりの分割の数を 倍にすると、ディスクヘッドの動きが頻繁になるが、I/O の並列処理 は少なくなる。デバイス数よりも多くの数に分割されているテーブ ル上にインデックスを作成すると、警告メッセージが表示されるが、 この場合は無視できる。 Adaptive Server Enterprise 第7章 並列クエリ処理 データのサブセットを使用した実験 並列クエリ処理を使用すると、大きなテーブルおよびほとんどの I/O 集約 クエリで最高のパフォーマンスを実現できます。しかし、巨大なテーブ ルでさまざまな物理レイアウトを実験してみるのは、大変時間がかかり ます。代わりに、より小さいデータのサブセットを使用する場合の注意 を次に示します。 • オプティマイザによって選択されるクエリ・プランの種類を判定す るための最初の調査では、データの比例サブセットで実験する。た とえば、5000 万行のローを持つテーブルが 500 万行のローのテーブ ルにジョインしている場合、そのデータの 1/10、つまり、500 万行 のローのテーブルと 50 万行のローのテーブルを使用する。必ず正し いジョインを持つテーブルのサブセットを選択する。テーブルの ジョインが並列で動作する場合、1 回のスキャンで 20 のローが返さ れるため、サブセットがこのジョインの選択性を反映することを確 かめる。 • オプティマイザは、基本となる物理デバイスを無視し、テーブルの分 割だけを考慮する。実験でのチューニング作業中は、データを別々の 物理デバイスに分散することによって、フル・テーブルを使用する運 用システムの特性について正確に予測できる。1 つのデバイス上にある テーブルも分割できる。このとき、設定パラメータのテスト、テーブ ルの分割、クエリの最適化のチェックなど、プランニング作業の最初 の段階で表示される警告メッセージについては無視できる。もちろん、 その場合は正確な I/O 統計が得られない。 データのサブセットを使用すると、並列クエリ・プランやテーブルの並列 度も判定できます。相違点として、大きなテーブルのときに並列で実行さ れるソートが、小さなテーブルのときに逐次処理で実行されることがあり ます。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 163 システム・レベルの影響 システム・レベルの影響 この章で説明しているさまざまな影響のほか、DSS と OLTP が混在する環 境に並列処理を追加する場合に考慮すべきことがあります。目標は、OLTP アプリケーションのパフォーマンスに悪い影響を与えることなく、並列処 理によって DSS のパフォーマンスを向上させることです。 ロックの問題 次のようなロック競合に注意してください。 • 並列クエリは、競合のないベンチ・マーク・クエリより速度が遅 くなる。スキャンを実行して、更新トランザクションにより排他 ロックされたページが多く見つかった場合、パフォーマンスが変 わる可能性がある。 • 並列クエリがネットワーク・バッファ・マージを使用して大量 のローを返す場合、ネットワーク・バッファで競合が多くなる ことがある。これらのクエリは、スキャンの処理中にデータ・ ページを共有ロックするため、共有ロックが解放されるまで データ修正ができなくなることがある。状況によっては、大き な結果セットを返すクエリを、逐次オペレーション用として制 限する必要がある。 • DSS クエリを逐次処理で実行していて、アプリケーションがデッ ドロックする場合、これらのクエリを並列処理で実行するとデッ ドロックが増加する。デッドロックが起こった場合のロールバッ クは、関連するプロセスの累積 CPU 時間に基づいて決定される ため、これらのデッドロックでロールバックされるトランザク ションは、OLTP クエリとなる可能性が大きい。 デッドロックの詳細については、 『パフォーマンス&チューニン グ・ガイド:ロック』マニュアルの「デッドロックと同時実行 性」(80 ページ ) を参照してください。 デバイスの問題 tempdb で複数のデバイスを設定すると、ワークテーブルを必要とする並 列クエリのパフォーマンスが向上します。これらの並列クエリには、ソー トと集約を実行するものや、再フォーマッティング方式を使用するものが あります。 164 Adaptive Server Enterprise 第7章 並列クエリ処理 プロシージャ・キャッシュの影響 並列クエリ・プランは、分割についての余分な命令や、ワーカー・プロセ スがアクセスする必要のあるページを含んでいるため、逐次クエリ・プラ ンより少し大きくなります。 特定のクエリの処理中、各ワーカー・プロセスにはクエリ・プランのコ ピーが必要になります。プロシージャ・キャッシュの領域は、これらのプ ランをメモリに保持するときに必要になるもので、特定のクエリが終了し たらプロシージャ・キャッシュとして再び使用できるようになります。 設定パラメータの max parallel degree と max scan parallel degree を変更 すると、キャッシュ内にあるストアド・プロシージャは無効になります。 次にクエリを実行するとき、クエリがディスクから読み込まれ、再コンパ イルされます。 並列クエリの結果が異なる場合 クエリにベクトルまたはスカラ集約が含まれていない場合、または最終 ソート手順が必要ない場合、並列クエリで返される結果の順序が、同じク エリを逐次処理で実行したときとは異なる順序になることがあります。そ れ以降、同じクエリを並列で実行すると、結果が毎回異なる順序で返され ます。 逐次クエリおよび並列クエリにベクトルまたはスカラ集約が含まれてい るか、最終ソート手順が必要な場合、その結果は、最終クエリ処理手順 でワークテーブルのすべての結果がマージまたはソートされてから返さ れます。この最終手順を必要とするクエリ句がない場合、並列クエリは、 ネットワーク・バッファ・マージを使用して結果をクライアントに送り ます。つまり、各ワーカー・プロセスは、このクエリを満たすデータを 取得した時点で、結果をネットワーク・バッファに送ります。 ワーカー・プロセスが異なると速度も異なるため、結果セットの順序に違 いが出ます。また、すでにキャッシュに入っているページや、ロックの競 合などによっても、それぞれの並列スキャンは違う動作になります。並列 クエリは常に、違う「順序」で同じ結果の「セット」を返します。結果の 順序を信頼できるものにする必要がある場合は、order by を使用するか、 クエリを逐次モードで実行します。 さらに、データ・ページを読み込む複数のワーカー・プロセスによる調整 の影響があるため、次の 2 種類のクエリは、集約または最終ソートが実行 されないとき、同じデータにアクセスしても異なる結果を返すことがあり ます。 • set rowcount を使用するクエリ。 • 十分に制限的なクエリ句を持たないで、カラムを選択してローカル変 数に入れるクエリ。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 165 並列クエリの結果が異なる場合 set rowcount を使用するクエリ set rowcount オプションを使用すると、一定数のローがクライアントに返 された後、処理が停止します。逐次処理では、反復実行を行った結果に一 貫性があります。逐次モードの場合、1 つのプロセスがデータ・ページを 毎回同じ順序で読み込むため、任意の rowcount 値に対して同じローが同 じ順序で返されます。 一方、並列クエリでは、ページへのアクセス速度がワーカー・プロセスご とに異なる可能性があるため、返される結果の順序とローのセットが異な ることがあります。set rowcount が有効な場合、それぞれのローは、見つ かった順にネットワーク・バッファに書き込まれます。そのバッファは、 必要な数のローが返されるまで、満杯になった時点でクライアントに送ら れます。一貫性のある結果を得るためには、最終ソート手順を実行する句 を使用するか、クエリを逐次モードで実行してください。 ローカル変数を設定するクエリ 次のクエリは、select 文でローカル変数の値を設定します。 select @tid = title_id from titles where type = "business" where 句は、titles テーブルの複数のローと一致します。そのため、この ローカル変数は常に、クエリから返されるローのうち最後に一致した ローの値に設定されます。逐次処理の場合、値は常に同じになります。し かし、並列クエリ処理の場合、結果は、ワーカー・プロセスの最後の状 態により変わります。一貫性のある結果を得るためには、最終ソート手 順を実行する句を使用するか、クエリを逐次モードで実行してください。 また、句を追加して、クエリ引数に 1 つのローだけを選択させる方法も あります。 一貫した結果の取得 この項で説明したすべてのクエリの種類で一貫した結果を得るには、最終 ソートを強制する句を追加するか、クエリを逐次モードで実行します。最 終ソートを実行するクエリ句は、次のいずれかになります。 166 • order by • distinct (avg(distinct price) などのように集合の中で distinct を使用す る場合を除く ) • union (union all は除く ) Adaptive Server Enterprise 第7章 並列クエリ処理 クエリを逐次モードで実行するときは、次の方法を使用します。 • set parallel_degree 1 を使用して、セッションを逐次オペレーション に限定する。 • クエリの from 句にリストされているそれぞれのテーブルの次に (parallel 1) 句を指定する。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 167 並列クエリの結果が異なる場合 168 Adaptive Server Enterprise 第 8 章 並列クエリ最適化 この章では、並列クエリを実行するために Adaptive Server が使用する基本 的な方式と、オプティマイザがさまざまなクエリに対してこれらの方式を どのように適用するかについて説明します。並列クエリ最適化は自動的に 行われ、Adaptive Server の作成したクエリ・プランによって、通常、特定 のクエリを最短の応答時間で処理します。 しかし、並列クエリの内部動作について知っている場合は、クエリが逐次 実行されることがあったり、予想よりも少ないワーカー・プロセスで実行 されたりする理由を理解しやすくなります。こうした事象が起こる理由を 知っておくことで、必要なプロセス数による並列クエリが確実に実行され るように、システムの他の部分に変更を加えることができます。 トピック名 並列クエリ最適化とは? ページ 169 最適化が実行される場合 170 オーバヘッド・コスト 171 並列アクセス・メソッド 172 並列アクセス・メソッドのまとめ 184 並列クエリの並列度 185 並列クエリの例 194 ワーカー・プロセスの実行時調整 202 並列処理のパフォーマンスの問題に対する診断 206 並列クエリのリソース制限 208 並列クエリ最適化とは? 並列クエリ最適化とは、クエリを分析し、並列アクセス・メソッドと逐次 アクセス・メソッドを最良の方法で組み合わせて、最も短い応答時間でク エリを行う処理です。並列クエリ最適化は、これまでの章で説明した逐次 最適化方式を拡張したものです。逐次クエリ最適化の場合と同様に、並列 最適化はジョイン順、ジョイン・タイプ、インデックスの各組み合わせに ついて並列アクセス・メソッドのコストを分析します。オプティマイザは 逐次アクセス・メソッドと並列アクセス・メソッドの組み合わせを選択し、 最も高速なクエリ・プランを作成します。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 169 最適化が実行される場合 最適化における応答時間と合計作業量 逐次クエリ最適化は、実行にかかるコストが最も少ないクエリ・プランを 選択します。クエリを実行するプロセスは 1 つだけなので、最もコストの 少ないプランを選択すると応答時間は最短になり、サーバからの合計作業 量も最少になります。 クエリを並列処理で実行する目的は、サーバからの合計作業量が多い場合 でも、応答時間を最短にすることです。並列クエリ最適化の実行中、オプ ティマイザは逐次最適化のときと同様にコスト・ベースの比較を行って、 最終的なクエリ・プランを選択します。 しかし、並列クエリ・プランでは、複数のワーカー・プロセスがクエリを 実行するため、Adaptive Server に要求される合計作業量が通常より多くな ります。複数のワーカー・プロセス、エンジン、分割によってクエリの速 度は向上しますが、オーバヘッド、CPU 使用率、ディスク・アクセスに ついては、必要なコストが増大します。言い換えれば、逐次クエリ最適化 が使用するサーバ・リソースを最小限にすることによってパフォーマンス を向上させる一方で、並列クエリ最適化は、使用できるリソースを十分に 活用することによって個々のクエリのパフォーマンスを向上させ、最短の 応答時間を実現します。 最適化が実行される場合 「並列度の制御」(148 ページ ) で説明されているように、Adaptive Server と 現在のセッションが並列処理を行うように正しく設定されている場合に 限り、オプティマイザは並列クエリ・プランを使用します。 Adaptive Server と現在のセッションの両方が並列クエリ用に設定されて いる場合、そのセッション中に実行されるすべてのクエリは並列クエリ最 適化に適したものとなります。また、オプティマイザ・ヒント parallel N ( 並列の場合 ) または parallel 1 ( 逐次の場合 ) を使用することで、並列ク エリ最適化を強制することもできます。 Adaptive Server または現在のセッションが並列クエリ用に設定されてい ない場合、または逐次処理を強制するオプティマイザ・ヒントをクエリが 使用する場合、オプティマイザは、逐次アクセス・メソッドだけを使用し ます。この場合、この章で説明する並列アクセス・メソッドは使用されま せん。 Adaptive Server は、システム・テーブルに対して並列クエリを実行するこ とはありません。 170 Adaptive Server Enterprise 第8章 並列クエリ最適化 オーバヘッド・コスト 並列クエリは、次のような内部作業を実行するため、より多くのオーバ ヘッド・コストを伴います。 • ワーカー・プロセスの割り付けと初期化。 • クエリ・プランを実行するワーカー・プロセスの調整。 • クエリ完了後のワーカー・プロセスの割り付け解除。 OLTP ベースのクエリに伴うこれらのオーバヘッド・コストを回避する ため、テーブル内でスキャンが 20 未満のデータ・ページにしかアクセス しない場合は、オプティマイザはそのテーブルが並列アクセス・メソッ ドを使用するには「不適切」と見なします。この制限は、テーブルのデー タにアクセスするためにインデックスが使用されるかどうかに関係なく 適用されます。Adaptive Server が 20 未満のデータ・ページしかスキャン しない場合は、オプティマイザは逐次テーブル・スキャンと逐次インデッ クス・スキャンだけを行い、並列最適化方式は適用されません。 考慮されない要素 並列アクセス・メソッドのコストを計算する場合、オプティマイザは、使 用できるエンジンの数や、エンジンの CPU 使用率、テーブルの分割が専 用の物理デバイスやコントローラにあるかどうか、などの要因を考慮しま せん。これらの要因は、クエリのパフォーマンスに大きく影響します。 Adaptive Server システムの全体にわたり、考えられる最良の方法でリソー スを確実に設定する作業は、システム管理者が行います。 Adaptive Server の設定の詳細については、 「並列設定パラメータの設定例」 (151 ページ ) を参照してください。 円滑な並列クエリを実行できるようにデータを分割する方法については、 『パフォーマンス&チューニング・ガイド:基本』の「テーブルを分割す るためのコマンド」(102 ページ ) を参照してください。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 171 並列アクセス・メソッド 並列アクセス・メソッド 以降の項では、オプティマイザが並列クエリを最適化する場合に使用する 並列アクセス・メソッドや、その他の方式を説明します。並列アクセス・ メソッドは、通常、次の 3 つのカテゴリに分類されます。 172 • 「パーティションベース・アクセス・メソッド」は、2 つ以上のワー カー・プロセスを使用して、テーブルの個別の分割にアクセスする。 パーティションベース・メソッドでは、テーブルへのアクセスを CPU と物理ディスクの両方に分散させるため、最も早い応答時間が得ら れる。CPU レベルでは、ワーカー・プロセスを個別のエンジンに キューイングすることで、処理のパフォーマンスを向上できる。物 理ディスクのレベルでは、テーブルの分割が個別の物理デバイスや コントローラに分散されている場合、各ワーカー・プロセスは互い に独立して I/O を実行する。 • 「ハッシュベース・アクセス・メソッド」では、テーブル・スキャン またはインデックス・スキャンのどちらかを使用して、分割された テーブルに並列アクセスができる。ハッシュベース方式は複数のワー カー・プロセスを使用して、データ・ページの 1 つのチェーンまたは インデックス・ページの 1 つのセット上で動作する。I/O は物理デバ イスやコントローラに分散されないが、ワーカー・プロセスは複数の エンジンに分散されて処理されるため、応答時間は短くなる。 • 「レンジベース・アクセス・メソッド」では、マージ・ジョイン中に、 ソートおよびマージ用に作成されたワークテーブルなどの分割され たテーブルや非分割テーブルに、インデックスを介して並列アクセ スできる。並列度を選択するときにテーブルの分割は考慮されない ので、物理デバイスやコントローラに分散されない。ワーカー・プ ロセスは複数のエンジンに分散されて処理されるため、応答時間は 短くなる。 Adaptive Server Enterprise 第8章 並列クエリ最適化 並列パーティション・スキャン 並列パーティション・スキャンでは、複数のワーカー・プロセスが、パー ティション・テーブルの各分割を完全にスキャンします。1 つの分割に対 して 1 つのワーカー・プロセスが割り当てられ、各プロセスが分割のペー ジを最初から最後まで読み込みます。図 8-1 は、並列パーティション・ス キャンを示します。 図 8-1: 並列パーティション・スキャン 分割されたテーブル ワーカー・ プロセス A 分割 1 ワーカー・ プロセス B 分割 2 ワーカー・ プロセス C 分割 3 並列パーティション・スキャンは、逐次テーブル・スキャンよりも高速に 動作します。作業は複数のワーカー・プロセスに分割され、各ワーカー・ プロセスを異なるエンジン上で同時に実行できます。他のワーカー・プロ セスがスリープしている間に、I/O または他のシステム・リソース上で実 行されるワーカー・プロセスもあります。テーブル分割が別の物理デバイ ス上にある場合でも、I/O 並列処理はできます。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 173 並列アクセス・メソッド 使用条件 オプティマイザが並列パーティション・スキャンを考慮するのは、クエリ の中の分割されたテーブルに対してだけです。テーブルのデータが分割の 数と厳密に対応していなければなりません。そうでない場合は、オプティ マイザはパーティションベースのアクセスを不適切と見なします。テーブ ル・データが分割に対応していないと見なされるのは、最大分割のサイズ が分割の平均サイズの 2 倍を超えるときです。 最後に、オプティマイザが並列アクセス・メソッドを考慮するには、最低 20 のデータ・ページにクエリがアクセスする必要があります。 コスト・モデル Adaptive Server オプティマイザは、並列テーブル・パーティション・ス キャンのコストを、スキャン中に任意の 1 つのワーカー・プロセスによっ て実行される論理 I/O と物理 I/O の最大数として計算します。言い換え ると、このアクセス・メソッドのコストは、テーブルの最大の分割に含 まれるすべてのページの読み込みに必要な I/O と等しくなります。 たとえば、3 つの分割からなるテーブルで、最初の分割に 200 ページ、2 つ目の分割に 300 ページ、最後の分割に 500 ページがあるとします。この 場合、並列スキャンを実行するためのコストは 500 論理 I/O と 500 物理 I/O となります ( 物理 I/O には 2K I/O を使用します )。これに比べて、このテー ブルの逐次スキャンのコストは 1000 論理 I/O と物理 I/O です。 並列クラスタード・インデックス・パーティション・スキャン ( 全ページロック・ テーブル ) クラスタード・インデックス・パーティション・スキャンは、クラス タード・インデックス・キーが探索引数と一致する場合に、分割された テーブルに含まれるデータ・ページをスキャンする複数のワーカー・プ ロセスを使用します。このメソッドは、全ページロック・テーブルでだ け使用できます。 テーブルの 1 つの分割に対して 1 つのワーカー・プロセスが割り当てられ ます。各ワーカー・プロセスは、プロセスがアクセスするキーの値の範囲 に応じて 2 つのメソッドのうち 1 つを使用し、分割のデータ・ページにア クセスします。分割されたテーブルにクラスタード・インデックスがある 場合、クラスタード・インデックス・キーに基づいてローがパーティショ ンに割り当てられます。 図 8-2 は、3 つの分割にわたるクラスタード・インデックス・パーティ ション・スキャンを示します。ワーカー・プロセス A、B、C が、テーブ ルの 3 つの分割にそれぞれ割り当てられています。このスキャンには 2 つ のメソッドがあります。 174 Adaptive Server Enterprise 第8章 • 並列クエリ最適化 メソッド 1 ワーカー・プロセス A はクラスタード・インデックスをスキャンし、分 割 1 の中で探索引数を満たす最初の開始ページを探す。次に、データ・ ページのスキャンを開始し、分割 1 の終端に達するまで実行する。 • メソッド 2 ワーカー・プロセス B と C は、クラスタード・インデックスを使用 せずに、それぞれに対応する分割の最初からデータ・ページをスキャ ンする。ワーカー・プロセス B は分割 2 の終端に達するとスキャン を完了する。ワーカー・プロセス C は、データ・ローが探索引数を 満たさなくなると、分割 3 の途中でスキャンを完了する。 図 8-2: 並列クラスタード・インデックス・パーティション・スキャン select avg(price) from t1 where keyvalue > 400 and keyvalue < 2700 分割されたテーブル ワーカー・ プロセス A 分割 1 分割に割り当て られる値 1 1000 ワーカー・ プロセス B 分割 2 1001 2000 ワーカー・ プロセス C 分割 3 2001 インデックス・ ページ 3000 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 175 並列アクセス・メソッド 使用条件 オプティマイザは、次の条件が満たされた場合にだけ、クラスタード・イ ンデックス・パーティション・スキャンを考慮します。 • クエリがテーブルに含まれる最低 20 のデータ・ページにアクセスす る場合。 • テーブルが分割され、テーブルの全ページがロックされている場合。 • テーブルのデータが分割の数に厳密に対応している場合。テーブル・ データが分割に対応していないと見なされるのは、最大分割のサイズ が分割の平均サイズの 2 倍以上になるとき。 コスト・モデル Adaptive Server オプティマイザは、スキャンが必要な合計ページ数に応 じて、クラスタード・インデックス・パーティション・スキャンのコス トを異なる方法で計算します。 • スキャンが必要な合計ページ数が、分割の平均サイズの 2 倍以下であ る場合、オプティマイザは、スキャンされる合計ページ数の 2 分の 1 としてスキャンのコストを計算する。 • スキャンが必要な合計ページ数が、分割の平均サイズの 2 倍より大き い場合、オプティマイザは、分割に含まれる平均ページ数としてス キャンのコストを計算する。 次の両方が満たされる場合、実際のスキャンのコストが計算よりも大きく なることがあります。 • スキャンが必要な合計ページ数が、1 つの分割のサイズよりも小さい。 • スキャンされるデータの全体が 1 つの分割内にある。 この条件が 2 つとも満たされると、実際のスキャンのコストは逐次処理で 実行された場合と同じになります。 並列ハッシュベース・テーブル・スキャン 並列ハッシュベース・テーブル・スキャンの実行方法は、テーブルの ロック・スキームによって若干異なります。 176 Adaptive Server Enterprise 第8章 並列クエリ最適化 全ページロック・テーブルのハッシュベース・テーブル・スキャン 全ページロック・テーブルのハッシュベース・テーブル・スキャンでは、 テーブルに含まれるデータ・ページからなる 1 つのチェーンを複数のワー カー・プロセスが同時にスキャンします。すべてのワーカー・プロセスは ページ・チェーンをスキャンし、各ページ ID に内部ハッシュ関数を割り 当てます。ハッシュ関数は、現在のページにあるローをどのワーカー・プ ロセスが読み込むかを決定します。ハッシュ関数により、テーブルの各 ページにあるローが、それぞれ唯一のワーカー・プロセスによってスキャ ンされることが保証されます。図 8-3 は、ハッシュベース・テーブル・ス キャンを示します。 図 8-3: 全ページロック・テーブルの並列ハッシュベース・テーブル・スキャン ワーカー・ プロセス A、B、C A がスキャンする ページ 1 つのページ・チェーン B がスキャンする ページ C がスキャンする ページ ハッシュベース・スキャンにより、データ・ページの 1 つのチェーンに対 する処理を、複数のエンジンに分散させることができます。オプティマイ ザは、このアクセス・メソッドをジョイン・クエリの外部テーブルに対し て使用することで、ジョイン条件を並列処理します。 データオンリーロック・テーブルに対するハッシュベース・テーブル・スキャン データオンリーロック・テーブルのハッシュベース・スキャンは、ペー ジ番号をハッシュするのではなく、エクステント番号またはアロケー ション・ページ番号のどちらかをハッシュします。アロケーション・ペー ジ番号、エクステント番号のどちらをハッシュするかは、オプティマイ ザがコストベースで決定します。どちらの方法を使用しても、非分割テー ブルで並列クエリを実行するコストを削減できます。全ページロック・ テーブルで逐次スキャンを選択するクエリは、そのテーブルがデータオ ンリー・ロックに変換される場合、新しいハッシュベース・スキャンの 1 つを使用します。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 177 並列アクセス・メソッド 使用条件 オプティマイザがハッシュベース・テーブル・スキャンを考慮するのは、 ヒープ・テーブルの場合と、ジョイン・クエリの外部テーブルの場合だけ です。クラスタード・インデックスや 1 つのテーブルに対するクエリの場 合は、このアクセス・メソッドは考慮されません。ハッシュベース・ス キャンは、分割されたテーブルにも、非分割テーブルにも使用できます。 オプティマイザが並列アクセス・メソッドを考慮する前に、クエリはその テーブルの最低 20 のデータ・ページにアクセスしている必要があります。 コスト・モデル オプティマイザは、ハッシュベース・テーブル・スキャンのコストを、 テーブルをスキャンするために必要な論理 I/O と物理 I/O の合計数として 計算します。 全ページロック・テーブルの場合、物理 I/O コストは、逐次テーブル・ス キャンの場合とほぼ同じです。論理コストは、読み込みページ数にワー カー・プロセス数を掛けた値です。各ワーカー・プロセスのコストは、 テーブルの各ページに対する 1 つの論理 I/O であり、およそ 1/N 物理 I/O です (N はワーカー・プロセス数 )。 データオンリーロック・テーブルの場合、物理 I/O と論理 I/O がワーカー・ プロセス間で均等に分割されるので、物理 I/O コストは逐次テーブル・ス キャンの場合とほぼ同じです。 並列ハッシュベース・インデックス・スキャン インデックス・ハッシュベース・スキャンは、ノンクラスタード・イン デックスまたはデータオンリーロック・テーブルのクラスタード・イン デックスで実行できます。次のようにスキャンを実行します。 • すべてのワーカー・プロセスは、高いインデックス・レベルをスキャ ンする。 • すべてのワーカー・プロセスは、リーフレベル・インデックス・ペー ジをスキャンする。 データオンリーロック・テーブルの場合、リーフレベルでスキャンする ワーカー・プロセスは、各ローについてページ ID をハッシュし、一致す るデータ・ページをスキャンします。 178 Adaptive Server Enterprise 第8章 並列クエリ最適化 全ページロック・テーブルの場合、ハッシュベース・インデックス・ス キャンは、テーブルがヒープ・テーブルであるか、またはテーブルがクラ スタード・インデックスを持つかどうかによって、次の 2 つの方法のどち らかで実行されます。2 つの方法の大きな違いは、ハッシュのメカニズム です。 • クラスタード・インデックスを持つテーブルの場合、ハッシュはキー 値に基づく。 • ヒープ・テーブルの場合、スキャン・ハッシュはページ ID に基づく。 図 8-4 は、ヒープ・テーブルに対する 2 つのワーカー・プロセスによるノ ンクラスタード・インデックス・ハッシュベース・スキャンを示します。 図 8-4: ノンクラスタード・インデックス・ハッシュベース・スキャン 7 WP1 WP2 インデックス・ ページ データ・ページ 両方のワーカー・ プロセスがスキャン するページ ワーカー・プロセス 1 がスキャンする ページ パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン ワーカー・プロセス 2 がスキャンする ページ 179 並列アクセス・メソッド コスト・モデルと使用条件 ノンクラスタード・インデックス・スキャンのコスト・モデルは、次の式 を使用します。 スキャンにかかるコスト = インデックス・レベルの数 + リーフ・ページ数 / IO あたりのページ数 + ( データ・ページ数 / IO あたりのページ数 ) / ワーカー・プロセス数 オプティマイザは、ノンクラスタード・インデックスとデータオンリー ロック・テーブルのクラスタード・インデックスを使うクエリ内のテー ブルに対してハッシュベース・インデックス・スキャンを考慮します。 また、クエリはテーブルに含まれる最低 20 のデータ・ページにアクセス しなければなりません。 注意 1 つのノンクラスタード・インデックスがクエリの結果をカバーする 場合、オプティマイザはノンクラスタード・インデックス・ハッシュベー ス・スキャンを考慮しません。 インデックス・カバーリングの詳細については、 『パフォーマンス&チュー ニング・ガイド:基本』の「インデックス・カバーリング」(289 ページ ) を参照してください。 並列レンジベース・スキャン 並列レンジベース・スキャンはマージ・ジョインのマージ処理に使用され ます。 2 つのテーブルが並列にマージされる場合、ワーカー・プロセスごとに マージする値の範囲が割り当てられます。この範囲は、ヒストグラムの 統計値やサンプリングを基に決定されます。少なくとも 1 つのジョイン・ カラムにヒストグラムが存在する場合、このヒストグラムを使用して、各 ワーカー・プロセスがほぼ同じ数のローで動作するように範囲を分割し ます。どのジョイン・カラムにもヒストグラムがない場合は、他の並列 ソート・オペレーションで実行されたサンプリングにならって、各ワー カー・プロセスでマージする値の範囲が決まります。 図 8-5 は、並列右マージ・ジョインを示します。この場合、次のようにな ります。 • 180 右マージ・ジョインが使用される。テーブル 1 ( 外部テーブル ) は、 スキャンされてワークテーブルに入り、さらにソートされてから内部 テーブルとマージされる。これらのワーカー・プロセスは、この手順 の最後に割り付け解除される。 Adaptive Server Enterprise 第8章 並列クエリ最適化 • 外部テーブルは 2 つの分割からなるので、並列パーティション・ス キャンを実行するには 2 つのワーカー・プロセスが使用される。 • 内部テーブルのジョイン・キーにノンクラスタード・インデックスが ある。max parallel degree を 3 に設定すると、3 つのワーカー・プロ セスが使用される。 使用条件 設定パラメータ enable merge joins を 1 に設定して、マージ・ジョイン対 象の外部テーブルから 21 ページ以上のデータ・ページにテーブルがアク セスする場合、オプティマイザは並列マージ・ジョインを考慮します。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 181 並列アクセス・メソッド 図 8-5: 並列右マージ・ジョイン data_dev1 テーブル 1: 2 つのデバイスに 分割されたテーブル 7 WP1 data_dev2 WP2 ワークテーブル 1 ソート ソート後にマージを実行 テーブル 2: ジョイン・キーの ノンクラスタード・ インデックス WP1 WP2 WP3 インデックス・ ページ ワーカー・プロセス別 ページ読み取り権限 データ・ページ 全 ワーカー・プロセス ワーカー・プロセス 1 ワーカー・プロセス 2 ワーカー・プロセス 3 182 Adaptive Server Enterprise 第8章 並列クエリ最適化 その他の並列方式 Adaptive Server は、クエリを並列で実行するときに他の方式を利用するこ とがあります。この方式には、分割されたワークテーブルと並列ソートが あります。 分割されたワークテーブル クエリがワーカー・プロセスを必要とする場合、Adaptive Server は分割され たワークテーブルを作成し、複数のワーカー・プロセスを使用してテーブ ルを移植することがあります。Adaptive Server がテーブルを移植する場合、 ワークテーブルを分割することによりパフォーマンスが向上し、そのため 全体として応答時間が短くなります。 分割ワークテーブル使用のメリットを利用できるクエリの例については、 「並列クエリの例」(194 ページ ) を参照してください。 並列ソート 並列ソートは複数のワーカー・プロセスを使用してデータを並列でソート する手法です。これは、複数のワーカー・プロセスがクエリを並列で実行 する方法と類似しています。create index など、ソートを必要とするクエ リはすべて、並列ソート使用のメリットを利用できます。 オプティマイザは、並列ソートの実行の直接的な最適化や制御は行いま せん。 並列ソートのメリットを利用できるクエリの例については、 「並列クエリ の例」(194 ページ ) を参照してください。 また、Adaptive Server が並列でソートを実行する方法の詳細については、 「並列ソート方式の概要」(212 ページ ) を参照してください。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 183 並列アクセス・メソッドのまとめ 並列アクセス・メソッドのまとめ 表 8-1 は、Adaptive Server によるクエリ処理において並列アクセス・メ ソッドが使用される可能性のある事例をまとめたものです。どのような 場合でも、オプティマイザが並列アクセス・メソッドを考慮する前に、ク エリは、テーブルに含まれる最低 20 のデータ・ページにアクセスする必 要があります。 表 8-1: 並列アクセス・メソッドのまとめ 並列メソッド 主なコストの要素 使用条件 相当する逐次メソッド パーティションベース・ 最大分割に含まれるページ数 スキャン 分割されたテーブルの データのバランスがとれ ていること 逐次テーブル・スキャ ン、逐次インデックス・ スキャン ハッシュベース・テーブ ル・スキャン 任意の外部テーブルがジョ イン・クエリ内にあり、か つそれがヒープであること 逐次テーブル・スキャ ン、逐次インデックス・ スキャン テーブルに含まれるページ数 クラスタード・インデッ スキャンされるページの合計数 <= クス・パーティション・ 平均サイズの分割に含まれるペー ジ数 * 2 である場合は、スキャンさ スキャン れる合計ページ数 / 2 分割されたテーブルに有用 逐次インデックス・ス なクラスタード・インデッ キャン クスがあること、全ページ・ ロックのみ スキャンされるページの合計数 > 平均サイズの分割に含まれるペー ジ数 * 2 である場合は、分割に含ま れる平均ページ数 ハッシュベース・イン デックス・スキャン リーフレベル以前にスキャンする インデックス・ページ数 + スキャン するリーフレベル・インデックス・ ページ数 + ( リーフレベル・イン デックス・ページ内で参照される データ・ページ数 / ワーカー・プロ セス数 ) 任意のテーブルに有用な 逐次インデックス・ス ノンクラスタード・イン キャン デックスがあること、また はデータオンリーロック・ テーブルにクラスタード・ インデックスがあること レンジベース・スキャン (2 つのテーブルでアクセスされる ページ数 / ワーカー・プロセス数 ) + ソートにかかるコスト 任意のテーブルがマージ・ 逐次マージ、ネスト ジョインを考慮するのに適 ループ・ジョイン 切なジョインにあること 並列アクセス・メソッドの選択 オプティマイザは、クエリ内にある個々のテーブルに対して、まず使用 できるインデックスと分割を評価し、テーブルのデータをスキャンする ためにどのアクセス・メソッドが使用できるかを決定します。Adaptive Server は、ジョインを含むクエリに対して、レンジベース・スキャンの マージ・ジョインを考慮し、並列クエリ処理が有効である場合に並列マー ジ・ジョインの使用を考慮します。レンジベース・スキャンはテーブル の分割には依存しないで使用されるため、クラスタード・インデックス とノンクラスタード・インデックスのどちらを使用してもレンジベース・ スキャンを実行できます。レンジベース・スキャンは、ジョイン・キー に有用なインデックスを持たないテーブルに対して使用されます。 184 Adaptive Server Enterprise 第8章 並列クエリ最適化 表 8-2 は、さまざまなテーブルとインデックスの組み合わせに応じて、オ プティマイザが選ぶ並列アクセス・メソッドを示します。ハッシュベー ス・テーブル・スキャンは、クエリ内に外部テーブルがあり、かつクエリ が parallel オプティマイザ・ヒントを使用しない場合にだけ考慮されます。 表 8-2: パーティションベースまたはハッシュベースの使用可能なアクセス・ メソッドの決定 有用なインデックスなし 分割されたテーブル 有用なクラスタード・ インデックス パーティション・スキャン。 ク ラ ス タ ー ド・イ ン ハッシュベース・テーブル・ デ ッ ク ス・パ ー テ ィ ション・スキャン スキャン ( テーブルがヒープである 場合 ) 有用なインデックス ( データオン リーロック・テーブルのノンクラス タード・インデックスまたはクラス タード・インデックス ) ノンクラスタード・インデックス・ ハッシュベース・スキャン 逐次インデックス・スキャン 逐次インデックス・ スキャン 逐次テーブル・スキャン 非分割テーブル ハッシュベース・テーブル・ 逐 次 イ ン デ ッ ク ス・ スキャン スキャン ( テーブルがヒープである 場合 ) ノンクラスタード・インデックス・ ハッシュベース・スキャン 逐次インデックス・スキャン 逐次テーブル・スキャン さらに、オプティマイザは、クエリで使用できるワーカー・プロセス数に 基づいて、並列アクセス・メソッドを考慮から外すことがあります。この 処理は、オプティマイザがクエリの全体としての並列度を計算するときに 発生します。 例については、「分割されたヒープ・テーブル」(192 ページ ) を参照して ください。 並列クエリの並列度 クエリの「並列度」とは、クエリを並列で実行するためにオプティマイ ザが選択するワーカー・プロセスの数です。並列度は、クエリの並列度 の上限と、オプティマイザが提示する並列処理のレベルとの両方に依存 します。 クエリの並列度の計算処理は、次の 2 つの理由により重要です。 • 最終的な並列度は、並列で動作するワーカー・プロセスの数を指定す るため、クエリのパフォーマンスに直接影響する。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 185 並列クエリの並列度 • 並列度を計算するときに、設定パラメータ、set コマンド、またはク エリ内の parallel 句で設定した上限値を超えるワーカー・プロセス数 が並列アクセス・メソッドで必要となる場合は、オプティマイザはそ の並列アクセス・メソッドを不適切と見なす。これにより、オプティ マイザがクエリのコストを計算するときに考慮するアクセス・メソッ ドの合計数が少なくなるため、全体的な最適化時間が減少する。この 方法でアクセス・メソッドを不適切と見なすことは、マルチテーブ ル・ジョインでは特に重要。マルチテーブル・ジョインの場合、オプ ティマイザは、ジョイン順序とアクセス・メソッドのさまざまな組み 合わせを考慮してから、最終的なクエリ・プランを選択する必要があ るためである。 上限値 システム管理者は、サーバ全体で使用する設定パラメータを使って並列 処理の上限値を設定します。セッション単位およびクエリレベルのオプ ションによって、並列処理の上限値をより小さく制限できます。これら の制限は、並列クエリで使用できるワーカー・プロセスの合計数と、ハッ シュベース・アクセス・メソッドで使用できるワーカー・プロセスの合 計数の両方を設定します。 オプティマイザは、クエリの上限値を超えるワーカー・プロセス数が必要 とされる場合、その並列アクセス・メソッドを候補から外します ( 並列度 の上限値が 1 である場合、オプティマイザはすべての並列アクセス・メ ソッドを候補から外します )。 並列度の上限を制御する設定パラメータの詳細については、 「並列設定パ ラメータの設定例」(151 ページ ) を参照してください。 最適化された並列度 オプティマイザは、サーバ、セッション、クエリのレベルで設定された 最大並列度のワーカー・プロセスを潜在的に使用できます。しかし、最 適化された並列度はこの最大値を下回ることがあります。パーティショ ンベースのスキャンの場合、オプティマイザは、クエリのテーブルに含 まれる分割の数と、設定されたワーカー・プロセス数に基づいて並列度 を選択します。 186 Adaptive Server Enterprise 第8章 並列クエリ最適化 パーティションベース・スキャンのワーカー・プロセス パーティションベースのアクセス・メソッドの場合、Adaptive Server は、 テーブル内のすべての分割について、それぞれ対応するワーカー・プロ セスを 1 つ必要とします。分割の数が max parallel degree またはセッ ションレベルやクエリレベルの上限値を超える場合、オプティマイザは ハッシュベースのアクセス・メソッドか逐次アクセス・メソッドを使用 します。マージ・ジョインが可能な場合、max parallel degree を使用し てマージ・ジョインを選択できます。 ハッシュベース・スキャンのワーカー・プロセス ハッシュベースのアクセス・メソッドの場合、オプティマイザは、最適な 並列度を計算する代わりに、max scan parallel degree パラメータで指定 されたワーカー・プロセス数を使用します。Adaptive Server システム全体 としての最適な max scan parallel degree 値の設定は、システム管理者が 行います。一般的な目安としては、このパラメータを 2 または 3 以下に設 定します。物理デバイスの I/O を有効に活用するため、システムは 2 ~ 3 のワーカー・プロセスしか使用しません。 レンジベース・スキャンのワーカー・プロセス マージ・ジョインは、複数のワーカー・プロセスを使用して、次のことを 実行します。 • ソートが必要なマージ・ジョインの場合、ローを選択してワークテー ブルに入れるためのスキャン。 • ワークテーブル・ソート。 • マージ・ジョインと、手順中のそれ以降のジョイン • フル・マージ・ジョイン中の両方のテーブルのレンジ・スキャン。 ワークテーブル作成中の使用状況 マージ・ジョインにワークテーブルが必要な場合、ワークテーブルを作成 するクエリ・ステップでは、逐次アクセス・メソッドまたは並列アクセ ス・メソッドを使用してスキャンできます。このステップのワーカー・プ ロセス数は、クエリのワーカー・プロセス数を選択する通常の方法で決定 されます。ローを選択してワークテーブルに入れるクエリは、シングル テーブル・クエリ、ネストループ・ジョインかマージ・ジョインを実行す るジョイン、ネストループ・ジョインとマージ・ジョインを組み合わせた ジョインのどれかです。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 187 並列クエリの並列度 マージ・ジョイン・ワークテーブルのための並列ソート ワークテーブル内でソートされるページ数が設定パラメータ number of sort buffer の値の 8 倍になった場合、並列ソートが使用されます。 並列ソートの詳細については、 「第 9 章 並列ソート」を参照してください。 マージ・スレッドの数 マージ・ステップでは、マージ・スレッドの数は max parallel degree に 設定されています。値の数が max parallel degree より小さい場合は例外 です。マージされる値の数が max parallel degree より小さい場合、タス クは値ごとに 1 つのワーカー・プロセスを使用します。ここで各ワーカー・ プロセスは 1 つの値をマージします。マージされるテーブルで値の数が異 なる場合、小さい方の数がワーカー・プロセスの数を決定します。計算式 は次のとおりです。 ワーカー・プロセス数 = min (max pll degree, min(t1_uniq_vals, t2_uniq_vals)) ジョイン・カラムに値が 1 つしかない場合、またはジョイン・カラムにあ る探索引数が等号を含む場合、マージ・ステップは逐次モードで実行され ます。このクエリにマージ・ジョインが使用されると、マージは逐次モー ドで実行されます。 select * from t1, t2 where t1.c1 = t2.c1 and t1.c1 = 10 マージ・ジョインでの総使用量 マージ・ジョインでは、マージに使用できる最大スレッド数は max parallel degree、ソートに使用できる最大スレッド数は max parallel degree です。 並 列 ソ ー ト を 実 行 す る マ ー ジ で 使 用 で き る 最 大 ス レ ッ ド 数 は、max parallel degree の 2 倍です。ソートに使用されるワーカー・プロセスは、 ソート完了時に解放されます。 188 Adaptive Server Enterprise 第8章 並列クエリ最適化 ネストループ・ジョイン オプティマイザは、ネストループ・ジョイン内の個々のテーブルに対し、 「最 適化された並列度」(186 ページ ) で説明した規則と同じものを使用して、並 列度を計算します。ただし、ジョイン・クエリの全体としての並列度は、 ジョイン内の個々のテーブルにアクセスするワーカー・プロセス数の「積」 になります。1 つのジョイン・クエ . リに割り付けられたすべてのワーカー・ プロセスは、ジョイン内のすべてのテーブルにアクセスします。ジョインの 並列度を扱うためにワーカー・プロセス数の積を使用することで、プロセス が各分割に等しく分散されることが保証され、ジョインが重複ローを返すこ ともなくなります。 図 8-6 では、3 つの分割からなる外部テーブルと 2 つの分割からなる内部 テーブルの 2 つのテーブルがジョイン内にある場合に、この規則が適用 される例を示します。オプティマイザが、各テーブルについてパーティ ションベースのアクセス・メソッドを使用することを決定した場合、ク エリがジョインを実行するには合計で 6 つのワーカー・プロセスが必要 となります。6 つのワーカー・プロセスはそれぞれ、外部テーブルの 1 つ の分割と内部テーブルの 1 つの分割をスキャンして、ジョイン条件を処 理します。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 189 並列クエリの並列度 図 8-6: ネストループ・ジョインにおけるワーカー・プロセスの使用 外部テーブル 分割 1 内部テーブル WP1 分割 1 WP2 分割 2 7 WP3 WP4 分割 2 WP5 分割 3 7 WP6 図 8-6 では、オプティマイザが逐次アクセス・メソッドを使用して内部 テーブルをスキャンすることを選択した場合、ジョインの実行に必要と されるワーカー・プロセスは 3 つだけです。この状況では、各ワーカー・ プロセスが外部テーブルの 1 つの分割をスキャンすると同時に、すべて のワーカー・プロセスが内部テーブルをスキャンして一致するローを探 します。 このため、それぞれスキャン度 m と n を持つ 2 つのテーブルがクエリ内 にある場合は、2 つのテーブルの間のネストループ・ジョイン並列度は、 次のいずれかになります。 190 • 1。オプティマイザが両方のテーブルに対して逐次アクセスを行う場合。 • m*1。オプティマイザが最初のテーブルについては並列アクセス・メ ソッド (m 個のワーカー・プロセスによる ) を使用し、2 番めのテー ブルについては逐次アクセスを使用する場合。 Adaptive Server Enterprise 第8章 並列クエリ最適化 • n*1。オプティマイザが 2 番目のテーブルについては並列アクセス・ メソッド (n 個のワーカー・プロセスによる ) を使用し、最初のテー ブルについては逐次アクセスを使用する場合。 • m*n。オプティマイザが両方のテーブルに並列アクセス・メソッドを 使用してアクセスする場合。 代替プラン 内部テーブルを繰り返しスキャンするとコストが大きくなるため、ジョイ ン内の両方のテーブルについてパーティションベースのスキャンが使用 されることはほとんどありません。オプティマイザが次の方式を選択する 場合もあります。 • マージ・ジョイン。 • 再フォーマット方式。再フォーマットする方がコストが小さい場合。 • パーティションベース・スキャンとハッシュベース・インデックス・ スキャンの組み合わせ。20 以上のデータ・ページからジョインがロー を返す場合。 図 7-7 (147 ページ ) を参照。 ネストループ・ジョインの並列度の計算 任意の 2 つのテーブル間のジョインについて並列度を決定するため (また、 非常に多くのワーカー・プロセスを必要とするアクセス・メソッドを不適 切と見なすため )、オプティマイザは次の規則を適用します。 1 オプティマイザは、ジョインの外部テーブルのための可能なアクセ ス・メソッドと並列度を決定します。この処理はシングルテーブル・ クエリの場合と同様です。 詳細については、「最適化された並列度」(186 ページ ) を参照してく ださい。 2 オプティマイザは、手順 1 で決定した各アクセス・メソッドについ て、ジョインの内部テーブル用に使用できる残りのワーカー・プロセ ス数を計算します。次の式によってこの数が決定されます。 残りのワーカー・プロセス数 = max parallel degree / 外部テーブル用のワーカー・プロセス数 3 オプティマイザは、残りのワーカー・プロセス数を、ジョインの内部 テーブルの可能なアクセス・メソッド数の上限値として、かつ並列度 として使用します。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 191 並列クエリの並列度 オプティマイザは、この処理をすべての可能なジョイン順とアクセス・メ ソッドに対して繰り返し、それぞれの組み合わせに対してコスト関数を適 用します。オプティマイザは、最もコストが小さくなるジョイン順とアク セス・メソッドの組み合わせを選択し、最終的な組み合わせから、ジョイ ン・クエリの全体としての並列度が計算されます。 この処理の例については、 「ネストループ・ジョイン」(189 ページ ) を参 照してください。 並列クエリと存在ジョイン Adaptive Server は、存在ジョインとして処理されるサブクエリに対して、 他の制限も加えます。これらのクエリの場合、並列度を決定するのは外 部テーブルの分割の数だけです。ワーカー・プロセスの数は、外部テー ブルの分割の数と同じになります。このようなクエリの内部テーブルに 対しては、常に逐次アクセスが行われます。この制限は、通常のジョイ ンにフラット化されるサブクエリには適用されません。 例 この項では、並列度の上限が次の種類のクエリに対してどのような影響を 与えるかを例で示します。 • 分割ヒープ・テーブル。 • 非分割ヒープ・テーブル。 • クラスタード・インデックスを持つテーブル。 分割されたヒープ・テーブル max parallel degree は 10 ワーカー・プロセスに、max scan parallel degree は 3 ワーカー・プロセスに設定されていると仮定します。 シングルテーブル・クエリ 6 つの分割からなり、有用なノンクラスタード・インデックスを持たない ヒープ・テーブルに対するシングルテーブル・クエリの場合、オプティマ イザは次のアクセス・メソッドのコストを計算します。 • 6 つのワーカー・プロセスを使用する並列パーティション・スキャン。 • 1 つのプロセスを使用する逐次テーブル・スキャン。 max parallel degree が 5 ワーカー・プロセスに設定されている場合、オプ ティマイザは、6 つの分割からなるテーブルに対してパーティション・ス キャンを考慮しません。 192 Adaptive Server Enterprise 第8章 並列クエリ最適化 ジョインを含むクエリ クエリがジョインを含む場合は、状況が変化します。max parallel degree が 10 ワーカー・プロセスに設定され、クエリがジョインを含み、かつ 6 つの分割からなるテーブルがクエリにとって外部テーブルである場合、オ プティマイザは次のアクセス・メソッドを考慮します。 • 6 つのワーカー・プロセスを使用するパーティション・スキャン。 • 3 つのワーカー・プロセスを使用するハッシュベース・テーブル・ス キャン。 • 10 つのワーカー・プロセスを使用するマージ・ジョイン。 • 1 つのプロセスを使用する逐次スキャン。 max parallel degree が 5 に設定され、max scan parallel degree が 3 に設定 されている場合、オプティマイザは次のアクセス・メソッドを考慮します。 • 3 つのワーカー・プロセスを使用するハッシュベース・テーブル・ス キャン。 • 5 つのワーカー・プロセスを使用するマージ・ジョイン。 • 1 つのプロセスを使用する逐次スキャン。 最後に、max parallel degree が 5 に設定され、max scan parallel degree が 1 に設定されている場合、オプティマイザは並列アクセス・メソッドと してマージ・ジョインだけを考慮します。 非分割ヒープ・テーブル クエリがジョインを含み、max scan parallel degree が 3 に設定され、非 分割ヒープ・テーブルがクエリにとって外部テーブルである場合、オプ ティマイザは次のアクセス・メソッドを考慮します。 • 3 つのワーカー・プロセスを使用するハッシュベース・テーブル・ス キャン。 • マージ・ジョインに 10 個のワーカー・プロセスを使用するレンジ・ スキャン。 • 1 つのプロセスを使用する逐次スキャン。 max scan parallel degree が 1 に設定されている場合は、オプティマイザ はハッシュベース・スキャンを考慮しません。 クエリの並列度を決定するその他の例については、「シングルテーブル・ スキャン」(195 ページ ) を参照してください。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 193 並列クエリの例 クラスタード・インデックスを持つテーブル オプティマイザは、テーブルが全ページ・ロックを使用する場合に、クラ スタード・インデックスを持つテーブルについて次の並列アクセス・メ ソッドを考慮します。 • 並列パーティション・スキャンまたは並列クラスタード・インデック ス・スキャン ( テーブルが分割され、max parallel degree が 6 以上に 設定されている場合 )。 • max parallel degree のワーカー・プロセスを使用するレンジ・ス キャン。 • 逐次スキャン。 テーブルがデータオンリー・ロックを使用する場合、オプティマイザは次 のことを考慮します。 • 並列パーティション・スキャン ( テーブルが分割され、max parallel degree が 6 以上に設定されている場合 )。 • max parallel degree のワーカー・プロセスを使用するレンジ・ス キャン。 • 逐次スキャン。 ワーカー・プロセスに対する実行時調整 オプティマイザが全体としてクエリの並列度を決定した後でも、Adaptive Server が実行時に最終的な調整を行い、実際に使用できるワーカー・プロ セスの数に合わせて並列度を補正することがあります。実行時に使用でき るワーカー・プロセス数がオプティマイザの提示した値を下回る場合、並 列度は、使用できるワーカー・プロセス数および最終クエリ・プランのア クセス・メソッド数と整合するように減らされます。並列度の実行時調整 の処理と、どのような場合にこうした調整が行われるかについては、 「ワー カー・プロセスの実行時調整」(202 ページ ) を参照してください。 並列クエリの例 以降の項では、Adaptive Server が次の種類の並列クエリを最適化する方法 を説明し、その例を示します。 194 • シングルテーブル・スキャン • マルチテーブル・ジョイン • サブクエリ • ワークテーブルを必要とするクエリ Adaptive Server Enterprise 第8章 • union クエリ • 集約を伴うクエリ • select into 文 並列クエリ最適化 データに対して挿入、削除、更新を行うコマンドや、カーソル内から実行 されるコマンドは、並列クエリ最適化では考慮されません。 シングルテーブル・スキャン 並列クエリ最適化の最も単純な例として、シングル・ベース・テーブルに アクセスするクエリがあります。Adaptive Server はベース・テーブルを評 価することでこれらのクエリを最適化し、適用できるアクセス・メソッド を決定し、その上でコスト関数を適用して最も低コストのプランを選択し ます。 Adaptive Server がシングルテーブル・クエリを最適化する方法を理解する ことは、より複雑な並列クエリを理解するために不可欠です。マルチテー ブル・ジョインやサブクエリなどのクエリは補足的な最適化方式を使用し ますが、これらのクエリの場合でも、個々のテーブルにアクセスする処理 は同じです。 次に、オプティマイザがシングルテーブル・クエリに対して並列アクセス を使用する例を示します。 テーブル・パーティション・スキャン この例では、オプティマイザが逐次テーブル・スキャンを使わないで、 テーブル・パーティション・スキャンを選択するクエリを示します。設定 とテーブル・レイアウトは次のとおりです。 設定パラメータの値 パラメータ max parallel degree 設定値 max scan parallel degree 2 ワーカー・プロセス 10 ワーカー・プロセス テーブル・レイアウト テーブル名 authors 有用なインデックス なし パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 分割数 5 ページ数 分割 1:50 ページ 分割 2:70 ページ 分割 3:90 ページ 分割 4:80 ページ 分割 5:10 ページ 195 並列クエリの例 クエリの例は次のとおりです。 select * from authors where au_lname < "L" 表 8-2 (185 ページ ) の論理に従って、オプティマイザは次のアクセス・メ ソッドについて考慮します。 • パーティション・スキャン。 • 逐次テーブル・スキャン オプティマイザがテーブルのスキャンにハッシュベース・テーブル・ス キャンを使用しないのは、分割に含まれるページ数のバランスがとれて いて、テーブルの並列度の上限値 (10) がパーティションベース・スキャ ンにとって十分大きいためです。 オプティマイザは、各アクセス・メソッドのコストを次のように計算します。 テーブル・パーティション・スキャンのコスト = 最大分割に含まれるページ数 = 90 ページ 逐次テーブル・スキャンのコスト = テーブルに含まれるページ数 = 300 ページ オプティマイザはテーブル・パーティション・スキャンを 90 物理 I/O と 90 論理 I/O のコストで実行することを選択します。これは、テーブルが 5 つの分割からなり、オプティマイザが 5 つのワーカー・プロセスを使用す ることを選択するためです。このクエリ最適化の最終的な showplan 出力 は次のとおりです。 QUERY PLAN FOR STATEMENT 1 (at line 1). Executed in parallel by coordinating process and 5 worker processes. STEP 1 The type of query is SELECT. Executed in parallel by coordinating process and 5 worker processes. FROM TABLE authors Nested iteration. Table Scan. Forward scan. Positioning at start of table. Executed in parallel with a 5-way partition scan. Using I/O Size 16 Kbytes for data pages. With LRU Buffer Replacement Strategy for data pages. Parallel network buffer merge. 196 Adaptive Server Enterprise 第8章 並列クエリ最適化 マルチテーブル・ジョイン ジョインを最適化するときに、オプティマイザは、テーブルと妥当なアク セス・メソッドのすべての組み合わせを想定して最適なジョイン順を考慮 します。オプティマイザは、異なる方式を使用して、内部および外部テー ブルのアクセス・メソッドとジョイン・クエリ全体の並列度を選択します。 逐次処理と同様に、オプティマイザは、特定のテーブルにアクセスする ためのさまざまな代替方法を比較検討します。オプティマイザは、並列 実行のコストとジョイン・クエリに影響を与えるその他の要素のコスト のバランスを考慮します。その他の要素は、クラスタード・インデック スの存在、ネストループ・ジョインまたはマージ・ジョインの使用、内 部テーブルの再フォーマットの可能性、ジョイン順、I/O 方式、キャッ シュ方式などです。次の項では、並列アクセス・メソッドと逐次アクセ ス・メソッドの選択だけに焦点をあてて説明します。 並列ジョインの最適化とジョイン順 この例では、並列実行に適したジョイン・クエリのクエリ・プランをオプ ティマイザが作成する方法を示します。設定とテーブル・レイアウトは次 のとおりです。 設定パラメータの値 パラメータ max parallel degree 設定値 max scan parallel degree 3 ワーカー・プロセス 15 ワーカー・プロセス テーブル・レイアウト テーブル名 publishers titles 分割数 1 ( 分割されていない 場合 ) 10 ページ数 1,000 ロー数 80,000 10,000 ( 分割に対して 均一に分散 ) 800,000 次のクエリの例では、上記の 2 つのテーブル間で簡単なジョインが実行さ れます。 select * from publishers, titles where publishers.pub_id = titles.pub_id パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 197 並列クエリの例 論理上は、オプティマイザは次の可能な組み合わせのコストをすべて考慮 します。 • 外部テーブルとしての titles、内部テーブルとしての publishers、並列 アクセスする titles。 • 外部テーブルとしての titles、内部テーブルとしての publishers、逐次 アクセスする titles。 • 外部テーブルとしての publishers、内部テーブルとしての titles、並列 アクセスする titles。 • 外部テーブルとしての publishers、内部テーブルとしての titles、逐次 アクセスする titles。 • 外部テーブルとしての publishers、内部テーブルとしての titles、並列 アクセスする publishers。 たとえば、titles を外部テーブルとして使用し、そのテーブルに並列アク セスする場合のジョイン順のコストは、次のように計算されます。 publishers を外部テーブルとして使用する場合のコストは、次のように計 算されます。 ただし、ジョイン順の決定においては、特定のテーブルが並列アクセスに 適しているかどうかを判断することよりも他の要素が重要になることが よくあります。 シナリオ A:publishers にクラスタード・インデックスがある場合 一般に、有用なクラスタード・インデックスがあるかどうかがオプティマ イザでジョイン・クエリのクエリ・プランを作成するときの重要な要素と なります。publishers の pub_id にクラスタード・インデックスがあり、 titles に有用なインデックスがない場合、オプティマイザはインデックス・ テーブルである publishers を内部テーブルとして選択できます。このジョ イン順では、内部テーブルにアクセスするごとにわずかな読み取りを行う だけでローを探すことができます。 publishers を内部テーブルとして使用する場合、オプティマイザは各テー ブルに適したアクセス・メソッドのコストを考慮します。外部テーブルの titles では、次のスキャンが考慮されます。 • 並列パーティション・スキャン ( コストは最大分割内のページ数に基 づく ) • 逐次テーブル・スキャン ( コストはテーブル内のページ数に基づく ) 内部テーブルの publishers の場合、オプティマイザは逐次クラスタード・ インデックス・スキャンのみを考慮します。 また、マージ・ジョイン ( 右マージ・ジョインまたは左マージ・ジョイン ) を実行して、titles に基づくワークテーブルを titles での順序にソートするこ とも考慮されます。 198 Adaptive Server Enterprise 第8章 並列クエリ最適化 クエリの最終的なコストは、titles に並列アクセスするコストを publishers 上のクラスタード・インデックスのアクセス数で整数倍したものです。 シナリオ B:titles にクラスタード・インデックスがある場合 titles の pub_id にクラスタード・インデックスがあり、publishers に有用 なインデックスがない場合、オプティマイザはクエリで titles を内部テー ブルとして選択できます。 ジョイン順が決定されると、オプティマイザは各テーブルに適したアクセ ス・メソッドのコストを考慮します。外部テーブルの publishers では、次 のスキャンが考慮されます。 • ハッシュベース・テーブル・スキャン ( 初期コストは逐次テーブル・ スキャンの場合と同じ ) 内部テーブルの titles の場合、オプティマイザは逐次クラスタード・イン デックス・スキャンのみを考慮します。 このシナリオでは、オプティマイザは publishers の逐次実行ではなく並列 実行を選択します。ハッシュベース・テーブル・スキャンは、逐次スキャ ンの場合とコストが同じですが、処理時間は 3 分の 1 になります。各ワー カー・プロセスは、内部テーブルのクラスタード・インデックスを同時に スキャンできるからです。 シナリオ C:いずれのテーブルにも有用なインデックスがない場合 いずれのテーブルにも有用なインデックスがない場合は、マージ・ジョイ ンがアクセス・メソッドの有力な選択肢になります。マージ・ジョインが 無効になっている場合は、ジョイン順での可能な並列アクセスよりも、テー ブル・サイズと使用可能なキャッシュ領域の方が重要な要素になります。 内部テーブルとして小さいテーブルを使用する方が、1 つの並列アクセス・ メソッドよりもメリットが大きくなります。オプティマイザは、publishers テーブルを内部テーブルとして選択します。このテーブルが 1 回だけ読み 込んでキャッシュに保存するには十分な大きさであり、コストのかかる物 理 I/O を減らすことができるからです。 次に、オプティマイザは、各テーブルに適したアクセス・メソッドのコス トを考慮します。 外部テーブルの titles では、 次のスキャンが考慮されます。 • 並列パーティション・スキャン ( コストは最大分割内のページ数に基 づく ) • 逐次テーブル・スキャン ( コストはテーブル内のページ数に基づく ) 内部テーブルの publishers の場合は、逐次テーブル・スキャンをキャッ シュにロードすることだけが考慮されます。 オプティマイザは、titles への並列アクセスを選択します。クエリのコス トが 10 分の 1 に減るからです。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 199 並列クエリの例 いずれのテーブルにも有用なインデックスがない場合、オプティマイザは、 内部テーブルを繰り返しスキャンするのではなく、再フォーマット方式を 選択してテンポラリ・テーブルとクラスタード・インデックスを作成する こともあります。 サブクエリ クエリにサブクエリがある場合、Adaptive Server は、さまざまなアクセス・ メソッドを使用してサブクエリの処理コストを減らします。並列最適化は、 サブクエリのタイプとアクセス・メソッドに依存します。 • 実体化されたサブクエリ - 並列クエリ・メソッドは、実体化の手順 には考慮されない。 • フラット化されたサブクエリ - 並列クエリ最適化は、サブクエリが 通常のジョインにフラット化される場合にだけ考慮される。並列クエ リ最適化は、存在ジョインや他のフラット化方式に対しては考慮され ない。 • ネストされたサブクエリ - 並列アクセス・メソッドは、サブクエリ を含むクエリの最も外側にあるクエリ・ブロックに対してだけ考慮さ れる。内部にあるネストされたクエリは、常に逐次で実行される。オ プティマイザが並列アクセス・メソッドを考慮するのは、サブクエリ の最も外側にあるクエリ・ブロックに対してだけである。しかし、外 部クエリ・ブロックにアクセスするすべてのワーカー・プロセスも、 ネストされたサブクエリの内部テーブルにアクセスする。 各ワーカー・プロセスは、内部のネストされたクエリ・ブロックに逐 次でアクセスします。サブクエリは外部テーブル内の各ローにつき 1 回実行されるが、各ワーカー・プロセスは実行される作業の 5 分の 1 を行うだけである。サブクエリの showplan 出力はネストされたクエ リが「5 つのワーカー・プロセスによって実行される」ことを示す。 これは、外部クエリ・ブロック内で使用される各ワーカー・プロセス が内部クエリ・ブロック内で指定されたテーブルをスキャンするため である。 各ワーカー・プロセスはサブクエリの結果を個別のキャッシュに格納 している。このため、サブクエリの実行回数は逐次処理よりもわずか に多くなる。 200 Adaptive Server Enterprise 第8章 並列クエリ最適化 ワークテーブルを必要とするクエリ ワークテーブルを必要とする並列クエリは、分割されたワークテーブルを 作成し、それらのワークテーブルを並列に移植します。クエリがソートを 必要とする場合、並列ソート・マネージャは、逐次ソートを使用するか並 列ソートを使用するかを決定します。 並列ソートの詳細については、 「第 9 章 並列ソート」を参照してください。 union クエリ オプティマイザは、union クエリの各部分に対して別々に並列アクセス・ メソッドを考慮します。union クエリ内の各 select は別々に最適化される ので、あるクエリは並列プランを、別のクエリは逐次プランを、さらに別 のクエリは異なるワーカー・プロセス数での並列プランを使用できます。 union クエリがワークテーブルを必要とする場合は、ワークテーブルも ワーカー・プロセスによって分割され、並列に移植されます。 union クエリが重複ローを返さないように設定している場合、並列ソート は内部ワークテーブル上で実行され、重複ローは削除されます。 並列ソートの詳細については、 「第 9 章 並列ソート」を参照してください。 集約を伴うクエリ Adaptive Server は、集約結果を返すクエリに対して、他のクエリの場合 と同様の方法で、並列アクセス・メソッドを考慮します。group by 句を 使ってグループ化された集約結果を返すクエリの場合にも、Adaptive Server は、クラスタード・インデックスを持つ複数のワークテーブルを 作成します。この場合は、クエリを実行する各ワーカー・プロセスに対 して 1 つのワークテーブルが作成されます。各ワーカー・プロセスは、 部分集約結果を指定のワークテーブルに格納します。ワーカー・プロセ スは、部分結果の計算が終了した時点で、それらの結果を共通ワークテー ブルとしてマージします。すべてのワーカー・プロセスが部分結果をマー ジし終えると、そのクエリに対応する、最終的にグループ化された集約 結果セットが共通ワークテーブルに保持されます。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 201 ワーカー・プロセスの実行時調整 select into 文 select into コマンドは、クエリの結果セットを格納するための新しいテー ブルを作成します。Adaptive Server は、通常のクエリと同じ方法で select into コマンドのベース・クエリ部分を最適化します。その際に、並列アク セス・メソッドと逐次アクセス・メソッドの両方が考慮されます。並列で 実行される select into 文は、次のように処理されます。 1 select into 文で指定されたカラムを使用して、新しいテーブルを作成 します。 2 新しいテーブルで n 個の分割を作成します。n はオプティマイザが選 択するクエリ全体の並列度です。 3 n 個のワーカー・プロセスを使用して、クエリの結果と共に新しい テーブルを移植します。 4 新しいテーブルの分割を解除します。 select into 文を並列で実行する場合は、それを逐次クエリ・プランで実行 する場合よりも多くの手順が必要になります。このため、並列 select into 文の実行は、逐次 select into 文の場合の 2 トランザクションではなく、4 つの不連続トランザクションを使用して行われます。この変更がデータ ベースのリカバリ処理に与える影響については、『Adaptive ServerASE リ ファレンス・マニュアル』の select の項を参照してください。 ワーカー・プロセスの実行時調整 showplan の出力には、クエリの最適化プランが記述されています。最適 化されたクエリ・プランは、クエリのコンパイル時にオプティマイザが提 示するアクセス・メソッドと並列度を指定します。実行時に使用できる ワーカー・プロセス数が、最適化されたクエリ・プランで必要なワーカー・ プロセス数よりも少ないことがあります。これは次の場合に起こります。 • 最適化されたクエリ・プランのために使用できる十分なワーカー・プ ロセスがない場合。 • クエリがコンパイルされてから、クエリに対応するサーバレベルまた はセッションレベルの上限値が縮小された場合。これは、ストアド・ プロシージャの内部からクエリが実行された場合に起こる。 Adaptive Server は、このような状況の場合、使用できるワーカー・プロセ スに見合うようにクエリ・プランを調整します。 「調整クエリ・プラン」 は実行時に生成され、使用できるワーカー・プロセスの不足を補います。 調整クエリ・プランは、最適化されたクエリ・プランよりも少ないワー カー・プロセスしか使用しないことがあり、また、1 つ以上のテーブルに ついて並列アクセスの代わりに逐次アクセスを使用することもあります。 202 Adaptive Server Enterprise 第8章 並列クエリ最適化 調整クエリ・プランの応答時間は、最適化されたプランに比べて非常に長 くなる場合があります。Adaptive Server は、次のオプションと情報を提供 します。 • set オプションである process_limit_action により、実行時調整を許 可するかどうかを制御できる。 • sp_sysmon 出力の中で、実行時調整についての情報を提供する。 Adaptive Server によるクエリ・プランの調整方法 Adaptive Server は、必要なワーカー・プロセスの数を減らすため、2 つの 基本的な規則を使用します。 1 最適化されたクエリ・プランがテーブルに対してパーティションベー スのアクセス・メソッドを指定し、各分割をスキャンするために使用 できるプロセス数が足りない場合、調整プランは逐次アクセス・メ ソッドを使用します。 2 最適化されたクエリ・プランがテーブルに対してハッシュベースのア クセス・メソッドを指定し、最適化された並列度を扱う十分なプロセ ス数がない場合、調整プランは使用できるワーカー・プロセスと整合 するレベルまで並列度を減少させます。 最初の規則の例を示すために、最適化されたクエリ・プランが、テーブル の 5 つの分割についてパーティションベースのテーブル・スキャンを行う ことを推奨していると仮定します。クエリが実行される時点で、実際には 4 つのワーカー・プロセスしか使用できない場合、Adaptive Server は、1 つのプロセスを使用してテーブルに逐次アクセスを行うように調整クエ リ・プランを作成します。 2 番目の規則の例として、最適化されたクエリ・プランが、ハッシュベー ス・アクセス・メソッドと 5 つのワーカー・プロセスでテーブルをスキャ ンすることを推奨していると仮定します。この場合、調整クエリ・プラン はハッシュベース・アクセス・メソッドを使用しますが、最大 4 つのワー カー・プロセスしか使用しません。 実行時調整の効果に対する評価 一般的に、最適化されたクエリ・プランは調整クエリ・プランよりもパ フォーマンスが優れています。しかし、パフォーマンスの違いは常に大き くなるわけではありません。パフォーマンスに対する最終的な効果は、調 整プランで Adaptive Server が使用するワーカー・プロセスの数と、並列メ ソッドの代わりに逐次アクセス・メソッドが使用されるかどうかに依存し ます。当然、パフォーマンスが最も低下するのは、Adaptive Server が並列 アクセス・メソッドの代わりに逐次アクセス・メソッドを使用してクエリ を実行する場合です。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 203 ワーカー・プロセスの実行時調整 複数テーブルのジョイン・クエリのパフォーマンスも、調整クエリ・プラ ンによって大きな影響を受けます。これは、Adaptive Server が調整クエ リ・プランを作成する場合にジョイン順を変更しないためです。調整クエ リ・プランが逐次で実行されると、クエリの潜在的なパフォーマンスは最 適化された逐次ジョインよりも遅くなります。これは、クエリのために最 適化された並列ジョイン順が、最適化された逐次ジョイン順と異なるため に発生します。 実行時調整の識別と管理 Adaptive Server は、クエリ・プランの実行時調整の監視に役立つ 2 つのメ カニズムを備えています。 • set process_limit_action により、実行時調整が行われる場合または警告 が出力される場合に、バッチ処理やプロシージャをアボートできる。 • showplan は、実行時調整が行われる場合に調整クエリ・プランを出 力し、showplan を有効にする。 set process_limit_action の使用 set コマンドに process_limit_action オプションを指定すると、セッショ ン・レベルまたはストアド・プロシージャ・レベルで調整クエリ・プラン の使用をモニタできます。process_limit_action を “abort” に設定すると、 Adaptive Server は、調整クエリ・プランが必要になった場合にエラー 11015 を記録してクエリをアボートします。process_limit_action を “warning” に 設定すると、Adaptive Server はエラー 11014 を記録しますが、クエリは実 行されます。 たとえば、次のコマンドは、クエリが実行時に調整される場合にバッチ処 理をアボートします。 set process_limit_action abort エラー 11014 とエラー 11015 がエラー・ログに記録されているかどうかを 調べると、Adaptive Server が最適化されたクエリ・プランの代わりに調整 クエリ・プランを使用した程度を確認できます。制限を解除して実行時調 整を可能にするには、次のコマンドを使用します。 set process_limit_action quiet process_limit_action の詳細については、 『Adaptive ServerASE リファレン ス・マニュアル』の set の項を参照してください。 204 Adaptive Server Enterprise 第8章 並列クエリ最適化 showplan の使用 showplan を使用すると、Adaptive Server はそのクエリに対する最適化プ ランを表示してから、クエリを実行します。クエリ・プランに並列処理が 含まれ、実行時調整が行われる場合は、showplan は次のメッセージに続 けて調整クエリ・プランを表示します。 AN ADJUSTED QUERY PLAN WILL BE USED FOR STATEMENT 1 BECAUSE NOT ENOUGH WORKER PROCESSES ARE AVAILABLE AT THIS TIME. set noexec が有効である場合、Adaptive Server はクエリを実行しません。 そのため、このオプションを使用すると実行時プランは表示されません。 実行時調整の発生回数の削減 実行時調整の数を減らすには、並列クエリに使用できるワーカー・プロ セス数を増やしてください。これは、より多くの合計ワーカー・プロセ ス数をシステムに追加するか、重要でないクエリに対する並列処理の実 行を制限または削除することで可能になります。次のいずれかの方法を 使います。 • set parallel_degree か set scan_parallel_degree ( またはその両方 ) を 使用し、並列度にセッションレベルの制限を設定する。 • クエリレベルの parallel 1 句と parallel N 句を使用し、各文によるワー カー・プロセスの使用を制限する。 システム・プロシージャについて実行時調整の数を減らす場合は、サー バ・レベルまたはセッション・レベルの並列度を変更してから、プロシー ジャを再コンパイルします。詳細については、 『Adaptive ServerASE リファ レンス・マニュアル』の sp_recompile の項を参照してください。 sp_sysmon による実行時調整の検査 sp_sysmon は、ワーカー・プロセスの不足のために拒否されたワーカー・ プロセス要求の回数と、クエリについて推奨されたワーカー・プロセス数 がより小さい数に調整された回数を示します。レポートの項で示される情 報は次のとおりです。 • 『パフォーマンス&チューニング・ガイド:モニタリングと分析』の 「ワーカー・プロセス管理」(28 ページ ) では、要求および拒否された ワーカー・プロセス要求の回数と、ワーカー・プロセス用のメモリ要 求の成功および失敗の出力について説明する。 • 『パフォーマンス&チューニング・ガイド:モニタリングと分析』の 「並列クエリ管理」(30 ページ ) では、実行時調整の回数と並列クエリ のロック回数に関してレポートする sp_sysmon 出力について説明す る。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 205 並列処理のパフォーマンスの問題に対する診断 プールにあるワーカー・プロセスの数が不十分で、問題が発生すると思 われる場合は、使用されるワーカー・プロセス数と設定上のワーカー・プ ロセス数を比較します。使用される最大ワーカー・プロセス数が number of worker processes の設定値と等しく、拒否されたワーカー・プロセス 要求の割合が 80 パーセントを超える場合は、 number of worker processes の値を大きくして sp_sysmon を再実行します。使用されるワーカー・プ ロセス数が number of worker processes の設定値より少なく、拒否され たワーカー・スレッド要求の割合が 0 パーセントである場合は、メモリ・ リソースを解放するために number of worker processes の値を小さくし ます。 並列処理のパフォーマンスの問題に対する診断 以降の項では、並列クエリに対するトラブルシューティングのガイドライ ンを示します。次の 2 つの状況について説明します。 • 並列実行が予想されたクエリが、逐次で実行される場合。 • クエリは並列実行されたが、予想どおりのパフォーマンスが得られな い場合。 クエリが並列実行されない場合 クエリが並列で実行されない場合は、次の原因が考えられます。 206 • 設定パラメータ max parallel degree が 1 に設定されているか、また はセッションレベル設定 set parallel_degree が 1 になっているため、 並列アクセスが実行されない。 • 設定パラメータ max scan parallel degree が 1 に設定されているか、 またはセッションレベル設定 set scan_parallel_degree が 1 になって いるため、ハッシュベース並列アクセスが実行されない。 • 実行時のワーカー・スレッド数が不足している。 「ワーカー・プロセ スに対する実行時調整」(194 ページ ) で説明したツールを使用して、 実行時調整を検査する。 • スキャンのスコープが 20 データ・ページ未満になっている。(parallel) 句によってバイパスされる可能性がある。 • プランがテーブル・スキャンを呼び出し、かつ次の条件のいずれかに 該当している。 • テーブルがヒープではない。 • テーブルが分割されていない。 Adaptive Server Enterprise 第8章 並列クエリ最適化 • 分割のバランスが取れていない。 • テーブルがヒープであり、外部テーブルのジョインではない。 最後の 2 つの条件は (parallel) 句によってバイパスされる。 • プランがクラスタード・インデックス・スキャンを呼び出し、かつ次 の条件のいずれかに該当している。 • テーブルが分割されていない。 • 分割のバランスが取れていない。(parallel) 句によってバイパスさ れる可能性がある。 • プランがノンクラスタード・インデックス・スキャンを呼び出し、選 択されたインデックスが必要なカラムをカバーしている。 • テーブルが一時テーブルまたはシステム・テーブルである。 • テーブルが外部ジョインの内側のテーブルである。 • Resource Governor を介して制限が設定されていて、すべての並列プラ ンが合計作業量を超えている。 • 並列化できないクエリである。insert コマンド、update コマンド、delete コマンド、ネストされた ( 最も外側ではない ) クエリ、カーソルなど。 期待どおりの並列処理パフォーマンスが得られない場合 次の原因が考えられます。 • 基本となる物理デバイスに対応する分割の数が多すぎる。 • コントローラあたりのデバイス数が多すぎる。 • (parallel) 句が不適切に使用されている。 • max scan parallel degree の設定値が高すぎる ( 推奨値は 2 ~ 3)。 サポート・センタへの診断依頼 上記のヒントを使っても診断ができない場合は、Sybase 製品の保守契約を 結んでいるサポート・センタで問題の原因を特定します。その場合は、次 の情報が必要です。 • テーブルとインデックス・スキーマ。create table 文、alter table...partition 文、create index 文が最も役立つ。create コマンドと alter コマンドが実際に使用できない場合は、sp_help からの出力も 役立つ。 • クエリ。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 207 並列クエリのリソース制限 • • 次のコマンドで実行するクエリの出力。 • dbcc traceon(3604.302, 310) • set showplan on • set noexec on クエリの statistics io 出力。 並列クエリのリソース制限 Adaptive Server に並列クエリ処理を設定している場合、I/O コスト制限の トラッキング精度は、非分割テーブルよりも分割されたテーブルの方が低 くなります。 分割されたテーブルに対してクエリを実行する場合、クエリを処理するた めの作業がすべて、分割の間で振り分けられます。たとえば、3 つの分割 からなるテーブルに対してクエリを実行すると、クエリの作業は 3 つの ワーカー・プロセスの間で分割されます。ユーザが I/O リソースの上限値 を 6000 に指定した場合、オプティマイザは各ワーカー・プロセスに対し て上限値 2000 を割り当てます。 しかし、2 つのスレッドが正確に同じ量の作業を実行することは保証され ないため、並列プロセッサは、各ワーカー・プロセスに対して正確に作 業を振り分けることはできません。実際にはエラーが発生していないに もかかわらず、showplan または statistics io の出力によって、I/O リソー スの制限値を超えたことを示すエラー・メッセージが表示される場合が あります。これとは逆に、分割では制限値をわずかに超えているのに、制 限が有効にならない場合もあります。 リソース制限の設定の詳細については、 『システム管理ガイド』を参照し てください。 208 Adaptive Server Enterprise 第 9 章 並列ソート この章では、並列ソートを実行するコマンドのパフォーマンスを向上させ るためにサーバを設定する方法について説明します。 データをソートする処理は、データベース管理システムにとって必要不可 欠な部分です。ソートは、インデックスを作成し、複雑なクエリを処理す るために実行します。Adaptive Server 並列ソート・マネージャでは、パ フォーマンスに優れた並列メソッドを使用してデータ・ローをソートでき ます。内部ソートを必要とするすべての Transact-SQL コマンドは、並列 ソートのメリットを利用できます。 並列ソートの動作方法と、並列ソートのパフォーマンスに影響する要因 についても説明します。並列ソートによって高いパフォーマンスを得る ために、また、並列ソートのリソース動作条件が他のリソース要求の干 渉を受けないためにも、上記のことを理解する必要があります。 トピック名 並列ソートのメリットを利用するコマンド ページ 209 稼働条件とリソースの概要 210 並列ソート方式の概要 212 並列ソート用のリソース設定 215 リカバリについて 228 ソート動作の監視およびチューニング用のツール 229 sp_sysmon を使用したインデックス作成のチューニング 234 並列ソートのメリットを利用するコマンド データ・ロー・ソートを必要とする Transact-SQL コマンドでは、並列ソー トのメリットを利用できます。以下にこれらのコマンドを示します。 • インデックス、ユニーク・キー、プライマリ・キーを構築する create index コマンドと alter table...add constraint コマンド • order by 句を使用するクエリ • distinct を使用するクエリ • ソートに必要なマージ・ジョインを実行するクエリ パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 209 稼働条件とリソースの概要 • • union を使用するクエリ (union all を除く ) 「再フォーマット方式」を使用するクエリ これ以外に、上記のコマンドを使用するカーソルでも並列ソートのメリッ トを利用できます。 稼働条件とリソースの概要 並列クエリ処理と同様に、並列ソートの場合にも、同じコマンドを逐次 実行した場合に比べて必要なリソースの量は大きくなります。インデッ クスを作成したり、クエリの結果をソートしたりする応答時間は短くな りますが、オーバヘッドがあるためにサーバが必要とする作業量は大き くなります。 Adaptive Server のソート・マネージャは、ソート・オペレーションを並 列実行するために必要なだけのリソースが使用できるかどうかを判断し ます。また、テーブル・サイズなどの要素を基にして、逐次ソートまた は並列ソートの実行を決定します。並列ソートを実行するには、次の基 準を満たしていなければなりません。 • • 210 ターゲット・データベースに sp_dboption で select into/bulk copy/pllsort データベース・オプションが true に設定されている。 • インデックスの場合は、テーブルが存在するデータベース内でこ のオプションを有効にする。分割されたテーブルにクラスター ド・インデックスを作成する場合は、このオプションを有効にし ないとソートが失敗する。他のインデックスを作成する場合は、 並列ソートが実行できないときに逐次ソートを実行できる。 • ワークテーブルをソートする場合は、tempdb 内でこのオプショ ンを有効にする。並列ソートが実行できないときに逐次ソートを 実行できる。 並列ソートでは、最小限の数のワーカー・プロセスが使用可能でなけ ればならない。この数は、テーブルを分割する数かターゲット・セグ メントのデバイス数 ( またはその両方 ) に依存する。サーバ・レベル およびセッション・レベルの並列度は、並列ソートに必要な最小ワー カー・プロセス数を使用できるだけの大きさを必要とする。分割され たテーブルのクラスタード・インデックスは、並列で作成されなけれ ばならない。十分な数のワーカー・プロセスが使用できない場合は、 他のソートを逐次実行できる。詳細については、 「並列ソート中のワー カー・プロセスの稼働条件」(216 ページ ) と「select クエリ・ソート 時のワーカー・プロセスの動作条件」(219 ページ ) を参照。 Adaptive Server Enterprise 第9章 • 並列ソート ソートが必要な select コマンドの場合とノンクラスタード・イン デックスを作成する場合、ソートされるテーブルは最低でも使用可 能なソート・バッファ・サイズ (number of sort buffers 設定パラ メータの値 ) の 8 倍のサイズでなければならない。それ以下のサイ ズでは、ソートは逐次モードで実行される。このため、Adaptive Server は、大きなパフォーマンスの向上が期待できない小さなテー ブルに対して、並列ソートを実行することはない。この規則は、分 割されたテーブルにクラスタード・インデックスを作成する場合に は適用されない ( この操作が常に並列ソートを必要とするため )。 詳細については、「ソート・バッファ設定のガイドライン」(221 ペー ジ ) を参照。 • create index コマンドの場合、number of sort buffers 設定パラメータ の値は、最低でも並列ソートで使用できるワーカー・プロセス数と同 じ大きさでなければならない。 詳細については、「ソート・バッファ設定のガイドライン」(221 ペー ジ ) を参照。 注意 dump transaction コマンドは、並列ソートを使用してインデッ クスを作成した後では使用できません。必ず、データベースをダンプ してください。逐次実行される create index コマンドでもリカバリは 可能です。しかし、インデックス作成コマンドが完全に再実行される ため、このリカバリには非常に時間がかかることがあります。リカバ リを高速化するため、インデックス作成を逐次実行してから、データ ベース・ダンプを実行することをおすすめします。ただし、dump transaction を使用するうえで必須ではありません。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 211 並列ソート方式の概要 並列ソート方式の概要 Adaptive Server オプティマイザと同様に、Adaptive Server 並列ソート・マ ネージャは、使用できるワーカー・プロセスや入力テーブルなどの他のリ ソースを分析して、ソートに使用するワーカー・プロセス数を決定します。 使用するワーカー・プロセス数を決定してから、Adaptive Server で並列 ソートを実行します。並列ソートを実行するプロセスは、ソートを必要と する create index コマンドやクエリと同様です。Adaptive Server は、次の 手順に従って並列ソートを実行します。 1 分散マップを作成します。ジョイン・カラム上の統計値をマージ・ ジョインする場合は、ヒストグラムの統計値を分散マップに使用し ます。その他の場合は、入力テーブルのデータをサンプリングして 分散マップを構築します。 2 テーブル・データを読み込み、分散マップの決定に従って、キー値を ソート・バッファのセットに動的に分散します。 3 それぞれの個別のキー値の範囲をソートし、サブインデックスを作成 します。 4 ソート済みのサブインデックスを最終的な結果セットにマージし ます。 各手順については、以降の項で説明します。 図 9-1 は、セグメントに 2 つの分割と 2 個の物理デバイスを持つテーブル の場合の並列ソートを示します。 212 Adaptive Server Enterprise 第9章 並列ソート 図 9-1: 並列ソート方式 手順 1:データの サンプリングと 分散マップの唆築 分割 1 7 分割 2 分散マップ 2 4 5 9 8 4 3 1 0 7 手順 2:重複しない 範囲へのデータの 分割 9 2 5 6 8 コンシューマ・ プロセス 1 0 1 2 コンシューマ・ プロセス 2 3 ソートされたデータ または サブインデックス 手順 4:ソート されたデータの マージ処理 1 3 4 2K ソート・バッファ マージされた 結果または インデックス 0 プロデューサ・ プロセス 2 プロデューサ・ プロセス 1 手順 3:各範囲の ソートとイン デックスの作成 6 0 1 5 4 コーディネーティング・ プロセス 2 3 4 5 6 7 6 7 8 9 ソートされたデータ または サブインデックス 8 9 分散マップの作成 並列ソートを実行する最初の手段として、Adaptive Server は分散マップを 作成します。ソートがマージ・ジョインの一部として実行され、統計情報 がジョイン・カラムに表示される場合は、ヒストグラムが分散マップの構 築に使用されます。他のソートを実行した場合は、Adaptive Server は入力 テーブルからランダムにデータのサンプルを選択してソートします。この 分散情報 ( 分散マップ ) は、2 番目のソート手順として使用され、並列ソー ト処理の次のフェーズ中に、等しいサイズの各範囲に入力データを分散し ます。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 213 並列ソート方式の概要 この分散マップには、テーブル内の最後の範囲を除く各範囲に割り当てら れる、最も大きなキーに対応するキー値が含まれています。図 9-1 では、 分散マップは 4 以下のすべての値を最初の範囲に割り当て、5 以上のすべ ての値を 2 番目の範囲に割り当てます。 動的な範囲による分割 分散マップを作成してから、Adaptive Server は 2 種類のワーカー・プロセ スを利用して、異なるソートを実行します。これらのワーカー・プロセ スを、 「プロデューサ・プロセス」および「コンシューマ・プロセス」と 呼びます。 • プロデューサ・プロセスは入力テーブルからデータを読み込み、分 散マップを使用して各キー値が属する範囲を決定する。プロデュー サは、正しい範囲に属する 2K ソート・バッファにコピーすることに よって、データを分散する。 • 各コンシューマ・プロセスは、ソート・バッファの範囲からデータを 読み込み、それをサブインデックスにソートする。詳細については、 「範囲ソート」(214 ページ ) を参照。 図 9-1 では、2 つのプロデューサ・プロセスが入力テーブルからデータ を読み込みます。各プロデューサ・プロセスは 1 つのテーブル分割をス キャンし、分散マップを使用してデータを複数の範囲に分散します。た とえば、最初のプロデューサ・プロセスがデータ値 7、2、4、5、9 を読 み込みます。分散マップの情報に基づいて、値 2 と 4 を最初のコンシュー マ・プロセスに、値 7、5、9 を 2 番目のコンシューマ・プロセスに分散 します。 範囲ソート 分割された各範囲には、他の範囲とは別にその範囲のデータをソートする、 専用のコンシューマ・プロセスがあります。テーブルのサイズと、ソート を実行するときに使用できるバッファの数によっては、専用コンシューマ は複数のマージを実行することがあります。この場合、割り当てられた範 囲のデータが完全にソートされるまで、ディスクに中間結果が書き込まれ、 その結果が読み込まれてマージされます。 • 214 create index コマンドの場合、それぞれの分割されたデータ範囲に対 応する各コンシューマは、個別のデータベース・デバイスに書き込み を実行する。これにより、データベース・デバイスがそれぞれ別個の 物理デバイスやコントローラの上にある場合は、I/O 並列処理が増加 するためにパフォーマンスが向上する。また、このコンシューマ・プ ロセスは、ソート済みのデータにサブインデックスというインデック スも構築する。 Adaptive Server Enterprise 第9章 並列ソート • マージ・ジョインの場合、各コンシューマ・プロセスでは、順序付け られたローを個々のリンクされたデータ・ページへ書き込む。書き込 みは、マージを実行するワーカー・プロセスごとに行われる。 • クエリの場合、コンシューマ・プロセスは、範囲内のデータを単に小 さい順 ( 最小値から最大値の順 ) に並べるだけである。 結果のマージ すべてのコンシューマ・プロセスが分割された各範囲でのデータのソート を終了すると、次のような処理が実行されます。 • create index コマンドの場合、コーディネーティング・プロセスが各 サブインデックスを最終的なインデックスにマージする。 • マージ・ジョインの場合、マージ手順で使用するワーカー・プロセ スが、マージ・ジョインした他のテーブルを使用してマージを実行 する。 • 他のクエリの場合、コーディネーティング・プロセスが、ソート結果 をマージしてからクライアントに返す。 並列ソート用のリソース設定 以降の項では、Adaptive Server がデータを並列で処理する場合に使用する リソースについて説明します。 • データを読み込み、ソートを実行するワーカー・プロセス • キャッシュ内のデータをプロデューサからコンシューマに渡すこ とで、物理 I/O を軽減するソート・バッファ • ソートに使用され、物理 I/O を減らすのに役立つキャッシュ内の大容 量 I/O プール 注意 大容量 I/O への参照は、論理ページ・サイズが 2K のサーバに基 づきます。ページ・サイズが 8K のサーバでは、I/O の基本単位は 8K になります。ページ・サイズが 16K のサーバでは、I/O の基本単位は 16K になります。 • I/O 並列処理を増やし、ほとんどのソートについてワーカー・プロセ ス数の決定に役立つ複数の物理デバイス パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 215 並列ソート用のリソース設定 並列ソート中のワーカー・プロセスの稼働条件 Adaptive Server は、並列ソートの実行に一定の最小ワーカー・プロセス数 を必要とします。追加のワーカー・プロセスが有効な場合は、ソートをよ り高速に実行できます。要求される最小数と使用できる最大数は、次の数 から決定されます。 • クラスタード・インデックスを作成する場合、テーブルの分割数 • ノンクラスタード・インデックスを作成する場合、デバイス数 • マージ・ジョインの場合、ワークテーブルの作成に使用するスレッド 数と tempdb 内のデバイス数 • ソートが必要な他のクエリの場合、tempdb 内のデバイス数 最小ワーカー・プロセス数が満たされない場合、次のようになります。 • 分割されたテーブルのクラスタード・インデックスに対するソートは 並列処理されなければならないので、使用できるワーカー・プロセス 数が足りない場合は失敗する。 • ノンクラスタード・インデックスや非分割テーブルのクラスタード・ インデックスのソートは、逐次実行される。 • クエリに対するソートはすべて、逐次実行される。 使用できるワーカー・プロセス数は、サーバ全体およびセッションでの制 限 値 に よ って 決められます。サーバ・レベルでは、number of worker processes と max parallel degree 設定パラメータが、ワーカー・プロセス のプールの合計サイズと、create index または select コマンドによって使 用できるワーカー・プロセスの最大数を制限します。 実行時に使用できるプロセス数は、max parallel degree の設定値やセッ ションの制限値よりも小さい数になることがあります。これは、並列実行 中の他のクエリがあるためです。ソートに使用するワーカー・プロセスの 個数の決定は、オプティマイザではなくソート・マネージャによって行わ れます。ソート・マネージャは実行時にこの決定を行うため、並列ソート の決定は、ソートを開始する時点で実際に使用できるワーカー・プロセス 数に基づいています。 サーバワイドな制限値とセッションワイドな制限値の制御については、 「並列度の制御」(148 ページ ) を参照してください。 インデックス作成時のワーカー・プロセスの動作条件 表 9-1 は、インデックス作成のために必要なプロデューサとコンシューマ の数を示します。ソートの「ターゲット・セグメント」は、create index コマンドの完了時にインデックスが格納されるセグメントです。インデッ クスを作成する場合、on segment_name 句を使用して位置を指定できます。 セグメントを指定しない場合、インデックスは default セグメントに格納 されます。 216 Adaptive Server Enterprise 第9章 並列ソート 表 9-1: インデックス作成用のプロデューサとコンシューマの数 インデックス・タイプ プロデューサの数 コンシューマの数 ノンクラスタード・インデックス 分割の数または 1 1 ターゲット・セグメントにあるデバイス数 非分割テーブルのクラスタード・イン デックス 分割されたテーブルのクラスタード・ 分割の数または 1 インデックス ターゲット・セグメントにあるデバイス数 分割の数 実際に並列ソートを行うのはコンシューマです。CPU 時間を使用して実 際のソートを行い、I/O を使用して中間結果の読み書きを行い、最終的な インデックスをディスクに書き込みます。まず、ソート・マネージャは、 各ターゲット・デバイス用のコンシューマとしてワーカー・プロセスを 1 つ割り当てます。次に、使用できるワーカー・プロセスが十分に存在する 場合、ソート・マネージャはテーブルの各分割に対してプロデューサを 1 つ割り当てます。ワーカー・プロセスが十分に存在しないため、各分割に 対して 1 つずつ割り当てられない場合は、テーブル全体が 1 つのプロ デューサによってスキャンされます。 分割されたテーブルのクラスタード・インデックス 分割されたテーブルにクラスタード・インデックスを作成するため、 Adaptive Server は、テーブルの各分割について最低 1 つのコンシューマ・ プロセスと、テーブルをスキャンするもう 1 つのワーカー・プロセスを必 要とします。十分な数のワーカー・プロセスを使用できない場合、create clustered index コマンドは失敗し、使用できるワーカー・プロセス数と必 要なワーカー・プロセス数を示すメッセージが表示されます。 十分な数のワーカー・プロセスを使用できる場合、ソート・マネージャは、 分割ごとにコンシューマ・プロセスを割り当てるのと同様に、分割ごとに 1 つのプロデューサ・プロセスを割り当てます。これによってデータの読 み込みが高速化されます。 最小数 分割ごとに 1 つのコンシューマと 1 つのプロデューサ 最大数 分割ごとに 2 つのワーカー・プロセス 逐次実行 不可 非分割テーブルのクラスタード・インデックス 非分割テーブルの場合、入力データをスキャンするために使用できるプロ デューサ・プロセスは 1 つだけです。コンシューマ・プロセスの数は、イ ンデックスが格納されるセグメントに存在するデバイス数によって決定 されます。十分な数のワーカー・プロセスが使用できない場合、ソートは 逐次で実行されます。 最小数 デバイスごとに 1 つのコンシューマと 1 つのプロデューサ 最大数 デバイスごとに 1 つのコンシューマと 1 つのプロデューサ 逐次実行 可 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 217 並列ソート用のリソース設定 ノンクラスタード・インデックス コンシューマ・プロセスの数は、ターゲット・セグメントに存在するデ バイス数によって決定されます。使用できるワーカー・プロセスが十分 にあり、テーブルが分割されている場合は、テーブルの各分割につき 1 つのプロデューサ・プロセスが使用されます。テーブルが分割されてい ない場合は、1 つのプロデューサ・プロセスがテーブル全体をスキャンし ます。 最小数 デバイスごとに 1 つのコンシューマと 1 つのプロデューサ 最大数 デバイスごとに 1 つのコンシューマと、分割ごとに 1 つの プロデューサ 逐次実行 可 インデックス作成時の with consumers の使用 RAID デバイスは、Adaptive Server では 1 つのデータベース・デバイスと して認識されます。そのため、デバイスが並列ソートの I/O ロードをサ ポートしていても、Adaptive Server は、デフォルトではデバイスに対して 1 つのコンシューマしか割り当てません。 create index 文で with consumers 句を使用すると、create index 文が使用 できるコンシューマ・プロセスの数を指定できます。ストライプ・デバイ スの I/O キャパシティをテストすると、RAID デバイスがサポートできる 同時プロセス数を決定して、この数を並列ソートの並列度の決定に使用す ることができます。基本的には、実際に存在する各物理デバイスにつき 1 つのコンシューマを使用します。次の例では、8 つのコンシューマを指定 しています。 create index order_ix on orders (order_id) with consumers = 8 また、primary key インデックスと unique インデックスを作成する alter table...add constraint 句とともに、with consumers 句を使用することもで きます。 alter table orders add constraint prim_key primary key (order_id) with consumers = 8 with consumers 句は、インデックスの作成に使用できますが、並列クエ リの内部ソートでは使用されるコンシューマ・プロセスの数を制御できま せん。分割されたテーブルのクラスタード・インデックスを作成する場 合、この句は使用できません。分割されたテーブルのクラスタード・イン デックスを作成する場合、Adaptive Server は、テーブル内の各分割につき 1 個のコンシューマ・プロセスを使用して、必ず最終的にソートされた データを各分割に等しく分散しなければなりません。 Adaptive Server は、指定されたプロセス数が使用できるワーカー・プロセ ス数よりも大きい場合や、指定されたプロセス数が並列処理のサーバ制限 またはセッション制限を超える場合、with cosumers 句を無視します。 218 Adaptive Server Enterprise 第9章 並列ソート select クエリ・ソート時のワーカー・プロセスの動作条件 ワークテーブル・ソートを必要とするクエリには、マルチステップ・クエ リ・プランがあります。ワークテーブル・ソート用のワーカー・プロセス の数は、ベース・テーブルのスキャンが完了してから決定されます。ワー クテーブルに対してデータを選択するクエリのフェーズで、各ワーカー・ プロセスは、そのワークテーブルの独立した分割に対してデータを選択し ます。 追加のワーカー・プロセスが割り付けられ、ソートの手順が実行されます。 showplan はこの値を報告しません。ソート・マネージャは、ソートが逐 次実行されたか並列実行されたかを報告するだけです。現在の手順では、 ワーカー・プロセスがソートを実行するわけではありませんが、タスクが 完了するまで並列タスクに割り付けられたままです。 マージ・ジョイン・ソート時のワーカー・プロセス マージ・ジョインの場合、tempdb の各デバイスにコンシューマ・プロセ スを 1 つずつ割り当てます。tempdb 内にデバイスが 1 つしかない場合は、 コンシューマ・プロセスを 2 つ使用します。プロデューサ数はワークテー ブルの分割数によって異なり、max parallel degree の設定は次のようにな ります。 • ワークテーブルが分割されていない場合は、プロデューサ・プロセス を 1 つ使用する。 • コンシューマ・プロセスの数にワークテーブルの分割数を加えた数が max parallel degree 以下の場合は、ワークテーブルの分割ごとにプロ デューサ・プロセスを 1 つ割り付ける。 • コンシューマ・プロセスの数にワークテーブルの分割数を加えた数が max parallel degree より大きい場合は、プロデューサ・プロセスを 1 つ使用する。 その他のワークテーブル・ソート その他のワークテーブル・ソートの場合は、ワークテーブルの作成が完了 すると、その分割が解除されます。ワーカー・プロセスを、次のとおり割 り当てます。 • tempdb にデバイスが 1 つしかない場合、ソートは 2 つのコンシューマ と 1 つのプロデューサを使用して実行される。 その他の場合は、 tempdb 内の各デバイスにコンシューマ・プロセスが 1 つ割り当てられ、1 つの プロデューサ・プロセスがワークテーブルをスキャンする。 • ソート開始時に、使用できるワーカー・プロセス数より多くのデバイ スが tempdb にある場合は、ソートは逐次実行される。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 219 並列ソート用のリソース設定 キャッシュ、ソート・バッファ、並列ソート キャッシュと number of sort buffer 設定パラメータの設定を最適化すると、 並列ソートのパフォーマンスを大きく向上させることができます。並列 ソートを実行する場合、次のチューニング・オプションを考慮します。 • キャッシュのバインド • ソート・バッファ • 大容量 I/O ほとんどの場合、通常の実行時操作のために選択するオプションは、ワー クテーブル・ソートを実行するクエリの必要に応じて選択してください。 同時実行される必要があるソートの数と、ワークテーブルのおおよそのサ イズを理解したうえで、tempdb が使用するキャッシュを設定し、ソート を最適化します。 システムの利用率が低い時間帯にインデックスの削除と作成を行う場合は、 キャッシュとプールの再設定とキャッシュ・バインドの変更によって、ソー ト数の最適化と必要時間の削減ができます。ユーザの作業中にインデックス の管理を実行する必要がある場合は、その再設定がユーザ応答時間に与える 影響を考慮してください。キャッシュの大部分を、キャッシュからのオブ ジェクトのソートや一時的なバインド解除のためにだけ使う設定にしてい ると、他の作業に重大な影響を与えることがあります。 キャッシュのバインド create index でのソートは、テーブルがバインドされるキャッシュ内で実 行されます。テーブルがキャッシュにバインドされていなくても、データ ベースがバインドされている場合は、そのキャッシュが使用されます。明 示的なキャッシュ・バインドがない場合、デフォルトのデータ・キャッ シュが使用されます。ワークテーブル・ソートでは、tempdb をバインド するキャッシュ、またはデフォルトのデータ・キャッシュを使用します。 個別のソートに対してソート・バッファの数と大容量 I/O を設定するには、 常にキャッシュ・バインドをチェックします。sp_help を使用して、テー ブルのバインドを調べることができます。サーバ上のすべてのバインドを 調べるには、sp_helpcache を使用します。テーブルのキャッシュ・バイ ンドを決定したら、sp_cacheconfig を使用してキャッシュにある 2K およ び 16K プール内の空き容量をチェックします。 ソート・パフォーマンスに影響するソート・バッファの数 プロデューサは入力テーブルから読み込みを行うために、コンシューマ は中間ソート結果を読み書きするために、それぞれディスク I/O を実行し ます。ソート中に、プロデューサはソート・バッファを使用してコン シューマにデータを渡します。これにより、データ・ローが完全にメモ リにコピーされ、ディスク I/O を回避します。予約されたバッファは、 ソートの実行中は他のタスクから利用できなくなります。 220 Adaptive Server Enterprise 第9章 並列ソート number of sort buffers 設定パラメータは、逐次ソートの実行時に使用可能 な最大領域を決定します。各ソート・インスタンスは、各ソートについて number of sort buffers の値を上限としてバッファを使用できます。アク ティブなソートがキャッシュ内のすべてのバッファを予約していて、別の ソートがソート・バッファを要求すると、後者のソートはキャッシュ内の バッファが使用可能になるまで待機します。 ソート・バッファ設定のガイドライン number of sort buffers は、1 つのバッチ内で読み込みとソートができる データの量を制御します。このため、より多くのソート・バッファを設定 すると、バッチ・サイズが大きくなり、必要なマージの実行数を減らすこ とができ、ソートの実行が高速になります。number of sort buffers は動的 に変更されるため、サーバを再起動する必要はありません。 ソート・バッファを設定するための一般的なガイドラインは次のとおり です。 • テーブル内のページ数が number of sort buffers の値の 8 倍未満であ る場合、ソート・マネージャは逐次ソートを選択する。ほとんどの 場合、select クエリや小規模なインデックスではデフォルト値 (500) で十分に機能する。この設定では、4000 ページ以下のすべての create index やワークテーブル・ソートに対して、ソート・マネージャは逐 次ソートを選択し、それよりも大きな結果セットに対しては並列 ソートを選択する。これにより、クエリ処理とより大規模なソート のためにワーカー・プロセスを節約できる。また、500 個までのソー ト・バッファを使用する複数のソート・プロセスが許可される。 ソートのために実行されるマージの回数を少なくするには、テンポ ラリ・ワークテーブルのサイズを非常に大きく確保しておいてから、 バッファ数を大きく設定する必要がある。詳細については、 『パ フォーマンス&チューニング・ガイド:基本』の「tempdb のサイズ 設定」(385 ページ ) を参照。 • 他のユーザがアクティブになっている時点で、大きなテーブルに対す るインデックスを作成する場合は、ソート・バッファ数を大きい数に 設定して、データ・キャッシュを使用する必要がある他の活動を妨げ ないようにする。 • 定期的な管理作業の時間帯に、システム上のアクティブなユーザが 少ない状態でインデックスを再作成する場合は、ソート・バッファ の値を大きい数に設定する。インデックスの管理作業を高速化する ために、大きいソート・バッファ数の値、大容量 I/O、キャッシュ・ バインドのパフォーマンスに対してベンチマークを実行し、イン デックスのアクティビティを最適化する必要がある。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 221 並列ソート用のリソース設定 • マージ実行回数は対数関数的に減少する。number of sort buffers の 値を 500 から 600 に増やしても、マージ実行回数はほとんど変化し ない。サイズをより大きくすると (5000 など )、マージ実行回数と必 要な I/O の減少により、ソートが非常に高速に実行される。 • number of sort buffers の値をワークテーブルのサイズの平方根より 小さく設定すると、ソートのパフォーマンスが低下する。ワークテー ブルには、select リストに指定されているカラムと後のジョイン実行 時に必要なカラムだけが含まれている。したがって、マージ・ジョイ ンに使用するワークテーブルのサイズは、通常、元のテーブル・サイ ズよりもかなり小さくなる。 • 十分な数のソート・バッファを設定する。 ソート・バッファによって、実行ごとにソートできるデータのページ 数が決まります。この数はソートの終了に必要な実行回数を計算する ときの対数関数の底となります。 たとえば、500 のバッファを使用する場合は、底を 500 とした “log ( テーブル内のページ数 )” で計算されます。 また、ソート・バッファ数は並列ソートのスレッドで共有され、十分 な数のソート・バッファがない場合は、並列ソートの動作が遅くなる 場合があります。 ソート・バッファを必要なだけ設定すると、ソート時に必要な中間ス テップ、マージ実行回数、物理 I/O は減少します。number of sort buffers の値がテーブルに対応するページ数以上である場合、ソート は完全にキャッシュ内で実行され、中間ステップ用の物理 I/O は実行 されません。I/O が必要になるのは、データとインデックス・ページ に対して読み書きを行う場合だけです。 • 名前付きキャッシュをテーブルにバインドして、そのキャッシュに大 きいバッファ・プールを設定し、大容量 I/O が可能になるようにする。 設定数より少ないソート・バッファの使用 設定数より少ないソート・バッファを使用するソートには、次の 2 種類が あります。 222 • 分割されたテーブルにクラスタード・インデックスを作成する場合、 常に並列ソートが必要。テーブル・サイズが設定されたソート・バッ ファ数より少ない場合、ソート用のテーブル内にあるページ数が予約 される。 • 小規模な逐次ソートでは、キャッシュ内のテーブルを扱うために必要 なソート・バッファ数だけが予約される。 Adaptive Server Enterprise 第9章 並列ソート number of sort buffers パラメータの設定 図 9-2 に示すように、インデックスを並列で作成する場合、number of sort buffers は、プール領域のウォッシュ・マーカより前にあるバッファ数の 90 パーセント以下でなければなりません。 図 9-2: ソート・バッファが使用できる領域 MRU ソート・バッファに使用できるウォッシュ・ マーカ前の領域の最大 90% 2K プールの使用 LRU ウォッシュ・マーカ プール・サイズの 90 パーセントという制限は、number of sort buffers パ ラメータの設定時ではなく、create index コマンドの実行時に課せられ ます。これは、この制限がソートされるテーブル用のプールに対して課 されるためです。number of sort buffer の最大設定値は 32,767 です。こ れは sp_configure によって制限されている値です。 プールで使用できるソート・バッファの計算 sp_cacheconfig は、プールのサイズをメガバイト単位で、またウォッ シュ・サイズをキロバイト単位で返します。たとえば、次の出力はデフォ ルトのデータ・キャッシュ内のプールのサイズを示しています。 Cache: default data cache, Status: Active, Type: Default Config Size: 0.00 Mb, Run Size: 38.23 Mb Config Replacement: strict LRU, Run Replacement: strict LRU Config Partition: 2, Run Partition: 2 IO Size Wash Size Config Size Run Size APF Percent -------- --------- ------------ ------------ ----------2 Kb 4544 Kb 0.00 Mb 22.23 Mb 10 16 Kb 3200 Kb 16.00 Mb 16.00 Mb 10 次のプロシージャは、2K プールのサイズとそのウォッシュ・サイズをパ ラメータに取り、両方の値をページ数に変換してソート・バッファのため に使用できる最大ページ数を計算します。 create proc bufs @poolsize numeric(6,2), @wash int as select "90% of non-wash 2k pool" = ((@poolsize * 512) - (@wash/2)) * .9 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 223 並列ソート用のリソース設定 次の例では、プール・サイズを “22.23Mb”、ウォッシュ・サイズを “4544Kb” として、bufs を実行します。 bufs 22.23, 4544 bufs プロシージャは次の結果を返します。 90% of non-wash 2k pool ----------------------8198.784 次のコマンドは、ソート・バッファ数を 8198 ページに設定します。 sp_configure "number of sort buffers", 8198 インデックスを作成したいテーブルがユーザ定義のキャッシュにバイン ドされている場合は、特定のキャッシュに対して適切なソート・バッファ 数を設定する必要があります。別の方法としては、次のようにキャッシュ からテーブルのバインドを解除してインデックスを作成し、テーブルを再 バインドすることもできます。 sp_unbindcache pubtune, titles create clustered index title_ix on titles (title_id) sp_bindcache pubtune_cache, pubtune, titles 警告! ソートによって使用されるバッファは、ソートが完了するまで全 体が予約されています。サーバ上の別のタスクに使用することはできま せん。ソート・バッファをプール・サイズの 90 パーセントに設定すると、 他のトランザクションがアクティブなままインデックスを作成する場合 に、クエリの処理に重大な影響を与えることがあります。 マージ・レベルと I/O を見積もるプロシージャ 次のプロシージャは、インデックスの作成に必要なマージ実行回数と物理 I/O の量を見積もります。 create proc merge_runs @pages int, @bufs int as declare @runs int, @merges int, @maxmerge int select @runs = ceiling ( @pages / @bufs ) /* if all pages fit into sort buffers, no merge runs needed */ if @runs <=1 select @merges = 0 else begin if @runs > @bufs select @maxmerge = @bufs else select @maxmerge = @runs 224 Adaptive Server Enterprise 第9章 並列ソート if @maxmerge < 2 select @maxmerge = 2 select @merges = ceiling(log10(@runs) / log10(@maxmerge)) end select @merges "Merge Levels", 2 * @pages * @merges + @pages "Total IO" このプロシージャのパラメータは次のとおりです。 • pages - テーブル内のページ数、またはノンクラスタード・インデッ クス内のリーフレベル・ページ数 • bufs - 設定するソート・バッファの数 次の例は、2,000,000 ページのテーブルに対して、デフォルトのソート・ バッファ数を使用しています。 merge_runs 2000000, 500, 20 merge_runs プロシージャは、インデックスを作成するには 2 回のマージ の実行と 10,000,000 の I/O が必要であると見積もります。 Merge Levels Total IO ------------ ----------2 10000000 ソート・バッファの数を 1500 に増やすと、マージ実行回数と I/O は次の ようになります。 merge_runs 2000000, 1500 Merge Levels Total IO ------------ ----------1 6000000 このプロシージャで予測される合計 I/O は、ソートが使用するキャッシュ とプールのサイズと設定に応じて、システムの I/O 使用率とは異なる値に なることがあります。 並列ソートでの大容量 I/O 用のキャッシュの設定 ソートは、次の場合に大容量 I/O を使用できます。 • サンプリング・フェーズ • プロシージャが入力テーブルをスキャンする場合 • コンシューマが、中間ソート結果および最終的なソート結果について ディスク I/O を実行する場合 これらのステップでは、ソートによって、ソートされるテーブルが使う キャッシュ内で可能な限り大きいプール・サイズが使用されます。大容量 I/O バッファがまったく使用できない場合は、2K プールを使用できます。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 225 並列ソート用のリソース設定 ソート・バッファと大容量 I/O 設定のバランス ソートが使用するキャッシュ内に 16K バッファ用のプールを設定すると、 物理 I/O の回数が実質的に減少するため、ソートの I/O が非常に高速化さ れます。この I/O の節約は、部分的には入力テーブルのスキャンに大容量 I/O を使用した結果です。 読み込みと書き込み両方について、追加の I/O がソートのマージ・フェー ズで実行されます。この手順の間の I/O の量は、必要とされるマージ・ フェーズの数に依存します。ソートおよびマージの手順では、バッファは 一度読み込まれてから必要でなくなるか、ディスクに書き込まれた中間 ソート結果を再利用できるように格納するかのいずれかです。ソート時の キャッシュヒット率は常に低くなるので、マージ実行回数を減らすために 大容量 16K キャッシュを使う設定を行うと、ソート・バッファとしてよ り有効に利用できる領域が消費されます。 たとえば、32MB のキャッシュを使用する 250MB のテーブルにクラス タード・インデックスを作成する場合に、4MB だけを 16K プールとして、 残りを 10,000 のソート・バッファとして設定した場合に最適に実行され たとします。プール・サイズをより大きくしても、キャッシュヒット率 や I/O の回数には影響しません。16K プール用のウォッシュ・サイズを許 容される最大値に変更すると、わずかにパフォーマンスが向上します。こ れは、プール・サイズを小さくすることで、書き込みが完了する前にバッ ファが LRU 側の終端に達するためです。次の式は、16K プールで許容さ れる最大ウォッシュ・サイズを計算します。 select floor((size_in_MB * 1024 /16) * .8) * 16 ディスクの動作条件 並列ソート用のディスク動作条件は次のとおりです。 226 • インデックス全体を格納するには空き領域が必要である。 • ターゲット・セグメントに複数のデバイスがあると、ワークテーブ ル・ソート用およびノンクラスタード・インデックス作成用のコン シューマ数と、非分割テーブルのクラスタード・インデックスの数を 増やすことができる。 Adaptive Server Enterprise 第9章 並列ソート インデックス作成時の空き領域の動作条件 インデックスの作成には、ソート済みのインデックスを格納する領域が 必要です。クラスタード・インデックスの場合、データ・ローをインデッ クス・キーの順に新しい位置にコピーする必要があります。新しく並べ 替えられたデータ・ローとインデックスの上部レベルの書き込みを実行 してから、ベース・テーブルを削除できるようにします。with sorted_data 句を使用してソートを中止する場合以外は、クラスタード・インデック スを作成するため、テーブルが占める領域の約 120 パーセントが必要に なります。 ノンクラスタード・インデックスを作成すると、新しいインデックスを格 納する領域が必要になります。オブジェクトのサイズと使用可能な領域を 調べるには、次のシステム・プロシージャが役に立ちます。 • sp_spaceused - テーブルのサイズを調べる。詳細については、『パ フォーマンス&チューニング・ガイド:基本』の「sp_spaceused を 使ってオブジェクト・サイズを表示する」(248 ページ ) を参照。 • sp_estspace - インデックスのサイズを予測する。詳細については、 『パフォーマンス&チューニング・ガイド:基本』の「sp_estspace を 使ってオブジェクト・サイズを見積もる」(250 ページ ) を参照。 • sp_helpsegment - データベース・セグメント上の空き領域を調べる。 詳細については、 『パフォーマンス&チューニング・ガイド:基本』の 「sp_helpsegment を使ってデバイスでのデータの分配をチェックする」 (109 ページ ) を参照。 ワークテーブル・ソート時の空き領域の動作条件 ワークテーブルをソートするクエリ ( マージ・ジョインと order by、 distinct、union、再フォーマット方式 ) は、まずクエリが必要とするカラ ムをワークテーブルにコピーし、次にソートを実行します。これらのワー クテーブルは tempdb 内の system セグメントに格納されるため、これが ソートを必要とするクエリのターゲット・セグメントとなります。使用可 能な領域とデバイス数を調べるには、次のコマンドを使用します。 tempdb..sp_helpsegment system ワークテーブルにローを挿入するプロセスと並列ソートは、並列実行に複 数のデバイスを必要としません。しかし、tempdb 内の system セグメン トが複数のデータベース・デバイスにまたがっていると、パフォーマンス は向上します。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 227 リカバリについて ターゲット・セグメント内のデバイス数 「並列ソート中のワーカー・プロセスの稼働条件」(216 ページ ) で説明し たように、ターゲット・セグメントにあるデバイス数は、分割されたテー ブルにクラスタード・インデックスを作成する場合を除いて、ソート・オ ペレーション用のコンシューマ数を決定します。 インデックスがデータとは別のデバイス上にある場合の I/O の向上など、 クエリ処理のパフォーマンスについては、デバイスの割り付けやオブ ジェクトの位置を決定するうえで、ソートの稼働条件よりも慎重に考慮 します。 ワークテーブル・ソートが並列ソートを必要とするほど大きい場合、 tempdb のシステム・セグメントに複数のデバイスがあると、ローをワー クテーブルに挿入するときに I/O 並列処理が向上するのと同様に、ソート も高速化されます。 リカバリについて インデックスの作成は、最小限のログを取るデータベース・オペレーショ ンです。逐次ソートは、トランザクション・ログからソート全体を再実行 することでリカバリできます。しかし、並列実行される create index コマ ンドは、トランザクション・ログからリカバリできません。並列ソートを 実行した後、データベースをダンプしてから、データベースに対して dump transaction コマンドを使用してください。 Adaptive Server は、select into/bulk copy/pllsort データベース・オプション が on に設定されていないかぎり、create index コマンドについて自動的 に並列ソートを実行することはありません。分割されたテーブルにクラス タード・インデックスを作成するには、常に並列ソートが必要です。他の ソート・オペレーションは、select into/bulk copy/pllsort オプションが有 効でない場合は逐次ソートでも実行できます。 228 Adaptive Server Enterprise 第9章 並列ソート ソート動作の監視およびチューニング用のツール Adaptive Server は、ソートの動作に関連して作業を行うツールを備えてい ます。 • set sort_resources on は、インデックスを作成することなく、create index コマンドがどのように実行されるかを示す。詳細については、 「set sort_resources on の使用」(229 ページ ) を参照。 • 次のシステム・プロシージャは、サイズ、空き領域、時間の条件の見 積もりに使用できる。 • sp_configure - 設定パラメータを表示する。詳細については、 「並列設定パラメータの設定例」(151 ページ ) を参照。 • sp_helpartition - 分割されたテーブルに関する情報を表示する。 詳細については、 『パフォーマンス&チューニング・ガイド:基 本』の「分割に関する情報を表示する」(107 ページ ) を参照。 • sp_helpsegment - セグメント、デバイス、領域の使用状況につ いて表示する。詳細については、 『パフォーマンス&チューニン グ・ガイド:基本』の「sp_helpsegment を使ってデバイスでの データの分配をチェックする」(109 ページ ) を参照。 • sp_sysmon - CPU 使用率、物理 I/O、キャッシュなど、並列ソー トで使用される多くのリソースのレポートを表示する。詳細に ついては、「sp_sysmon を使用したインデックス作成のチューニ ング」(234 ページ ) を参照。 set sort_resources on の使用 set sort_resources on コマンドは、ソート・マネージャによる create index 文の並列ソートの実行方法を理解するのに役立ちます。設定パラメータの 値を増加したり、ソート用の追加コンシューマを指定したりする必要があ るかどうかを決定するため、このコマンドを使用してからインデックスを 作成できます。 set sort_resources on を使用すると、Adaptive Server は、実際にインデッ クスを作成するのではなく、リソースを分析してサンプリングの手順を実 行し、create index コマンドを実行するために並列ソートをどのように使 用するかについて詳細な情報を表示します。表 9-2 は、ソート・オペレー ションに対して表示されるメッセージを示します。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 229 ソート動作の監視およびチューニング用のツール 表 9-2: 基本的なソート・リソース・メッセージ メッセージ The Create Index is done using sort_type 意味 sort_type は “Parallel Sort” または “Serial Sort.” 参照先 「稼 働 条 件 と リ ソ ー ス の 概 要」(210 ページ ) Sort buffer size: N N は number of sort buffers 設定パラ 「ソート・バッファ設定のガイドライ メータの値 ン」(221 ページ ) Parallel degree: N N は並 列 ソー ト が使 用 でき る ワー 「キャッシュ、ソート・バッファ、並 カー・プロセスの最大数。設定パラ 列ソート」(220 ページ ) メータで設定 Number of output devices: N N はターゲット・システムにあるデー 「ディスクの動作条件」(226 ページ ) タベース・デバイスの合計数 Number of producer threads: N N はソート・マネージャによって決 定される最適なプロデューサ・プロ セス数 「並列ソート中のワーカー・プロセス の稼働条件」(216 ページ ) Number of consumer threads: N N はソート・マネージャによって決 定される最適なコンシューマ・プロ セス数 「並列ソート中のワーカー・プロセス の稼働条件」(216 ページ ) The distribution map contains M element(s) for N partitions. M は分散マップ内の範囲境界を定義 「分散マップの作成」(213 ページ ) するエレメントの数。N は分散マップ 内の分割 ( 範囲 ) 数 Partition Element:N value N は分 散 マッ プ・エレ メ ント の 数。 「分散マップの作成」(213 ページ ) value は各分割の境界を定義する分散 マップ・エレメント Number of sampled records: N N は分散マップの作成に使用される、 「分散マップの作成」(213 ページ ) サンプリングされたレコードの数 例 次の例は、set sort_resources コマンドの出力を示します。 非分割テーブルのノンクラスタード・インデックス この例では、非分割テーブルでの create index コマンドに対して、Adaptive Server が並列ソートを実行する方法を示します。この例の詳細は次のとお りです。 230 • default セグメントは 4 つのデータベース・セグメントに広がっている。 • max parallel degree は 20 ワーカー・プロセスに設定。 • number of sort buffers はデフォルトの 500 バッファに設定。 Adaptive Server Enterprise 第9章 並列ソート 次のコマンドは、sort_resources on を設定し、orders テーブルに対して create index コマンドを発行します。 set sort_resources on create index order_ix on orders (order_id) Adaptive Server からは次のように出力されます。 The Create Index is done using Parallel Sort Sort buffer size: 500 Parallel degree: 20 Number of output devices: 4 Number of producer threads: 1 Number of consumer threads: 4 The distribution map contains 3 element(s) for 4 partitions. Partition Element: 1 458052 Partition Element: 2 909063 Partition Element: 3 1355747 Number of sampled records: 2418 この例では、default セグメントの 4 つのデバイスによって、ソート用の コンシューマ・プロセス数が決定されます。入力テーブルが分割されてい ないので、ソート・マネージャは合計並列度 5 に対して、プロデューサ・ プロセスを 1 つ割り付けます。 分散マップは、4 つある範囲に対して 3 つの分類値を使用します。458052 以下の最小の入力値は、最初の範囲に属します。458052 より大きく 909063 以下の値は 2 番目の範囲に属します。909063 より大きく 1355747 以下の 値は 3 番目の範囲に属します。1355747 より大きい値は 4 番目の範囲に属 します。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 231 ソート動作の監視およびチューニング用のツール 分割されたテーブルのノンクラスタード・インデックス この例では、最初の例と同じテーブルとデバイスを使用します。ただし、 この例では、入力テーブルを分割してからノンクラスタード・インデック スを作成します。コマンドは次のとおりです。 set sort_resources on alter table orders partition 9 create index order_ix on orders (order_id) この場合、create index コマンドは、sort_resources オプションが指定さ れたうえで次のように出力します。 The Create Index is done using Parallel Sort Sort buffer size: 500 Parallel degree: 20 Number of output devices: 4 Number of producer threads: 9 Number of consumer threads: 4 The distribution map contains 3 element(s) for 4 partitions. Partition Element: 1 458464 Partition Element: 2 892035 Partition Element: 3 1349187 Number of sampled records: 2448 入力テーブルは分割されているため、ソート・マネージャは、総数 13 の ワーカー・プロセスに対して 9 つのプロデューサ・スレッドを割り付け ます。分散マップ内のエレメント数は同じですが、前のソートの例とは 値が多少異なります。 分割されたテーブルのクラスタード・インデックス ( 並列実行される場合 ) この例では、orders にクラスタード・インデックスを作成します。セグメ ント名としては order_seg を指定します。 set sort_resources on alter table orders partition 9 create clustered index order_ix on orders (order_id) on order_seg 232 Adaptive Server Enterprise 第9章 並列ソート 使用できるワーカー・プロセス数が 20 であるため、次の出力に示すとおり、 このコマンドは 9 つのプロデューサと 9 つのコンシューマを使用できます。 The Create Index is done using Parallel Sort Sort buffer size: 500 Parallel degree: 20 Number of output devices: 9 Number of producer threads: 9 Number of consumer threads: 9 The distribution map contains 8 element(s) for 9 partitions. Partition Element: 1 199141 Partition Element: 2 397543 Partition Element: 3 598758 Partition Element: 4 800484 Partition Element: 5 1010982 Partition Element: 6 1202471 Partition Element: 7 1397664 Partition Element: 8 1594563 Number of sampled records: 8055 この分散マップは、ソートされるテーブルの 9 つある分割に対して 8 つの エレメントを含んでいます。使用するワーカー・プロセス数は 18 です。 注意 最初にクラスタード・インデックスを作成します。ノンクラスター ド・インデックスを作成した後で、クラスタード・インデックスを作成し ないでください。クラスタード・インデックスを作成すると、作成済みの ノンクラスタード・インデックスがすべて再構築されます。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 233 sp_sysmon を使用したインデックス作成のチューニング ソートの失敗 たとえば、このコマンドに 10 のワーカー・プロセスしか使用できなかっ た場合、テーブル全体を読み込むために 1 つのプロデューサ・プロセスを 使用することで、このコマンドは成功しています。10 未満のワーカー・プ ロセスしか使用できない場合は、sort_resources 出力の代わりに次の警告 メッセージが表示されます。 Msg 1538, Level 17, State 1: Server ’snipe’, Line 1: Parallel degree 8 is less than required parallel degree 10 to create clustered index on partition table. Change the parallel degree to required parallel degree and retry. sp_sysmon を使用したインデックス作成のチューニング sp_sysmon では、“begin_sample” および “end_sample” 構文を使用して、個 別に create index コマンドのパフォーマンスの結果を提供することがで きます。 sp_sysmon begin_sample create index ... sp_sysmon end_sample チェックするレポートのセクションには、次のものがあります。 • “Sample Interval”。インデックスの作成にかかる合計時間の場合。 • テーブルが使用するキャッシュの統計値。 • 234 • 大容量 I/O の効率を調べるため、2K および 16K プールの “Buffer Grabs” の値をチェックする。 • “Dirty Buffer Grabs” の値をチェックする。 この値が 0 でない場合は、 プール内のウォッシュ・サイズを大きくするか、sp_poolconfig を 使用してプール・サイズを大きくする ( またはその両方を行う )。 テーブルとインデックスが使用するディスクのディスク I/O。“Total Requested I/Os” の値をチェックする。 Adaptive Server Enterprise 第9章 並列ソート 並列ソートを使用した create index の高速化 並列ソートを利用して create index の高速化を図るには、複数のデバイ スにターゲット・セグメントを設定します。複数のデバイスを使用する ことで、並列ソートは並列 I/O を十分に使用できるようになり、Adaptive Server はデバイス数に基づいてソートと create index のオペレーション に対するコンシューマ数を決定します。 並列ソートによる create index を実行する場合、テーブルをスライスする 必要があるとは限りません。その代わりに、create index を consumer 句 と一緒に使用します。ただし、ターゲット・セグメントが複数のデバイス に存在しない場合は、consumer 句に指定したコンシューマ数が無視され ることがあります。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 235 並列ソートを使用した create index の高速化 236 Adaptive Server Enterprise 第 1 0 章 非同期プリフェッチのチューニング この章では、どのように非同期プリフェッチが多くの種類のクエリの I/O パフォーマンスを向上させるかを説明します。これは、クエリがデータ・ ページとインデックス・ページを要求する前に、これらのページをキャッ シュに読み込むことによって実現されます。 トピック名 非同期プリフェッチによるパフォーマンスの向上 ページ 237 プリフェッチが自動的に無効になる場合 244 非同期プリフェッチのチューニング目標 247 Adaptive Server のほかのパフォーマンス機能 248 非同期プリフェッチ制限値の特殊な設定 251 高いプリフェッチ・パフォーマンスのための管理作業 253 パフォーマンス・モニタリングと非同期プリフェッチ 254 非同期プリフェッチによるパフォーマンスの向上 非同期プリフェッチは、次のような方法でパフォーマンスを向上させます。 つまり、予測可能なアクセス・パターンを持つ、ある種の十分に定義され たデータベース・アクティビティについて、必要になるページを予測する 方法です。予測されたページ数に対しては、クエリでそのページが必要と なる前に I/O 要求が発行されるので、あるページに対するアクセスがクエ リ処理によって必要になるときには、すでにほとんどのページがキャッ シュの中に存在しています。非同期プリフェッチによってパフォーマンス が向上するのは、次の場合です。 • テーブル・スキャン、クラスタード・インデックス・スキャン、カ バード・ノンクラスタード・インデックス・スキャンなどの、逐次ス キャン • ノンクラスタード・インデックスを介したアクセス • ある種の dbcc チェックと update statistics 処理 • リカバリ マシンの I/O サブシステムが飽和状態にならない限り、非同期プリフェッ チによって、大量のページをアクセスするクエリ ( 意思決定支援アプリ ケーションなど ) のパフォーマンスを向上させることができます。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 237 非同期プリフェッチによるパフォーマンスの向上 非同期プリフェッチは、I/O サブシステムがすでに飽和状態に達している か Adaptive Server が CPU の能力によって制限を受けている場合には、効 果を発揮しません ( 発揮してもわずかです )。特定の OLTP アプリケーショ ンなどで非同期プリフェッチを使用できますが、OLTP クエリは実行する I/O 処理が比較的少ないので、わずかな効果しか得られません。 Adaptive Server は、クエリでテーブル・スキャンを実行する必要が生じ ると、次のように動作します。 • ページのローと、ローの値を検査する。 • テーブルから読み込まれる次のページについて、キャッシュ内を チェックする。そのページがキャッシュ内にあれば、タスクの処理を 続行する。なければ、タスクは I/O 要求を発行し、I/O が完了するま でスリープする。 • I/O が完了すると、タスクはスリープ・キューから実行キューに移行 する。エンジンに対してタスクがスケジュールされている場合には、 Adaptive Server は新しくフェッチしたページのローを検査する。 このようなディスク読み込みの実行と停止のサイクルは、テーブル・ス キャンが完了するまで続けられます。同様に、ノンクラスタード・イン デックスを使用するクエリは、データ・ページを処理し、インデックスで 参照される次のページへの I/O を発行し、そのページがキャッシュに存在 しなければ I/O が完了するまでスリープします。 このような実行と停止のパターンは、大量ページの物理 I/O を発行するク エリのパフォーマンスを低下させます。物理 I/O の完了を待つ時間がある だけでなく、タスクによるエンジンのオン/オフも繰り返されます。この タスクの切り替えにより、処理のオーバヘッドが増大します。 ページのプリフェッチによるクエリ・パフォーマンスの向上 非同期プリフェッチは、クエリでページが必要になる前に、これらのペー ジに対する I/O 要求を発行し、クエリ処理でページへのアクセスが必要に なった時点では、大部分のページがキャッシュ内に存在しています。必要 なページがキャッシュ内にあれば、クエリは物理読み込みを待つためにエ ンジンを生成しません ( ほかの理由で生成することもありますが、頻度は より少なくなります )。 実行するクエリのタイプに基づいて、非同期プリフェッチは、すぐに必要 になると予測される「予備セット」を構築します。Adaptive Server は、非 同期プリフェッチを使用する処理の種類ごとに、異なる予備セットを定義 します。 238 Adaptive Server Enterprise 第 10 章 非同期プリフェッチのチューニング 場合によっては、予備セットが非常に正確になることがあります。また、 いくつかの仮定と推測の結果、フェッチされたページが読み込まれない こともあります。キャッシュに読み込まれた不要なページのパーセン テージがごく低い場合には、非同期プリフェッチによるパフォーマンス の向上は、むだな読み込みによる不利益を補って余りあります。使用さ れないページの数が大きくなると、Adaptive Server はその状況を検出し、 予備セットのサイズを小さくするか、またはプリフェッチを一時的に無 効にします。 マルチユーザ環境でのプリフェッチ制御メカニズム 同時実行される多くのクエリが、大量のページをバッファ・プールにプリ フェッチするとき、1 つのクエリ用にフェッチされたバッファが、使用さ れないうちにプールからフラッシュされる危険性があります。 Adaptive Server は、非同期プリフェッチによって各プールに取り込まれた バッファと、使用されたバッファ数を追跡します。また、プリフェッチさ れたけれども使用されなかったバッファ数の、プールごとのカウントを保 守します。デフォルトでは、Adaptive Server は非同期プリフェッチの制限 値を各プールの 10% に設定しています。さらに、プリフェッチされたに もかかわらず使用されないバッファ数の制限値は、プールごとに設定でき ます。 プールの制限値と使用統計は、キャッシュ・ヒット率を大きく保ち、不要 な I/O を削減するための、非同期プリフェッチに対する監督者としての役 割を果たします。全体的な効果として、ほとんどのクエリが大きなキャッ シュ・ヒット率を示し、ディスク I/O スリープに起因する停止が少なくな ります。 以降の各項では、アクティビティに対する予備セットの構築方法と、非同 期プリフェッチを使用するクエリの種類について説明します。ある種の非 同期プリフェッチの最適化では、アロケーション・ページを使って予備 セットが構築されます。 アロケーション・ページがどのようにオブジェクトの記憶領域についての 情報を記録するかは、「アロケーション・ページ」(154 ページ ) を参照し てください。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 239 非同期プリフェッチによるパフォーマンスの向上 リカバリ中の予備セット リカバリ中、Adaptive Server はトランザクションのレコードを含む各ロ グ・ページを読み込みます。次に、そのトランザクションによって参照さ れるすべてのデータ・ページとインデックス・ページを読み込んでタイム スタンプを確認し、トランザクションのロールバックまたはロールフォ ワードを実行します。その後、完了したトランザクションに対して次々と 同じ作業を実行し、データベースに対するすべてのトランザクションが処 理された状態にします。2 つの独立した非同期プリフェッチ・アクティビ ティ ( ログ・ページ自体に対する非同期プリフェッチ、および参照される データ・ページとインデックス・ページへの非同期プリフェッチ ) により、 リカバリが高速化されます。 ログ・ページのプリフェッチ トランザクション・ログは、各アロケーション・ユニットのエクステン トを満たしながら、ディスクに連続的に記憶されます。リカバリ・プロ セスは、新しいアロケーション・ユニットからログ・ページを読み込む たびに、ログで使用されているアロケーション・ユニットのページをす べてプリフェッチします。 独立したログ・セグメントを持たないデータベースでは、同じアロケー ション・ユニットにログとデータ・エクステントが混在している場合があ ります。この場合にも非同期プリフェッチはアロケーション・ユニットの すべてのログ・ページをフェッチしますが、予備セットはより小さくなる 可能性があります。 データとインデックス・ページのプリフェッチ Adaptive Server はトランザクションごとにログをスキャンし、参照され る各データ・ページと各インデックス・ページから予備セットを構築し ます。1 つのトランザクションのログ・レコードを処理している間に、非 同期プリフェッチは、ログ内の後続のトランザクションによって参照さ れるデータ・ページとインデックス・ページへの要求を発行し、現在の トランザクションより先のトランザクションまで読み込みます。 注意 リカバリは、デフォルト・データ・キャッシュ内のプールだけを使 用します。詳細については、 「リカバリ用の非同期プリフェッチ制限値の 設定」(251 ページ ) を参照してください。 240 Adaptive Server Enterprise 第 10 章 非同期プリフェッチのチューニング 逐次スキャン中の予備セット 逐次スキャンには、テーブル・スキャン、クラスタード・インデックス・ スキャン、カバード・ノンクラスタード・インデックス・スキャンが含ま れます。 テーブル・スキャンとクラスタード・インデックス・スキャンの間、非同 期プリフェッチは、オブジェクトが使用するページについてのアロケー ション・ページ情報を使って、予備セットを構築します。新しいアロケー ション・ユニットからページをフェッチするたびに、オブジェクトが使用 するアロケーション・ユニットのすべてのページから予備セットが構築さ れます。 逐次スキャンがアロケーション・ユニット間をホップする回数は、ペー ジ・チェーンの断片化を計測するために保管されます。この値を使って 予備セットのサイズを調整し、断片化の程度が低い場合には大量のペー ジをプリフェッチし、程度が高い場合にはフェッチするページを少なく します。詳細については、 「ページ・チェーンの断片化」(245 ページ ) を 参照してください。 ノンクラスタード・インデックス・アクセス中の予備セット ノンクラスタード・インデックスを使ってローにアクセスする場合、非 同期プリフェッチは、ノンクラスタード・インデックス・リーフ・ペー ジで、条件を満たすすべてのインデックス値のページ番号を検索します。 また、必要なすべてのページのユニーク・リストから、予備セットを構 築します。 非同期プリフェッチは、条件を満たすローが 2 つ以上ある場合にだけ使用 されます。 ノンクラスタード・インデックス・アクセスが、いくつかのリーフレベ ル・ページを必要とする場合には、それらのページに対しても非同期プリ フェッチ要求が発行されます。 dbcc チェック中の予備セット 次の dbcc チェック中に非同期プリフェッチが使用されます。 • データベース内のすべてのテーブルおよびインデックスの割り付け をチェックする dbcc checkalloc と、それに対応するオブジェクトレ ベル・コマンド (dbcc tablealloc と dbcc indexalloc) • データベース内のすべてのテーブルとインデックスのリンクを チェックする dbcc checkdb と、個々のテーブルとそれらのインデッ クスをチェックする dbcc checktable パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 241 非同期プリフェッチによるパフォーマンスの向上 割り付けのチェック ページの割り付けをチェックする dbcc コマンド dbcc checkalloc、dbcc tablealloc、dbcc indexalloc は、アロケーション・ページの情報を検証し ます。割り付けをチェックする dbcc オペレーション用の予備セットは、 そのほかの逐次スキャン用の予備セットと似ています。スキャンがオブ ジェクトの別のアロケーション・ユニットに入ると、そのアロケーショ ン・ユニットでオブジェクトによって使用されるすべてのページから予備 セットが構築されます。 checkdb と checktable dbcc checkdb と dbcc checktable コマンドは、テーブルのページ・チェー ンをチェックし、ほかの逐次スキャンと同じ方法で予備セットを構築し ます。 チェック対象のテーブルにノンクラスタード・インデックスがある場合、 それらのインデックスは、ルート・ページから始めてデータ・ページへの すべてのポインタをたどり、再帰的にスキャンされます。リーフ・ページ からデータ・ページへのポインタをチェックするとき、dbcc コマンドは、 ノンクラスタード・インデックス・スキャンと似た方法で非同期プリ フェッチを使用します。リーフレベル・インデックス・ページがアクセス されると、そのリーフレベル・インデックス・ページで参照されているす べてのページのページ ID から予備セットが構築されます。 予備セットの最小および最大サイズ ある時点でのクエリの予備セットのサイズは、いくつかの要因によって決 定されます。 • クエリのタイプ ( 逐次スキャン、ノンクラスタード・インデックス・ スキャンなど ) • クエリが参照するオブジェクトによって使用されているプールのサ イズ、および各プールに対して設定されたプリフェッチ制限値 • スキャンを実行する処理の場合、テーブルまたはインデックスの断 片化 • 非同期プリフェッチ要求の最新の成功率と、I/O キューの過負荷状態、 およびサーバの I/O 限界 表 10-1 に、各タイプの非同期プリフェッチを使用した場合の最小サイズ と最大サイズをまとめます。 242 Adaptive Server Enterprise 第 10 章 非同期プリフェッチのチューニング 表 10-1: 予備セットのサイズ アクセス・タイプ アクション テーブル・スキャン クラスタード・インデック ス・スキャン カバード・リーフレベル・ スキャン 新しいアロケーション・ 最小サイズはクエリが必要とする 8 ページ。 ユニットからページを読 最大サイズは次のうち小さい方の値。 み込む。 • オブジェクトに属するアロケーション・ユニットの ページ数。 予備セットのサイズ ノンクラスタード・インデック ス・スキャン リーフ・ページで条件を 満たすローを探し、デー タ・ページのアクセスの 準備をする。 • リカバリ トランザクションをリカ バリする。 プールのプリフェッチ制限値。 最小サイズは 2 つの条件を満たすロー。 最大サイズは次のうち小さい方の値。 • リーフ・インデックス・ページ内で条件を満たす ローの、ユニークなページ番号の数。 • プールのプリフェッチ制限値。 最大サイズは次のうち小さい方の値。 • リカバリを実行中のトランザクションによって処理 されるすべてのデータ・ページとインデックス・ペー ジの数。 • デフォルト・データ・キャッシュ内にあるプールの プリフェッチ制限値。 トランザクション・ログ をスキャンする。 最大サイズは、ログに属するアロケーション・ユニット のすべてのページ数。 dbcc tablealloc、dbcc indexalloc、dbcc checkalloc ペ ー ジ・チ ェ ー ン を ス キャンする。 テーブル・スキャンと同じ。 dbcc checktable、 dbcc checkdb ペ ー ジ・チ ェ ー ン を ス キャンする。 テーブル・スキャンと同じ。 ノンクラスタード・イン デックスのデータ・ペー ジへのリンクをチェック する。 リーフレベル・ページで参照されるすべてのデータ・ ページ数。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 243 プリフェッチが自動的に無効になる場合 プリフェッチが自動的に無効になる場合 非同期プリフェッチは、プールまたは I/O サブシステムを溢れさせたり、 不要なページを読み込んだりすることなく、必要なページをバッファに フェッチしようとします。Adaptive Server は、プリフェッチされたページ がキャッシュ内に読み込まれてはいるが使用されていないことを検出す ると、非同期プリフェッチを一時的に制限または停止します。 プールの溢れ データ・キャッシュ内の各プールについて、設定可能なパーセンテージ 分のバッファを非同期プリフェッチで読み込み、最初に使用するときま で保管しておくことができます。たとえば、2K プールに 4000 バッファ があり、そのプールの制限値が 10% である場合には、最高 400 バッファ を非同期プリフェッチで読み込んで、未使用のままプール内に保管でき ます。プール内にある、プリフェッチされてアクセスされないバッファ 数が 400 に達すると、Adaptive Server はそのプールに対して一時的に非同 期プリフェッチを停止します。 プール内のページがクエリによってアクセスされるに従って、プール内 の未使用のバッファ数は減っていき、非同期プリフェッチが処理を再開 します。使用できるバッファの数が予備セット内のバッファ数よりも少 ない場合には、その数だけの非同期プリフェッチが発行されます。たと えば、400 バッファまで使えるプールに 350 の未使用バッファがあり、ク エリの予備セットが 100 ページの場合には、最初の 50 の非同期プリ フェッチが発行されます。 これにより、ページを読み込む前にキャッシュからページをフラッシュ する複数の非同期プリフェッチ要求によって、プールが溢れることを防 ぎます。プールごとの制限値によって発行できない非同期 I/O の数は、 sp_sysmon によってレポートされます。 I/O システムの過負荷 Adaptive Server とオペレーティング・システムは、サーバに対応する未処 理の I/O の数について、全体としての、およびエンジンごとの制限値を設 定します。設定パラメータ max async i/os per server と max async i/os per engine は、Adaptive Server でのこれらの制限値を制御します。使用し ているハードウェアで、これらのパラメータを設定する方法の詳細につ いては、オペレーティング・システムのマニュアルを参照してください。 設定パラメータ disk i/o structures は、Adaptive Server が予約するディス ク制御ブロックの数を制御します。各物理 I/O ( 読み書きされる各バッ ファ ) が I/O キューに入っている間は、1 つの制御ブロックを必要とし ます。 『システム管理ガイド』を参照してください。 244 Adaptive Server Enterprise 第 10 章 非同期プリフェッチのチューニング Adaptive Server は、max async i/os per server、max async i/os per engine、 または disk i/o structures を超える数の非同期プリフェッチ要求を発行し ようとすると、制限値に達するまでの要求を発行し、残りの要求を廃棄し ます。たとえば、ディスク I/O 構造体が 50 しか使用できないときに、サー バが 80 ページをプリフェッチしようとすると、50 の要求が発行されて残 りの 30 は廃棄されます。 sp_sysmon は、非同期プリフェッチ要求がこれらの制限値を超えた回数 をレポートします。詳細については、『パフォーマンス&チューニング・ ガイド:モニタリングと分析』の「非同期プリフェッチ・アクティビティ に関するレポート」(90 ページ ) を参照してください。 不要な読み込み 非同期プリフェッチは、不要な物理読み込みを避けようとします。リカバ リ中、およびノンクラスタード・インデックス・スキャン中は、予備セッ トが正確で、トランザクション・ログ内のページ番号、またはインデック ス・ページ内のページ番号によって参照されるページだけがフェッチされ ます。 テーブル・スキャン、クラスタード・インデックス・スキャン、dbcc チェックの予備セットはそれほど正確ではなく、不要な読み込みが発生す ることがあります。逐次スキャン中、次の理由によって不要な I/O が発生 することがあります。 • 全ページロック・テーブル上のページ・チェーンの断片化 • 複数のユーザによるキャッシュの過剰使用 ページ・チェーンの断片化 Adaptive Server のページ割り付けメカニズムは、同じオブジェクトに属す るページが、物理記憶領域内で互いに近い位置になるように配慮してい ます。これは、すでにオブジェクト用に割り付けられているエクステン トに新しいページを割り付け、オブジェクトがすでに使用しているアロ ケーション・ユニットに新しいエクステントを割り付けることによって 行われます。 しかし、ページの割り付けと割り付け解除が繰り返されると、データオン リーロック・テーブル上のページ・チェーンにねじれが発生することがあ ります。図 10-1 は、2 つのアロケーション・ユニットのエクステント間で ねじれたページ・チェーンの例を示しています。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 245 プリフェッチが自動的に無効になる場合 図 10-1: 複数のアロケーション・ユニットにまたがるページ・チェーンのねじれ 0 1 2 8 9 10 11 12 13 14 15 3 4 5 6 7 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 .. . 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 オブジェクトが使用する ページ OAM ページ アロケーション・ページ その他のページ 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 .. . 504 505 506 507 508 509 510 511 図 10-1 では、最初にスキャンでアロケーション・ユニット 0 のページを アクセスする必要が生じると、アロケーション・ページをチェックして非 同期 I/O を発行します。これは、スキャン対象のオブジェクトが使用する すべてのページに対する非同期 I/O であり、プールに設定されている制限 値を超えない範囲で実行されます。キャッシュ内でページが使用可能にな ると、クエリはページ・チェーンを順番にたどってそれらを処理します。 スキャンがページ 10 に達したとき、ページ・チェーン内の次のページで あるページ 273 はアロケーション・ユニット 256 に属しています。 ページ 273 が必要になると、アロケーション・ページ 256 がチェックされ、 そのオブジェクトに属するアロケーション・ユニットにあるすべてのペー ジに対して、非同期プリフェッチ要求が発行されます。 246 Adaptive Server Enterprise 第 10 章 非同期プリフェッチのチューニング ページ・チェーンが再びアロケーション・ユニット 0 のページをポイント する場合には、次の 2 つの可能性があります。 • アロケーション・ユニット 0 からプリフェッチされたページがキャッ シュにまだ残っている場合には、クエリは不要な物理 I/O なしで処理 を続行する。 • アロケーション・ユニット 0 からプリフェッチされたページが、アロ ケーション・ユニット 256 からの読み込みや、そのプールを使用する ほかのクエリによって発生したほかの I/O によってキャッシュから フラッシュされている場合には、クエリはプリフェッチ要求を再発行 しなければならない。この状況は、次の 2 つの方法で検出される。 • Adaptive Server による、アロケーション・ページ間のホップ数が 2 になった時点。サーバは、ホップ数とプリフェッチされたペー ジ数の比率を使用して予備セットのサイズを小さくし、I/O の発 行回数を減らす。 • プリフェッチされたにもかかわらず使用されないプール内の ページ数が大きくなると、プールの制限値に基づいて、非同期プ リフェッチが一時的に停止される場合がある。 非同期プリフェッチのチューニング目標 バッファ・プールの最適なサイズと最適なプリフェッチ・パーセンテージ を選択することは、非同期プリフェッチのパフォーマンスを向上させるた めの鍵です。複数のアプリケーションを同時実行するとき、うまくチュー ニングされたプリフェッチング・システムは、プール・サイズとプリフェッ チ制限値のバランスを取ることで次の目標を達成します。 • システム・スループットを向上させる。 • 非同期プリフェッチを使用するアプリケーションのパフォーマンス を向上させる。 • 非同期プリフェッチを使用しないアプリケーションのパフォーマン ス低下をなくす。 プール・サイズとプリフェッチ制限値の設定は動的に変更され、変動する 負荷のもとでのニーズに対応できます。たとえば、リカバリまたは dbcc チェック中に、パフォーマンスを高めるように非同期プリフェッチを設定 してから、Adaptive Server を再起動しないで再設定できます。 詳細については、「リカバリ用の非同期プリフェッチ制限値の設定」(251 ページ ) および 「dbcc 用の非同期プリフェッチ制限値の設定」(252 ペー ジ ) を参照してください。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 247 Adaptive Server のほかのパフォーマンス機能 設定用コマンド 非同期プリフェッチの制限値は、プール内にプリフェッチされたけれども 使用されないページを保管できるパーセンテージで設定します。次の 2 つ の設定レベルがあります。 • サーバ全体で使用するデフォルト。設定パラメータ global async prefetch limit で設定する。Adaptive Server を最初にインストールする とき、global async prefetch limit のデフォルト値は 10 (%) である。 詳細については、『システム管理ガイド』を参照。 • sp_poolconfig の設定でプールごとに設定できる。各プールに対して 設定されている制限値を調べるには、sp_cacheconfig を使用する。 詳細については、『システム管理ガイド』を参照。 非同期プリフェッチの制限値を変更するときは、Adaptive Server の再起 動を必要としないで、すぐに変更が有効になります。設定ファイルで、 グローバルな制限値とプールごとの制限値の両方を設定することもでき ます。 Adaptive Server のほかのパフォーマンス機能 この項では、非同期プリフェッチと Adaptive Server のほかのパフォーマン ス機能との相互作用について説明します。 大容量 I/O 大容量 I/O と非同期プリフェッチを組み合わせると、テーブル・スキャン を実行するクエリや dbcc 処理の I/O オーバヘッドが少なくなり、高速な クエリ処理ができます。 大容量 I/O がアロケーション・ユニットのすべてのページをプリフェッチ する場合、アロケーション・ユニット全体での I/O の最小数は次のとおり です。 • 31 回の 16K I/O • アロケーション・ページとエクステントを共有するページの場合、7 回 の 2K I/O 注意 大容量 I/O への参照は、論理ページ・サイズが 2K のサーバに基づき ます。ページ・サイズが 8K のサーバでは、I/O の基本単位は 8K になり ます。ページ・サイズが 16K のサーバでは、I/O の基本単位は 16K にな ります。 248 Adaptive Server Enterprise 第 10 章 非同期プリフェッチのチューニング 16K プールのサイズ設定と制限値 デフォルトの非同期プリフェッチ制限値 ( プール内のバッファの 10%) を 使って 31 回の 16K プリフェッチを実行するためには、少なくとも 310 回 の 16K バッファを持つプールが必要です。プールがこれより小さい場合、 または制限値がこれより低い場合には、一部のプリフェッチ要求が拒否さ れます。プールでより多くの非同期プリフェッチ・アクティビティを可能 にするには、より大きいプールを設定するか、またはプールに対してより 大きいプリフェッチ制限値を設定します。 複数の重複したクエリが同じプールを使ってテーブル・スキャンを実行す る場合、プール内でプリフェッチされるが使用されないページ数は、大き く設定する必要があります。クエリはおそらく、アクセス対象のページの 読み込みのさまざまな段階で、やや不規則な間隔でプリフェッチ要求を発 行します。たとえば、1 つのクエリが 31 ページ分をプリフェッチしたば かりで、プール内に 31 の未使用ページがあるにもかかわらず、前のクエ リでは未使用のページが 2 または 3 だったという場合もあります。このよ うなクエリに対するチューニング作業を開始するには、プリフェッチ要求 のページ数の半分に、プール内のアクティブ・クエリの数を乗算した値を 想定してください。 2K プールの制限値 逐次スキャン中に大容量 I/O を使用するクエリの場合でも 2K I/O を実行 することがあります。 • スキャンが新しいアロケーション・ユニットに入ると、ユニット内で アロケーション・ページと領域を共有する 7 ページに対して 2K I/O を実行する。 • プリフェッチ要求が発行された時点で、アロケーション・ユニットか らのページがすでに 2K プールに存在する場合には、そのエクステン トを共有するページを 2K プールに読み込む必要がある。 2K プールの非同期プリフェッチ制限値が 0 に設定されている場合は、最 初の 7 回の読み込みは通常の非同期 I/O によって行われ、キャッシュに ページが存在しなければクエリは読み込みごとにスリープします。プリ フェッチのパフォーマンスが低下しないよう、2K プールの制限値は十分 に大きく設定してください。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 249 Adaptive Server のほかのパフォーマンス機能 MRU ( 使い捨て ) スキャン スキャンが MRU 置換方式を使用する場合に、非同期プリフェッチによっ てバッファがキャッシュに読み込まれると、特殊な方法で処理されます。 まず、ウォッシュ・マーカではなくチェーンの MRU 終点にページがリン クされます。クエリがそのページをアクセスすると、バッファはプールの ウォッシュ・マーカに再リンクされます。この方式は、キャッシュの過使 用によって、ウォッシュ・マーカにリンクされたプリフェッチ済みバッ ファが使用されないうちに、キャッシュがフラッシュされることを防止す るのに役立ちます。この方式は、不要なページが大量にプリフェッチされ る場合を除くと、パフォーマンスに対してほとんど影響を及ぼしません。 不要なページが大量にプリフェッチされる場合には、それらのプリフェッ チされたページによって、キャッシュからほかのページがフラッシュされ る可能性がより大きくなります。 並列スキャンと大容量 I/O 並列クエリの場合、バッファ・プールの要求量が大きくなる可能性があり ます。同じプールに対して逐次クエリが動作している場合、各クエリは少 しずつ違った時点で発行され、各クエリが異なる実行段階にある ( すでに キャッシュに存在しているページをアクセス中のクエリもあれば、I/O 待 機中のクエリもある ) と仮定すると安全です。 並列実行によるバッファ・プールの要求量は、スキャンのタイプと並列度 に応じて異なります。ある種の並列クエリは、大量のプリフェッチ要求を 同時に発行する傾向があります。 ハッシュベース・テーブル・スキャン 全ページロック・テーブル上のハッシュベース・テーブル・スキャンでは、 複数のワーカー・プロセスが同じページ・チェーンをアクセスします。各 ワーカー・プロセスはテーブル内の各ページのページ ID をチェックしま すが、ページ ID がワーカー・プロセスのハッシュ値と一致するページの ローだけを検証します。 新しいアロケーション・ユニットからのページを必要とする最初のワー カー・プロセスは、そのユニットのすべてのページに対するプリフェッチ 要求を発行します。ほかのワーカー・プロセスのスキャンもやはり同じア ロケーション・ユニットからのページを必要とする場合、それらのワー カー・プロセスは、必要なページがすでに I/O 処理中であるか、すでに キャッシュ内に存在していることを発見します。最初に完了したスキャン が次のユニットに入ったときも、このプロセスが繰り返されます。 250 Adaptive Server Enterprise 第 10 章 非同期プリフェッチのチューニング ファミリ内でハッシュベース・スキャンを実行する 1 つのワーカー・プロ セスが停止 ( たとえばロック待機中など ) していないかぎり、ハッシュ ベース・テーブル・スキャンでは逐次プロセスよりもプール要求量が大き くなることはありません。複数のプロセスは、逐次プロセスよりもはるか に高速にページを読み込むことができるので、ページのステータスを未使 用から使用済みへ、より高速に変更します。 パーティションベース・スキャン パーティションベース・スキャンでは、複数のワーカー・プロセスが異な るアロケーション・ユニットに対して非同期プリフェッチを実行する可能 性があるので、プール要求量がより大きくなる傾向があります。複数のデ バイスの分割されたテーブルで、サーバごとの I/O 制限値やエンジンごと の I/O 制限値に達する可能性は少ないものの、プールごとの制限値によっ てプリフェッチが制限される可能性は大きくなります。 並列クエリが解析され、コンパイルされると、クエリはワーカー・プロセ スを起動します。4 つの分割からなるテーブルが 4 つのワーカー・プロセ スによってスキャンされる場合、各ワーカー・プロセスはその最初のアロ ケーション・ユニット内のすべてのページをプリフェッチしようとします。 この単一のクエリのパフォーマンスに対して最も望ましい結果は、16K プールのサイズと制限値が十分に大きく、124 (31*4) の非同期プリフェッチ 要求が処理でき、結果的にすべての要求が成功することです。各ワーカー・ プロセスはキャッシュ内のページを高速にスキャンし、次々と新しいアロ ケーション・ユニットに移って、大量のページに対するプリフェッチ要求 を次々と発行します。 非同期プリフェッチ制限値の特殊な設定 次のような特殊な目的のため、非同期プリフェッチの設定を一時的に変更 したい場合があります。 • リカバリ • 非同期プリフェッチを使用する dbcc 処理 リカバリ用の非同期プリフェッチ制限値の設定 Adaptive Server は、リカバリ中にデフォルト・データ・キャッシュの 2K プールだけを使用します。shutdown with nowait を使ってサーバを停止す るか、または電源異常やマシン障害のためサーバがダウンした場合には、 リカバリするログ・レコードの数が非常に多くなる場合があります。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 251 非同期プリフェッチ制限値の特殊な設定 リカバリを高速化するため、設定ファイルを編集して次のどちらか一方、 または両方の処理ができます。 • デフォルト・データ・キャッシュ内のほかのプールのサイズを小さく することにより、キャッシュ内の 2K プールのサイズを大きくする。 • 2K プールのプリフェッチ制限値を大きくする。 これらの設定変更は両方とも動的に実行されるので、リカバリの完了後に sp_poolconfig を使用し、Adaptive Server を再起動せずに値をリストアで きます。リカバリ・プロセスでは、master データベースのリカバリが完了 するとすぐ、ユーザがサーバにログインできます。データベースは一度に 1 つずつリカバリされ、特定のデータベースがリカバリされるとすぐ、 ユーザはそのデータベースの使用を開始できます。一部のデータベースが まだリカバリ中の場合には、競合が発生する可能性があり、デフォルトの データ・キャッシュの 2K プール内でのユーザ・アクティビティは重くな ります。 dbcc 用の非同期プリフェッチ制限値の設定 サーバでのほかのアクティビティが少ない時間帯にデータベース一貫性 チェックを実行している場合は、dbcc が使用するプールに対して非同期 プリフェッチ制限値を大きく設定すれば、一貫性チェックを高速化でき ます。 dbcc checkalloc は、該当するデータベース用のキャッシュに 16K プー ルがなければ、特殊な内部 16K バッファを使用できます。データベース 用の 2K プールがあり、16K プールがない場合は、dbcc checkalloc の実 行中、プールに対応するローカルのプリフェッチ制限値を 0 に設定して ください。16K 内部バッファの代わりに 2K プールを使用すると、実際 にパフォーマンスが低下する可能性があります。 252 Adaptive Server Enterprise 第 10 章 非同期プリフェッチのチューニング 高いプリフェッチ・パフォーマンスのための管理作業 テーブルのデータが何度も修正されるうちに、全ページロック・テーブル およびリーフ・レベルのインデックスでの、ページ・チェーンのねじれが 発生します。一般に、新しく作成したテーブルにはねじれは少ししかあり ません。ページの分割、新しいページの割り付け、ページの割り付け解除 を伴う更新、削除、挿入が繰り返されたテーブルでは、アロケーション・ ユニット間でページ・チェーンのねじれが発生している可能性があります。 テーブルにある元のローを 10 ~ 20% 以上修正した場合には、ページ・ チェーンのねじれによって非同期プリフェッチの効率性が損なわれていな いかチェックしてください。ページ・チェーンのねじれによって非同期プ リフェッチのパフォーマンスが低下している疑いがあれば、インデックス を再作成するか、またはテーブルを再ロードしてねじれを減らす必要があ ります。 ヒープ・テーブルのねじれの除去 全ページロック・ヒープでは、1 つのページ内のローを削除することに よってページが割り付け解除される場合を除いて、一般にページの割り 付けは連続的です。オブジェクトに追加の領域が割り付けられると、こ れらのページを再使用できるようになります。クラスタード・インデッ クスを作成するか ( テーブルをヒープとして保管したい場合には、イン デックスを作成してから削除する )、データをバルク・コピーによってコ ピー・アウトし、テーブルをトランケートしてから、再びデータをコピー・ インできます。両方のアクティビティにより、テーブルが使用する領域 が圧縮され、ページ・チェーンのねじれが除去されます。 クラスタード・インデックス・テーブルのねじれの除去 クラスタード・インデックスでは、ページの分割とページの割り付け解除 により、ページ・チェーンのねじれが発生することがあります。クラス タード・インデックスを再構築しても、アロケーション・ページ間のリン クが必ずしもすべて除去されるわけではありません。クラスタード・イン デックスの増加が予測される場合は、fillfactor を使用し、データの修正に 起因するねじれの数を減らしてください。 ノンクラスタード・インデックスのねじれの除去 混合クエリがカバード・インデックス・スキャンを使用する場合、リーフ レベル・ページ・チェーンが断片化したら、ノンクラスタード・インデッ クスを削除して再作成することにより、非同期プリフェッチ・パフォーマ ンスを向上させることができます。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 253 パフォーマンス・モニタリングと非同期プリフェッチ パフォーマンス・モニタリングと非同期プリフェッチ statistics io の出力は、非同期プリフェッチが実行した物理読み込みの回 数と、通常の非同期 I/O が実行した読み込みの回数をレポートします。さ らに、statistics io は、キャッシュ内のページの検索が、キャッシュ・ス ピンロックを伴わずに非同期プリフェッチによって発見された回数もレ ポートします。 詳細については、 『パフォーマンス&チューニング・ガイド:モニタリン グと分析』の「物理 I/O と論理 I/O の統計値のレポート」(57 ページ ) を参 照してください。 sp_sysmon レポートには、“Data Cache Management” セクションと “Disk I/O Management” セクションの両方に非同期プリフェッチ情報が含まれて います。 sp_sysmon を使って非同期プリフェッチのパフォーマンスを評価すると、 次に示すような、ほかのパフォーマンス分野での向上が確認できる場合が あります。 • 非同期プリフェッチが有効となっているプールでのキャッシュ・ヒッ ト率の増加 • キャッシュ・ミスに起因するコンテキスト・スイッチの相対的な低下。 自発的なパフォーマンス増大をもたらす。 • ロック競合の低下。 クエリが必要とする次のページへの I/O の実行中、 タスクはページをロックする。非同期プリフェッチによるキャッ シュ・ヒットの増加によってこの時間が短くなり、ロックがより短時 間ですむ。 詳細については、 『パフォーマンス&チューニング・ガイド:モニタリン グと分析』の「データ・キャッシュ管理」(85 ページ ) と「ディスク I/O 管 理」(105 ページ ) を参照してください。 254 Adaptive Server Enterprise 第 11 章 複数のテンポラリ・データベース この章では、複数のテンポラリ・データベースについて説明します。 トピック名 テンポラリ・データベースの作成後 ページ 259 sp_tempdb の使用 260 テンポラリ・データベースとのバインド 260 複数のテンポラリ・データベースとシステム 262 インストールに関する注意事項 273 概要 Adaptive Server では、以前のバージョンの Adaptive Server では唯一のテン ポラリ・データベースであったシステム tempdb だけでなく、複数のテン ポラリ・データベースを作成および管理できます。 複数のテンポラリ・データベース (tempdbs ともいいます ) を使用すると、シ ステム・カタログやシステム tempdb のログに対する競合が削減されます。 次の処理が行えます。 • 高速アクセス・デバイスにテンポラリ・データベースを作成する。 • 記憶領域を再利用するためにテンポラリ・データベースを削除する。 • 特定の tempdbs を使って、テンポラリ・オブジェクトの作成タスクを 分割する。このため、これらのタスクはテンポラリ・データベース領 域を必要とするほかのセッションの干渉を受けなくなる。 複数のテンポラリ・データベース機能は、次の内容に完全に対応してい ます。 • 新規インストール • Adaptive Server 12.5 より前のバージョンからのアップグレードによる インストール • Adaptive Server 12.5 より前のバージョンからロードされたデータベース tempdb データベースは、システムにより作成されたテンポラリ・データ ベースです。Adaptive Server バージョン 12.5.0.3 より前では、tempdb は サーバ内で唯一のテンポラリ・データベースでした。テンポラリ・テーブ ルとワーク・テーブルは tempdb に作成されます。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 255 概要 Adaptive Server では複数のテンポラリ・データベースが作成できるため、テン ポラリ・データベースを使って、プライベートのテンポラリ・テーブルやワー ク・テーブルなどのテンポラリ・オブジェクトを作成できます。データベー ス管理者は、特定のテンポラリ・データベースに対して、または sp_tempdb を使用するテンポラリ・データベースの default グループに対して、“sa” ログ インとアプリケーションをバインドする、つまり、関係付けを行うことがで きます。default グループはシステムにより作成されたグループであり、メン バーとして少なくとも 1 つのシステム tempdb を持っています。このグループ にほかのテンポラリ・データベースを追加できます。 注意 オブジェクトを tempdb に明示的にバインドすることはできません。 グループにバインドされたアプリケーションには、そのグループ内のテンポラ リ・データベースがラウンドロビン方式で割り当てられます。 注意 ユーザ・グループと default テンポラリ・データベース・グループに関連 性はありません。 ユーザ作成のテンポ ラリ・データベース ユーザ作成のテンポラリ・データベースは、通常はデータベース管理者によっ て作成されます。これらのデータベースは通常、システム tempdb におけるリ ソース競合 ( システム・カタログやログの競合など ) を最小限に抑えるために 作成されます。ユーザ作成のテンポラリ・データベースは、次の点でシステム tempdb に非常によく似ています。 • 主に、テンポラリ・オブジェクトを作成するために使われる。 • システムリカバリ・プロセス中に、リカバリされるのではなく、再作成さ れる。 停止前またはクラッシュ前のテンポラリ・データベース内のオブジェクトは、 リカバリ・プロセス中にすべて消失しますが、これはテンポラリ・データベー スが model データベースによって上書きされるためです。システム tempdb に 適用されるこれらの制約は、ユーザ作成のテンポラリ・データベースにも適用 されます。詳細については、 「ロールバックとリカバリ」(264 ページ ) を参照 してください。 システム tempdb とは異なり、ユーザ作成のテンポラリ・データベースは削除 できます。 テンポラリ・データ ベースとバインド 256 セッションは、ログイン時に、現在有効なバインドに基づいてテンポラリ・ データベースに割り当てられます。 • オンラインの、使用可能な特定のテンポラリ・データベースにバインドが 設定されている場合、セッションはこのテンポラリ・データベースに割り 当てられます。 • バインドが default グループに設定されている場合は、そのグループのテン ポラリ・データベースがラウンドロビン選択方式によって選択されます。 Adaptive Server Enterprise 第 11 章 • 複数のテンポラリ・データベース バインドが指定されていない場合は、default グループからテンポラリ・デー タベースが選択されます。 セッションで選択されたテンポラリ・データベースは、そのセッション期間中 は有効であり、バインドに変更が加えられた場合でも、テンポラリ・データ ベースが変更されることはありません。 いったんセッションがテンポラリ・データベースに割り当てられると、その セッション中に作成されたテンポラリ・オブジェクトはすべてテンポラリ・ データベースに作成されます。これらのオブジェクトは、セッションまたは サーバの停止時に自動的に削除されます。共有テンポラリ・テーブルは、サー バ停止時に自動的に削除されます。 注意 テンポラリ・テーブルはセッションによって明示的に削除されることが あります。 サーバまたは共有テンポラリ・テーブルは、データベース名とテーブル名を含 めるために “tempdb..server_temptab” として完全修飾されている場合、シス テム tempdb に継続的に作成されます。この処理は、共有テンポラリ・テーブ ルを使ってセッション間で情報を渡す既存のアプリケーションが作業を継続 できることを目的としています。ただし、新規アプリケーションはユーザ作成 の tempdbs を使って共有テンポラリ・テーブルを作成できます。 プライベート・テンポ ラリ・テーブル プライベート・テンポラリ・テーブルはセッションごとに作成され、それぞれ の名前の先頭に “#” 記号を使用します ( 例:#pubs)。プライベート・テンポラ リ・テーブルはセッション間で共有できません。これらのテンポラリ・テーブ ルとワーク・テーブルは、セッションが割り当てられたテンポラリ・データ ベースに常駐します。プライベート・テンポラリ・テーブルには 2 つのタイプ があります。これらは、それぞれの可視スコープと暗黙に存在する期間によっ て区別されます。 • セッション・テンポラリ・テーブル - プロシージャの外部のバッチ・レ ベルで作成されます。このタイプのプライベート・テンポラリ・テーブル は次の特徴を備えています。 • すべてのコマンドで使用可能である。作成中のセッション内で実行さ れるプロシージャも含まれる。 • セッションが終了すると、自動的に削除される。 バッチ・レベルで実行される次の create 文によって、プライベート・テ ンポラリ・テーブルが作成されます。 create table #t1(id int, desc varchar(250)) • プロシージャ・テンポラリ・テーブル - プロシージャ内で作成され、次 の特徴を備えています。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 257 概要 • プロシージャ・テンポラリ・テーブルを作成するプロシージャと、プ ロシージャ・テンポラリ・テーブルを呼び出す任意のネスト・プロ シージャで使用可能である。 • 作成プロシージャが終了すると、自動的に削除される。 次の文では、2 つのプロシージャ・テンポラリ・テーブルが作成されます。 create procedure SetupTempTables as create table #pt1( . . . ) create table #pt2( . . . ) アプリケーションは、システム tempdb に共有テンポラリ・テーブルを作成す る場合と同じ方法で、ユーザ作成のテンポラリ・データベース内に共有テンポ ラリ・テーブルを作成できます。協調プロセスにおいて、これらのテーブル間 の通信ができます。 注意 プロシージャ・テンポラリ・テーブルは明示的に削除することもできます。 プライベート・テンポラリ・テーブルを作成したりアクセスしたりするストア ド・プロシージャは、セッションに割り当てられたテンポラリ・データベース についてこのような処理を行います。 共有テンポラリ・ テーブル 共有テンポラリ・テーブルは、システム tempdb の中だけでなく、ユーザ作成 のテンポラリ・データベースでも作成できます。すべての共有テンポラリ・ テーブルはセッション間で共有でき、サーバのリブート時に自動的に削除され ます。 注意 システム tempdb とは異なり、ユーザ作成のテンポラリ・データベース は削除できます。削除済みのユーザ作成のテンポラリ・データベースに依存 するアプリケーションは、共有テンポラリ・テーブルが存在していると動作 しません。 258 Adaptive Server Enterprise 第 11 章 複数のテンポラリ・データベース テンポラリ・データベースの作成後 新規に作成されたテンポラリ・データベースの dbid は、使用可能なすべての テンポラリ・データベースのグローバル・リストに自動的に登録されます。こ のデータベースがグローバル・リストに登録されるまで、オブジェクトをこの データベースにバインドすることはできません。サーバを再起動すると、テン ポラリ・データベースは、リカバリされると同時にグローバル・リストに追加 されます。 サポートされるテンポラリ・データベースの数は静的に宣言されます。これは、 設定できるものではありません。バインドに使用可能な ( したがって、セッ ションに割り当て可能な ) テンポラリ・データベースのグローバル・リストに 登録できるテンポラリ・データベースの数は 512 であり、これには tempdb も 含まれます。 グローバル・リストが満杯になった場合は、テンポラリ・データベースをグ ローバル・リストに追加しようとすると、警告が表示されます。リストの内容 を確認するには、dbcc pravailabletempdbs コマンドを実行します。詳細につ いては、「dbcc pravailabletempdbs」(272 ページ ) を参照してください。 データベースの dbid をグローバル・リストに登録できない場合でも、そのデー タ ベ ー ス を 作 成 で き ま す。グ ロ ー バ ル・リ ス ト が 満 杯 の 場 合 は、 dbcc addtempdb コマンドを実行すると、使用可能な領域が生じたときに dbid をグローバル・リストに追加できます。dbcc addtempdb コマンドの詳細につ いては、「dbcc addtempdb」(273 ページ ) を参照してください。 また、テンポラリ・データベースが削除されてグローバル・リストに使用可能 な領域が生じると、次の処理が可能になります。 • テンポラリ・データベースの削除と再作成。このときに、グローバル・リ ストで使用可能になった領域を使ってテンポラリ・データベースが登録 され、バインドに使用できるようになる。 • サーバを再起動する。 注意 dbid の値が 2 であるシステム tempdb は、サーバの再起動時にグローバ ル・リストに登録されます。これは登録解除できません。 Adaptive Server は、作成したテンポラリ・データベースが default グループにバ インドされていないものと想定しています。default グループに新しいデータ ベースを追加するには、sp_tempdb を使用します。詳細については、 『リファ レンス・マニュアル:プロシージャ』の「sp_tempdb」の項を参照してくださ い。データベースをグループに追加すると、そのデータベースは、グループ内 からラウンドロビン方式で即時に割り当てられるようになります。 データベースが default グループに組み込まれていない場合でも、アプリケー ションまたはログイン・バインドによってセッションに割り当てることができ ま す。詳 細 につ いては、『リファレ ンス・マニュア ル:プロシージャ』の 「sp_tempdb」の項にある bind オプションを参照してください。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 259 sp_tempdb の使用 sp_tempdb の使用 sp_tempdb を使用すると、次の処理が行えます。 • default テンポラリ・データベース・グループを作成する。 • テンポラリ・データベースを default テンポラリ・データベース・グルー プにバインドする。 • “sa” ログインとアプリケーションを default テンポラリ・データベース・ グループまたは特定のテンポラリ・データベースにバインドする。 sp_tempdb の構文は次のとおりです。 sp_tempdb [ [ { create | drop } , groupname ] | [ { add | remove } , tempdbname, groupname ] | [ { bind, objtype, objname, bindtype, bindobj [, scope, hardness ] } | { unbind, objtype, objname [, scope ] } ] | [ unbindall_db, tempdbname ] | [ show [, "all" | "gr" | "db" | "login" | "app" [, name ] ] | [ who, dbname ] [ help ] ] 詳細なパラメータと使用法については、 『リファレンス・マニュアル:プロシー ジャ』を参照してください。 テンポラリ・データベースとのバインド sp_tempdb bind を実行するには、次の処理が必要です。 条件 処理 objtype が login_name objname には有効なログイン名、 scope には NULL を指定する。 objtype が application objname にはアプリケーション名、scope には NULL を指定 する。 条件 処理 bindtype が group bindobj には、バインド先の既存グループの名前を指定する。 この場合は default。 bindtype が database bindobj には既存のテンポラリ・データベース名を指定する。 tempdb には明示的なバインドを設定できないため、ここで は tempdb は使用できない。 sp_tempdb bind が正常に実行されると、このバインドを表す新しいエントリ が sysattributes に挿入されます。 sp_tempdb bind に指定した objname/objtype/scope の組み合わせに対してエン トリがすでに存在している場合、その sysattributes 内のエントリは、指定した bindtype と bindobj によって表される新規情報で更新されます。 260 Adaptive Server Enterprise 第 11 章 複数のテンポラリ・データベース 新しく作成したバインドは即時に有効になりますが、すでにテンポラリ・デー タベースに割り当てられているセッションは、そのまま元の割り当てを維持し ます。新規バインドの影響を受けるのは、新しいセッションだけです。 注意 アプリケーションは、 セッションを接続して開始した後であっても、ct_lib や jConnect などのインタフェースを使って名前を変更できます。名前を変更し ても、セッションに対するテンポラリ・データベースの割り当ては影響を受け ません。これは、setuser コマンドにも当てはまります。 “sa” を専用のテンポ ラリ・データベース にバインドする “sa” ログインを別個のテンポラリ・データベースにバインドすると、メンテナ ンスと障害時のリカバリに対応できます。ほかのアプリケーションやユーザの テンポラリ・データベースのアクティビティから “sa” ユーザを独立させるこ とで、“sa” ユーザは必要な場合にテンポラリ・データベースのリソースにアク セスできることが保証されます。 セッションのバインド ログイン時にセッションがテンポラリ・データベースに割り当てられます。こ の割り当てはセッション期間中ずっと有効であり、変更できません。バインド は sysattributes から読み込まれ、次のように条件に応じて選択されます。 • タイプ LG ( ログイン ) のバインドが存在する場合は、そのバインドを使 用する。 • タイプ AP ( アプリケーション名 ) のバインドが存在する場合は、そのバ インドを使用する。 • default グループ内では、セッションをテンポラリ・データベースにバイ ンドする。 バインドには、ハードまたはソフトがあります。 • ソフト・バインド - 有効なバインドに従ってテンポラリ・データベース をセッションに割り当てられなかった場合でも、ログインは必ず正常に実 行されます。その他のすべてが失敗した場合、セッションは常にシステム tempdb に割り当てられた状態で終了します。 • ハード・バインド - 有効なバインドに従ってテンポラリ・データベース をセッションに割り当てられない場合、ログインは失敗します。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 261 複数のテンポラリ・データベースとシステム 複数のテンポラリ・データベースとシステム この項では、Adaptive Server に対する複数のテンポラリ・データベース機能の 影響について説明します。 システム・テーブルの変更 複数のテンポラリ・データベース機能は sysattributes と sysdatabases に影響 します。 sysattributes 表 11-1 に、テンポラリ・データベース・グループとそのバインドが sysattributes システム・テーブルに表示されるときの表記を示します。関係するカラムのみ を示します。それ以外のカラムはすべて NULL です。グループは、attribute の 値が “0” のローで表されます。ログインとアプリケーションのバインド、およ びデータベースとグループとのバインドは、attribute の値が “1” のローで表さ れます。 class attribute 表 11-1: sysattributes の表記 object_type object_cinfo object object_cinfo1 int_value char_value 16 0 GR グループ名 NULL NULL 16 0 D グループ ID NULL NULL 16 1 LG データ ベース名 NULL グループ ID NULL ユーザ ID ソフトの場合は 0、 データベース ハードの場合は 1。 の場合は 0、 グループの場 合は 1。 データベー ス名または グループ名。 16 1 AP NULL ソフトの場合は 0、 データベース ハードの場合は 1。 の場合は 0、 グループの場 合は 1。 データベー ス名または グループ名。 アプリケー ション名 NULL sysdatabases sysdatabases は status3 フィールドで新しいビットをサポートします。データ ベースのテンポラリ・ステータスは、sysdatabases エントリの status3 フィー ルドで 0x00000100 (10 進数では 256) の値によって示されます。 262 Adaptive Server Enterprise 第 11 章 複数のテンポラリ・データベース @@tempdbid グローバル変数 @@tempdbid は、セッションに割り当てられたテンポラリ・データベースの 有効なテンポラリ・データベース ID (dbid) を返します。 例 例 1 セッションに割り当てられたテンポラリ・データベース、mytempdb の dbid を返します ( この場合は 7)。 select @@tempdbid from mytempdb 7 例 2 テンポラリ・データベースの名前を返します ( この場合は mytempdb)。 select db_name(@@tempdbid) mytempdb tempdb_id() 関数 tempdb_id() は、指定のセッションが割り当てられているテンポラリ・データ ベースをレポートします。tempdb_id() 関数の入力はサーバ・プロセス ID で あり、その出力はプロセスが割り当てられているテンポラリ・データベース です。サーバ・プロセスが指定されない場合、tempdb_id() は現在のプロセス に割り当てられているテンポラリ・データベースの dbid をレポートします。 指定のテンポラリ・データベースに割り当てられているサーバ・プロセスをす べて検索するには、次の文を実行します。 select spid from master..sysprocesses where tempdb_id(spid) = db_id("tempdatabase") 注意 select tempdb_id() は、select @@tempdbid と同じ結果になります。 ログ・トランケーション Adaptive Server では、ユーザ作成のテンポラリ・データベースは tempdb ログ と同じ方法でトランケートされます。テンポラリ・データベースでシステム・ チェックポイント・プロセスを実行すると、tempdb ログとユーザ作成のテン ポラリ・データベースが両方とも、trunc log on chkpt オプションのためにト ランケートされます。これは、ユーザがテンポラリ・データベースのチェック ポイントを開始したときではなく、システムがチェックポイントを開始したと きのみ、適用されます。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 263 複数のテンポラリ・データベースとシステム ロールバックとリカバリ ユーザ作成のテンポラリ・データベースのリカバリ・プロセスは、通常のデー タベースのリカバリ・プロセスと大きく異なります。 システム tempdb とユーザ作成のテンポラリ・データベースとの間で、実行時 取り消しロールバックに違いはありません。 リカバリ再開始プロセスは、tempdb の場合とほとんど同じです。ユーザ作成 のテンポラリ・データベースが sysusages のエントリを使って作成され、そ の上に model データベースがコピーされます。停止前にテンポラリ・データ ベースに存在していたユーザ作成のオブジェクトはすべて消失します。 テンポラリ・データベースは、sysdatabases に表示される順序でリカバリさ れます。別のリカバリ順序を指定するには、sp_dbrecovery_order を使用し ます。 通常の割り当て先であるテンポラリ・データベースのリカバリの前にログイ ンするセッションは、ハード・バインドが設定されていないかぎり、別のテ ンポラリ・データベースに割り当てられます。ハード・バインドが設定され て い る 場 合、ロ グ イ ン は 失 敗 し ま す。こ の 影 響 を 最 小 限 に 抑 え る に は、 sp_dbrecovery_order を使って、すべての、または一部のテンポラリ・デー タベースがその他のユーザ・データベースよりも前にリカバリされるように 設定します。 リカバリが正常に行われると、テンポラリ・データベースは使用可能なテンポ ラリ・データベースのグローバル・リストに追加されます。さらに、default グ ループにバインドされている場合は、そのグループにも追加されます。 sysdatabases のテンポラリ・データベースの作成日時エントリは、データベー スが再作成された時間を反映しています。この日付は、テンポラリ・データ ベースが再作成されるごとに、リカバリ時に更新されます。 model データベースは、テンポラリ・データベースにコピーできるように、シ ステムのリカバリ中はロックされています。 注意 model はロックされているため、リカバリ・プロセスが完了するまで、新 規データベースを作成したり use model を使用することはできません。 264 Adaptive Server Enterprise 第 11 章 複数のテンポラリ・データベース テンポラリ・データベースの削除 テンポラリ・データベースは、次の場合のみ削除できます。 • バインドが関連付けられていない。 • アクティブなセッションが割り当てられていない。 したがって、データベースには次のことが要求されます。 • default テンポラリ・データベース・グループに組み込まれていない。 • ログインまたはアプリケーションがバインドされていない。 バ イ ン ド が 設定さ れて いると、drop database は 失敗 をレポ ート します。 default グループからデータベースを削除し、すべてのログインとアプリケー ションのバインドを解除してください。テンポラリ・データベースに関連し ているすべてのバインドを判別するには、sp_tempdb “show” インタフェース を使用します。 削除しようとしているデータベースにアクティブなセッションが接続されて いると、drop database は失敗します。このようなセッションは、データベー スのバインドが削除される前にインスタンス化された場合に存在する可能性 があります。削除プロセスを実行するには、これらのアクティブなセッション がシステムから完全になくなるまで待機するか、セッションを強制終了する必 要があります。指定のテンポラリ・データベースに現在接続しているセッショ ンを判別するには、sp_tempdb “who” dbname を使用します。 その他のデータベースの削除 データベースを削除するには、削除の対象となるデータベース内の Java クラ スがテンポラリ・データベース内のオブジェクトによって参照されていないこ とが必要です。このような参照は、select into #temptable コマンドを実行した 結果として存在することがあります。その場合は、テンポラリ・テーブルのカ ラムがソース・データベース内のクラスを参照します。このような参照が存在 していないか確認するために、すべてのテンポラリ・データベースがスキャン されます。参照が存在している場合、データベースは削除されません。 注意 この動作は、複数のテンポラリ・データベース機能を使わない場合の Adaptive Server の動作と一致しています。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 265 複数のテンポラリ・データベースとシステム alter database Adaptive Server は、一部の alter database オペレーションに対してデータをコ ピーします。これらのオペレーションでは通常、ページ内容のロギングは行わ れません。このため、サーバはページをディスクにフラッシュして、データ ベースのクラッシュ後に変更のリカバリが行われるようにします。ただし、 tempdb の内容は常にリカバリ・プロセス中に再作成されるため、tempdb に 対してこの処理を行う必要はありません。 また、ユーザ作成のテンポラリ・データベースもリカバリ中に新しく再作成さ れます。したがって、これらのデータベースは tempdb と一貫性を保持するよ うに扱われます。次に、これが alter database に適用される特別なケースにつ いて説明します。また、alter database のほかのインスタンスには、ユーザ作 成のテンポラリ・データベースに対する動作と tempdb に対する動作が同じも のもあります。 テンポラリ・データ ベースの拡張 システム tempdb が拡張されるときに、新規のデータベース・ページはゼロ設 定されません。アロケーション・ページのみがディスクに書き込まれます。 ユーザ作成のテンポラリ・データベースもこのアプローチに従って処理され ます。 model データベースの 拡張 model はサーバの再起動時にテンポラリ・データベースにコピーされるため、 model データベースは最小のテンポラリ・データベースよりも大きくできま せん。model のサイズを変更しようとすると、model の変更後のサイズが最 小のテンポラリ・データベースよりも大きくないことを検証するチェックが 開始されます。さらに小さいテンポラリ・データベースが見つかった場合、 alter database コマンドはエラーをレポートします。 キャッシュ特性 グループ内のテンポラリ・データベース間のキャッシュは、キャッシュ特性ご とに、それぞれ同じように設定します。オプティマイザは、効率的なクエリ・ プランを選択するときに、データベースのキャッシュ特性を考慮します。プラ ンがプロシージャの一部である場合、そのプランは別のテンポラリ・データ ベースに割り当てられている別のセッションによって再使用されることがあ ります。2 つのテンポラリ・データベースのキャッシュ特性が大きく異なると、 パフォーマンスが低下する可能性があります。 266 Adaptive Server Enterprise 第 11 章 複数のテンポラリ・データベース ユーザ作成のテンポラリ・データベースをデータ・キャッシュにバインドする sp_bindcache を使用して、データベースをデータ・キャッシュにバインドし ます。ユーザ作成のテンポラリ・データベースのバインド処理は、次の点を 除き、ほかのすべてのユーザ・データベースのバインド処理と同じです。 ユーザ作成のテンポラリ・データベースは、セッションが割り当てられている かぎり、使用中とみなされます。これは、アクティブなセッションに対して実 際にアクティビティが行われていない場合でも同様です。ただし、データベー スのキャッシュ・バインドを変更するには、データベースを排他的にロックす る必要があります。アクティブなセッションがデータベースに割り当てられて いるかぎり、そのデータベースはロックできません。これを回避する手順は、 データベースの削除に必要な手順と同じです。 ❖ データベースのキャッシュ・バインドを変更する 1 テンポラリ・データベースに関連するすべてのバインドを削除するには、 sp_tempdb を使用する。データベースと default グループとのバインド、 およびデータベースに対するアプリケーションとログインのバインドも すべて対象になる。 2 すでにテンポラリ・データベースに割り当てられている有効なセッション が完全になくなるまで待機するか、必要に応じてこれらのセッションを終 了する。sp_tempdb を使用して、データベースに割り当てられているア クティブなセッションをリストする。 3 データベースとキャッシュのバインドを続行する。 4 最初の手順で削除されたバインドをリストアする。 ストアド・プロシージャの処理 状況に応じて、テンポラリ・オブジェクトの dbid が現在のセッションのテン ポラリ・データベース ID に再マップされます。これは、これらのオブジェク トが適切なテンポラリ・データベースに作成され、アクセスされていることを 確認するためです。次に例を示します。 • ストアド・プロシージャがあるテンポラリ・データベースに付加されてい るセッションによって作成され、そのあとで別のテンポラリ・データベー ス内の別のセッションによってコンパイルされる場合。 • ストアド・プロシージャが、それを実行するセッションのテンポラリ・ データベースとは異なるセッションによってコンパイルされる場合。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 267 複数のテンポラリ・データベースとシステム ただし、テンポラリ・データベース ID を再マップしても、プロシージャの動 作がテンポラリ・データベース間で同じであることは保証されません。特定 のキャッシュ特性を持つテンポラリ・データベースでコンパイルされたプロ シージャは、異なるキャッシュ特性のテンポラリ・データベースで実行され る と き に、ま ったく 異なる 動作を とるこ とがあ ります。同 様に、特定 の dboption 設定をもつテンポラリ・データベースでコンパイルされたプロシー ジャは、異なる dboptions 設定のテンポラリ・データベースで実行されると きに、非常に異なるセマンティックを示すことがあります。 tempdb 書き込みの最適化 Adaptive Server は再起動時にテンポラリ・データベースを再作成するため、テ ンポラリ・データベースのリカバリはできません。Adaptive Server は、データ またはログ・バッファの書き込みを遅らせることで、この特性を利用します。 通常の非テンポラリ・データベースで、ログされていない select などのコマン ドを使用すると、Adaptive Server はリカバリのために、ディスクにそのデータ を保存します。 バージョン 12.5.0.3 以降、テンポラリ・データベースに対してはこの処理は行 われません。つまり、次の select into 文のようなコマンドをテンポラリ・デー タベースで使用すると、Adaptive Server はデータ・バッファのディスクへの書 き込みを強制しません。 select * into tempdb..temp_table from foo また、insert、update、delete などのコマンドをテンポラリ・データベースで 使用した場合にも、Adaptive Server がコミット操作の終わりにログの書き込み を強制的に実行することはありません。たとえば、次の insert into コマンドを 使用すると、コンテキストの切り替えが減少し、ログ・デバイスまたはデー タ・デバイスへの負荷が軽減され、スループットが向上します。 insert into tempdb..temp_table select * from foo 高可用性に関する考慮事項 次の各項では、高可用性設定での複数のテンポラリ・データベースに関する注 意事項について説明します。 高可用性の設定 複数のテンポラリ・データベース機能が組み込まれていない Adaptive Server の バージョンでは、初期の高可用性設定でユーザ・データベースがセカンダリ・ コンパニオンに存在することはありませんでした。ユーザ作成のテンポラリ・ データベースを導入すると、次のことが可能になります。 • 268 セカンダリ・サーバへのユーザ作成のテンポラリ・データベースの格納 ( データベース名がユニークな場合 )。 Adaptive Server Enterprise 第 11 章 • 複数のテンポラリ・データベース プライマリ・サーバの dbid と重複する dbid のあるユーザ作成のテンポラ リ・データベースの、セカンダリ・サーバへの格納 ( セカンダリ・サーバ とプライマリ・サーバで重複する dbids が双方のサーバでテンポラリ・ データベースに対応している場合 )。 Sybase では次のことをおすすめします。 • 高可用性の設定時にユーザ・データベースをロードする。これによって、 ユニークな dbid がセカンダリ・サーバ内のテンポラリ・データベース用 に生成され、ユーザはユーザ作成のテンポラリ・データベースを削除しな くても削除と再設定が行えます。 • 特定のアプリケーションとログインのバインドを、セカンダリ・サーバで 作成されたテンポラリ・データベース用のセカンダリ・コンパニオンにイ ンストールする。これは、フェールオーバ時にプライマリ・サーバ・アプ リケーションによって使用されることがあります。ただし、バインドをイ ンストールしない場合、フェールオーバしたアプリケーションはセカンダ リ・コンパニオンのデフォルト・グループ内のテンポラリ・データベース を使用します。この場合、パフォーマンスへの影響はほとんどありません。 プロキシ・データベースのサポート プロキシ・データベースは、次の理由から、複数のテンポラリ・データベース には作成されません。 • ユーザ作成のテンポラリ・データベースについては、データベースを再作 成する必要がある。これは、フェールオーバとフェールバック双方のパ フォーマンスに影響する。 • マウントを強制しないことによって、ユーザは、デュアルポート化されて いるとは限らないテンポラリ・データベースに対して高パフォーマンスの RAM、ディスク、ローカル・ディスクを展開できる。 • 高可用性プロキシは作成されないため、適切な設定に必要な領域を評価する 領域計算では、ユーザ作成のテンポラリ・データベースは対象にならない。 フェールオーバ・シナリオ フェールオーバ時は、ユーザ作成のテンポラリ・データベースはマウントされ ません。Adaptive Server ではフェールオーバ・ステータスでユーザ・データ ベースを作成できますが (set proxy オプションが有効になっていない場合 )、 フェールオーバ時にユーザ作成のテンポラリ・データベースを使用することは できません。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 269 複数のテンポラリ・データベースとシステム 正常なコンパニオン動作 ノーマル・コンパニオン・モードでは、ユーザ・データベースと同じルール ( たとえば、ユニークな名前を付けること ) で、ユーザ作成のテンポラリ・ データベースを作成できます。設定モードでは、with_proxydb オプションを 使用した場合でも、複数のテンポラリ・データベースに対するプロキシ・デー タベースは作成されません。 マウント/マウント解除 テンポラリ・データベースは、フェールオーバ時はマウントされません。セカ ンダリ・サーバにフェールオーバするクライアントは、通常のログイン・プロ セスを経て、セカンダリ・コンパニオンの既存のバインドに基づいて新規テン ポラリ・データベースに割り当てられます。 テンポラリ・データベースのダンプとロード テンポラリ・データベースはダンプできますが、ダンプしてもあまり意味があ りません。以下の点に注意してください。 270 • これらのデータベースはサーバが再起動するたびに再作成され、テンポ ラリ・テーブルのオブジェクト名がセッション別に内部で生成される。つ まり、同じユーザが 2 つの異なる isql セッションを通してサーバにログ インし、テンポラリ・テーブル #t1 を作成できる。内部で生成される名 前は、#t1 のインスタンスごとに作成される。このユニークな名前はテン ポラリ・データベースの sysobjects テーブルに保存される。したがって、 複数のアクティブなセッションに対して、ユーザ指定の同一名のテンポ ラリ・テーブルをそれぞれ専用に割り当てることができる。 • 複数のテンポラリ・データベースが有効になる前のサーバで作成されたシ ステム tempdb は、正常にダンプされるが、ロードできない。 • ユーザ作成のテンポラリ・データベースは正常にダンプされるが、ロード できない。 Adaptive Server Enterprise 第 11 章 複数のテンポラリ・データベース sp_dboption ストアド・プロシージャ グループ内のすべてのテンポラリ・データベースに同じ dboptions を使用する 必要があります。 これらのオプションに異なるものがあると、アプリケーションは正しく動作 しない場合があります。たとえば、グループ内で mtdb1 というテンポラリ・ データベースがこのオプションを有効にし、同じグループ内の mtdb2 という 別のテンポラリ・データベースがこのオプションを有効にしていない場合、次 に示す、テーブルを作成して 1 つのローを挿入し、1 つのフィールド値を削除 するというプロシージャが 2 つのテンポラリ・データベースで異なる動作を 示します。 create procedure P1 as create table #t1 (c1 int, str char(250)) insert #t1 values (1) go mtdb1 での insert 文は NULL が使用可能なために正常に処理されますが、 mtdb2 での insert 文は NULL が使用できないために失敗します。 オープン・データベース数の設定 作成するテンポラリ・データベースごとに、 「オープン・データベース」の設 定値を 1 ずつ増やしていきます。セッションがテンポラリ・データベースに割 り当てられている場合は、データベースを示すリソースが保存されており、現 在のセッション中に再使用されることのないように使用中とマークされてい ます。 変更されたプロシージャ 一部のストアド・プロシージャは、複数のテンポラリ・データベース機能が使 用できるように変更されました。 • sp_helpdb - データベースがユーザ作成のテンポラリ・データベースであ るかどうかをレポートします。これは、status カラムに表示されます。 sp_helpdb "mytempdb3" name db_size owner dbid created ------- ------- ----- ---- ------mytempdb 32.0 MB sa 7 Dec 12, 2001 • status ----select into/bulkcopy/pllsort, trunc log on chkpt, user created temp db sp_bindcache - 個別テーブルがユーザ作成のテンポラリ・データベース 内の名前付きキャッシュにバインドできないように拡張されています。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 271 複数のテンポラリ・データベースとシステム • sp_dboption - ユーザ作成のテンポラリ・データベースがシングルユー ザ・モードに設定できないように拡張されています。また、テンポラリ・ データベースに対してオプションを変更しようとすると、データベース・ オプションはすべてのテンポラリ・データベース間で一致している必要が あることを示す警告が発行されます。 • sp_dropuser - ユーザ作成のテンポラリ・データベースからゲスト・ユー ザを削除できないように拡張されています。 変更されない要注意のプロシージャ 次のプロシージャは変更されていませんが、テンポラリ・データベースに関連 するものです。 プロシージャ名 sp_changedbowner 説明 ユーザ作成のテンポラリ・データベースの所有者は変更できるが、tempdb を含むシステム・ データベースの所有者は変更できない。 sp_defaultloc tempdb を含むシステム・データベースはデフォルト・ロケーションにマップできない。た だし、ユーザ作成のテンポラリ・データベースはマップできる。 sp_renamedb tempdb を含めて、システム・データベースの名前は変更できない。ただし、ユーザ作成の テンポラリ・データベースの名前は変更できる。名前を変更するテンポラリ・データベー スの既存のバインドが削除され、新しいデータベース名で再作成されたことを確認する必 要がある。 変更および追加された DBCC いくつかの dbcc コマンドが新規に追加されました。 dbcc pravailabletempdbs dbcc pravailabletempdbs は、使用可能なテンポラリ・データベースのグロー バル・リストを出力します。 例 1> dbcc pravailabletempdbs 2> go Available temporary databases are: Dbid: 2 Dbid: 4 Dbid: 5 Dbid: 6 Dbid: 7 DBCC execution completed. If DBCC printed error messages, contact a user with System Administrator (SA) role. 272 Adaptive Server Enterprise 第 11 章 複数のテンポラリ・データベース dbcc addtempdb dbcc addtempdb は、使用可能なテンポラリ・データベースのグローバル・リ ストにテンポラリ・データベースを追加します。このコマンドの構文は次のと おりです。 dbcc addtempdb( dbid | dbname ) データベースが存在しない場合やテンポラリ・データベースでない場合は、エ ラーが生成されます。データベースがすでにリストに登録されている場合は、 情報メッセージが出力されます。 その他の変更 テンポラリ・データベースの使用状況に関する Resource Governor の制限値は、 ユーザ作成のテンポラリ・データベースに対して引き続き有効です。これは、 tempdb の場合と同じです。 大規模な割り付け解除は、テンポラリ・データベースのログに記録されません。 Replication Agent は、テンポラリ・データベースに対して起動しません。 並列クエリ 並列クエリの子スレッドは、その親と同じテンポラリ・データベースに割り当 てられます。 複数データベースの トランザクション テンポラリ・データベースと非テンポラリ・データベースにまたがる複数デー タベースのトランザクションは、テンポラリ・データベースでは開始できま せん。このようなトランザクションのリカバリが不可能なためです。ただし、 テンポラリ・データベースのみにまたがる複数データベースのトランザク ションは、この制約を受けません。テンポラリ・データベースは、サーバが 再起動するたびに再作成されるためです。 インストールに関する注意事項 default テンポラリ・データベース・グループを表す新しいローが、12.5 サー バへのアップグレードの一環として、また master デバイスが新規に構築され る場合に、sysattributes に追加されます。 すでに 12.5 サーバを実行しているためにアップグレードを行わない場合は、 sp_tempdb create “default” を実行することで、default テンポラリ・データベー ス・グループを追加できます。ストアド・プロシージャの詳細については、 『リ ファレンス・マニュアル:プロシージャ』の sp_tempdb の項目を参照してく ださい。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 273 インストールに関する注意事項 アプリケーション用のテンポラリ・データベースのサイズ指定と設定 テンポラリ・データベースに対するリソースと領域の要件は、アプリケーショ ンごとに異なります。すべてのテンポラリ・データベースのサイズは、次の場 合を除き、同じにします。 • リソースと領域の要件を完全に把握している。 • データベースの割り当てがリソースと領域の要件を満たすように、データ ベースとグループのバインドに従ってアプリケーションを設定している。 すべてのテンポラリ・データベースに同一のサイズを指定することで、アプリ ケーションまたはセッションの特定のインスタンスにどのデータベースが割 り当てられているかに関係なく、リソースや領域を消費し尽くすことなくアプ リケーションを実行できます。 同様に、使用される tempdb に関係なく、各クエリ・プランに同等のパフォー マンスが確保されるようにグループ内の tempdb キャッシュを設定します。 高可用性の設定では、tempdb プロパティに関してプライマリ・サーバとセカ ンダリ・サーバを同じように設定します。 共有テンポラリ・テーブル 共有テンポラリ・テーブルは、ユーザ作成のテンポラリ・データベースとシス テム tempdb の両方に作成できます。共有テンポラリ・テーブルの作成時に tempdb を使用する既存のアプリケーションは、引き続きこれらのテーブルを システム tempdb に作成します。このため、テンポラリ・データベース内の共 有可能テーブル間を通信する協調アプリケーションとセッションは、今までど おりに動作します。 新規アプリケーションは、ユーザ作成のテンポラリ・データベースにそれぞれ の共有テンポラリ・テーブルを作成できます。これは、tempdb に作成された 共有テンポラリ・テーブルと同じように機能します。つまり、ほかのセッショ ンにアクセスできます。また、明示的に削除された場合を除き、サーバが再起 動されるまで常駐しています。 注意 ユーザ作成のテンポラリ・データベースを使用するアプリケーションは、 指定されたユーザ作成のテンポラリ・データベースが削除されると、動作しな くなります。 274 Adaptive Server Enterprise 第 11 章 複数のテンポラリ・データベース ユーザ作成のストアド・プロシージャの更新 テンポラリ・テーブルが常に tempdb に存在していることを前提としている既 存のユーザ作成のストアド・プロシージャは、すべて変更する必要があります。 たとえば、プライベート・テンポラリ・テーブルの有無に関してシステム tempdb の sysobjects カタログをチェックするストアド・プロシージャは、有 効なチェックではなくなります。そのようなテーブルは割り当てられたテンポ ラリ・データベースに存在しており、それが tempdb のこともあるためです。 次に例を示します。 select db_name(@@tempdbid) go -----------------------------a_tempdb1 (1 row affected) create table #t1 (c1 int) go #t1 は、システム tempdb の sysobjects カタログには見つかりません。 use tempdb select name from sysobjects where name like "#%" name -----------------------------(0 rows affected) 代わりに、割り当てられた tempdb のカタログにこのエントリが存在しています。 declare @tempdb_name varchar(32) select @tempdb_name = db_name(@@tempdbid) use @tempdb_name go (1 row affected) select name from sysobjects where name like "#%" go name -----------------------------#t1__________00000270012069406 (1 row affected) パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 275 インストールに関する注意事項 以前のバージョンへのダウングレード この項では、複数のテンポラリ・データベース機能が有効な Adaptive Server バージョン 12.5.0.3 から Adaptive Server バージョン 12.5.0.2 にダウングレード する方法について説明します。 注意 12.5.0.2 より以前のバージョンは、バージョン 12.5.0.3 からのダウング レードに対応していません。 ❖ 複数 tempdb が有効な Adaptive Server からのダウングレード 1 sp_tempdb を使ってすべてのバインドを削除する。 2 すべてのユーザ作成のテンポラリ・データベースを削除する。 3 サーバを停止する。 4 Adaptive Server のバージョン 12.5.0.2 を起動する。 5 Adaptive Server バージョン 12.5.0.2 に組み込まれていた installmaster と instmsgs.ebf を使用して、システム・ストアド・プロシージャとシステム・ メッセージを再インストールする。 Adaptive Server バージョン 12.5.0.2 では、バージョン 12.5.0.3 からのダウ ングレードをサポートするために追加手順を実行する必要はない。 バージョン 12.5.0.2 は、バージョン 12.5.0.3 のユーザ作成のテンポラリ・ データベースを使ってツリーが正規化されている場合に、そのツリーを動 的にテキストから再定義できるように修正されている。 276 Adaptive Server Enterprise 第 1 2 章 tempdb のパフォーマンスについて この章では、tempdb データベースを使用する際のパフォーマンスの問題 について説明します。tempdb には、どのユーザでもオブジェクトを作成 で き ま す。tempdb は多くのプロセスによって暗黙的に使われます。 tempdb は、サーバワイドなリソースです。主に、内部ソート処理、ワー クテーブル作成、再フォーマット、および、ユーザが作成するテンポラ リ・テーブルとインデックスの保管などの目的に使用されます。 多くのアプリケーションが、tempdb 内にテーブルを作成するストアド・プ ロシージャを使って、複雑なジョインを効率的に作成したり、1 つのステッ プでは実行しにくい、ジョイン以外の複雑なデータ分析を実行します。 トピック名 tempdb の管理がパフォーマンスに及ぼす影響 ページ 277 テンポラリ・テーブルの種類と使い方 278 tempdb の初期割り付け 280 tempdb のサイズ設定 281 tempdb の配置 282 tempdb セグメントからのマスタ・デバイスの削除 282 tempdb の専用キャッシュへのバインド 284 テンポラリ・テーブルとロック 285 tempdb 内のログの最小化 285 テンポラリ・テーブルの最適化 286 tempdb の管理がパフォーマンスに及ぼす影響 tempdb を適切に管理することは、Adaptive Server の全体的なパフォーマン スにとって非常に大切です。tempdb は、見過ごすこともデフォルトのま ま放置することもできない重要なデータベースです。tempdb は、多くの サーバ上で最も動的なデータベースであるため、特別な配慮が必要です。 tempdb に関連する問題は、あらかじめ適切に計画しておけば、たいて いの場合、防ぐことができます。tempdb のサイズや配置が不適切な場 合には、次のような問題が発生します。 • tempdb が頻繁に満杯になるため、エラー・メッセージがユーザに対 して発行される。エラー・メッセージを受け取ったユーザは、領域が 使用可能になったときに、必要なクエリをもう一度実行しなければな らない。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 277 テンポラリ・テーブルの種類と使い方 • ソートに要する時間が長くなるが、ユーザにはなぜ自分のクエリのパ フォーマンスが低下するか分からない。 • システム・テーブルにロックが設定されるため、ユーザのクエリが一 時的にテンポラリ・テーブルを作成できなくなる。 • tempdb オブジェクトの使用頻度が高いため、他のページがデータ・ キャッシュからフラッシュされる。 tempdb パフォーマンス問題の主な解決方法 前述の主なパフォーマンス問題は、次の方法で簡単に解決できます。 • すべての Adaptive Server アクティビティに対して適切なサイズにな るように tempdb を設定する。 • tempdb の配置を最適化して、競合を最小限に抑える。 • tempdb を専用データ・キャッシュにバインドする。 • tempdb 内で設定するリソースのロックを最小限に抑える。 テンポラリ・テーブルの種類と使い方 ユーザ定義テンポラリ・テーブルが適切に使われているかどうかは、 Adaptive Server とアプリケーションの全体的なパフォーマンスに大きく 影響します。 テンポラリ・テーブルを使うメリットは非常に大きく、多くの場合、サー バが実行しなければならない作業が削減されます。しかし、テンポラリ・ テーブルを使うには、tempdb のサイズを大きくしなければなりません。 テンポラリ・テーブルは、その名のとおり一時的にしか存在しないものと、 永続的なものがあります。 tempdb には、次の 3 つの種類があります。 278 • 一時的なテンポラリ・テーブル • 正規のユーザ・テーブル • ワークテーブル Adaptive Server Enterprise 第 12 章 tempdb のパフォーマンスについて 一時的なテンポラリ・テーブル 次のように、テーブル名の最初の文字に “#” を使うと、一時的なテンポラ リ・テーブルを作成できます。 create table #temptable (...) または、 select select_list into #temptable ... テンポラリ・テーブルには次の特性があります。 • ユーザ・セッションの間だけ、またはテンポラリ・テーブルを作成す るプロシージャのスコープに対してだけ存在する。 • 複数のユーザ接続間では共有できない。 • セッションまたはプロシージャの終わりに自動的に削除される ( また は手動で削除できる )。 次のようにテンポラリ・テーブルにインデックスが作成されると、これら のインデックスは tempdb に保管されます。 create index tempix on #temptable(col1) 正規のユーザ・テーブル 次のように、テーブルを作成するコマンドにデータベース名を指定すると、 tempdb 内に正規のユーザ・テーブルを作成できます。 create table tempdb..temptable (...) または、 select select_list into tempdb..temptable tempdb 内の正規ユーザ・テーブルには次の特性があります。 • 複数のセッションにわたって存在できる。 • バルク・コピー・オペレーションによって使用することができる。 • パーミッションを付与すると、共有できる。 • 所有者が意識的に削除する必要がある ( そうしないと、Adaptive Server の再起動時に自動的に削除される )。 次のように指定すると、永続的なテンポラリ・テーブルに対するインデッ クスが tempdb 内に作成されます。 create index tempix on tempdb..temptable(col1) パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 279 tempdb の初期割り付け ワークテーブル ワークテーブルは、マージ・ジョイン、ソートなどの内部サーバ・プロセ ス用に Adaptive Server が tempdb 内に自動的に作成するテーブルです。 ワークテーブルには次の特性があります。 • 共有することはできない。 • コマンド完了時に消失する。 tempdb の初期割り付け Adaptive Server のインストール時には tempdb のサイズは 2MB であり、 図 12-1 に示すように、tempdb 全体がマスタ・デバイス上に置かれます。 一 般 的に は、システム管理者が最初に大きくする必要を感じるのが tempdb データベースです。サーバ上のユーザが増えるにつれ、大きくす る必要性が高くなります。tempdb は、マスタ・デバイスか他のデバイス 上にロケーションを変更できます。変更の必要性によっては、tempdb を 複数のデバイス間に分散保存する方法があります。 図 12-1: tempdb のデフォルトの割り当て tempdb データおよび ログ (2MB) d_master sp_helpdb を使って tempdb のサイズとステータスを表示します。次に、 インストール時の tempdb のデフォルト設定を表示する例を示します。 sp_helpdb tempdb name db_size owner dbid created status --------- -------- ------ ------ ----------- -------------------tempdb 2.0 MB sa 2 May 22, 1999 select into/bulkcopy device_frag size usage free kbytes ------------ -------- ------------ --------master 2.0 MB data and log 1248 280 Adaptive Server Enterprise 第 12 章 tempdb のパフォーマンスについて tempdb のサイズ設定 tempdb には、同時 Adaptive Server ユーザすべてが次のプロセスを処理で きるだけのサイズを設定します。 • マージ・ジョイン用のワークテーブル • distinct、group by、order by の実行、再フォーマット、OR 方式、およ びビューとサブクエリの実体化のために作成されるワークテーブル • テンポラリ・テーブル ( テーブル名の最初の文字に “#” が指定されて いるテーブル ) • テンポラリ・テーブルに設定されるインデックス • tempdb 内の正規ユーザ・テーブル • 動的 SQL が構築するプロシージャ アプリケーションによっては、テンポラリ・テーブルを使って複数の テーブルのジョインを分割する方がパフォーマンスが向上する場合が あります。こうした分割方式は、次の場合に使われます。 • 6 つ以上のテーブルをジョインするクエリのとき、適切なクエリ・プ ランをオプティマイザが選択しない場合 • 非常に大量のテーブルをジョインするクエリ • 非常に複雑なクエリ • 中間ステップとしてデータをフィルタする必要があるアプリケー ション 次の目的にも tempdb が使われます。 • いくつかのテーブルを非正規化していくつかのテンポラリ・テーブル にする。 • 集合処理を実行するために、非正規化されたテーブルを正規化する。 ほとんどのアプリケーションでは、tempdb をユーザ・データベースの 20 ~ 25% のサイズで作成することで十分な領域を確保できます。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 281 tempdb の配置 tempdb の配置 tempdb は、重要なアプリケーション・データベースの配置先とは別の物 理ディスクに保存します。使用可能なディスクの中で最速のディスクを使 います。プラットフォームが固体回路デバイスをサポートしており、アプ リケーションにとって tempdb を使うことがボトルネックである場合は、 固体回路デバイスを使います。tempdb を他のデバイス上で拡張したら、 マスタ・デバイスを system セグメント、default セグメント、logsegment セグメントから削除します。 master データベースと同じデバイス上で tempdb を拡張できても、別の デバイスを使うことをおすすめします。また、Adaptive Server のミラー リングを使用してミラーリングされるのは、データベースではなく論理 デバイスであることに注意します。マスタ・デバイスをミラーリングす る場合は、マスタ・デバイス内に常駐するデータベースのすべての部分 のミラーが作成されます。ミラーに「逐次」書き込みが使用されている 場合、tempdb データベースの使用頻度が高いと、パフォーマンスが著し く低下します。 tempdb セグメントからのマスタ・デバイスの削除 デフォルトでは、tempdb の system セグメント、default セグメント、 logsegment セグメントは、マスタ・デバイス上の tempdb の 2MB の割り 付けを含みます。tempdb に新しいデバイスが割り付けられると、新しい デバイスは自動的に system、default、logsegment の 3 つのセグメントの 一部になります。次のデバイスが tempdb に割り付けられると、default セ グメントと logsegment セグメントからマスタ・デバイスを削除できます。 このようにして、tempdb 内のワークテーブルと他のテンポラリ・テーブ ルは、マスタ・デバイス上で使用している他のテーブルとは競合しないこ とが確認できます。 マスタ・デバイスをセグメントから削除するには、次の手順に従います。 1 tempdb を別のデバイスに移動し終えていない場合は、移動します。次 に例を示します。 alter database tempdb on tune3 = 20 2 use tempdb コマンドを発行してから、セグメントからマスタ・デバ イスを削除します。 sp_dropsegment "default", tempdb, master sp_dropdegment system, tempdb, master sp_dropdegment logsegment, tempdb, master 282 Adaptive Server Enterprise 第 12 章 3 tempdb のパフォーマンスについて default セグメントがマスタ・デバイスを持っていないことを確認す るには、次のコマンドを発行します。 select dbid, name, segmap from sysusages, sysdevices where sysdevices.low <= sysusages.size + vstart and sysdevices.high >= sysusages.size + vstart -1 and dbid = 2 and status & 2 = 2 segmap カラムは、次のようにマスタ・デバイス上にある割り付けに は “1” をレポートし、system セグメントだけがマスタ・デバイスを 使っていることを示します。 dbid name segmap ------ --------------- ----------2 master 1 2 tune3 7 複数のディスクの場合の並列クエリのパフォーマンスの使用 図 12-2 に示すように、tempdb が複数のデバイスにまたがっている場合は、 一部のテンポラリ・テーブルまたはワークテーブルに、並列クエリのパ フォーマンスを利用できます。 図 12-2: 複数のディスクにまたがる tempdb disk_1 disk_2 disk_3 d_master tempdb パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン tempdb 283 tempdb の専用キャッシュへのバインド tempdb の専用キャッシュへのバインド Adaptive Server の通常の使用状況では、tempdb はテンポラリ・テーブル が作成され、データが挿入されて、削除されると、データ・キャッシュを 頻繁に使用します。 tempdb を専用データ・キャッシュに割り当てると、次のようなメリット があります。 • テンポラリ・オブジェクトに対するアクティビティが、デフォルト・ データ・キャッシュから他のオブジェクトをフラッシュしないように する。 • 複数のキャッシュ間で I/O を分散しやすくする。 詳細については、 「tempdb のキャッシュ・ニーズの調査」(230 ページ ) を 参照してください。 キャッシュ・バインド用コマンド sp_cacheconfig と sp_poolconfig コマンドを使って、名前付きデータ・ キャッシュを作成し、大容量 I/O に対応する指定サイズのプールを設定し ます。キャッシュとプールを設定できるのはシステム管理者だけです。 注意 大容量 I/O への参照は、論理ページ・サイズが 2K のサーバに基づき ます。ページ・サイズが 8K のサーバでは、I/O の基本単位は 8K になり ます。ページ・サイズが 16K のサーバでは、I/O の基本単位は 16K にな ります。 名前付きキャッシュとプールの設定方法については、『システム管理ガ イド』を参照してください。 キャッシュが設定され、サーバが再起動されたら、次のように指定して tempdb を新しいキャッシュにバインドできます。 sp_bindcache "tempdb_cache", tempdb 284 Adaptive Server Enterprise 第 12 章 tempdb のパフォーマンスについて テンポラリ・テーブルとロック テンポラリ・テーブルとそのインデックスを作成したり削除したりする と、tempdb のシステム・テーブル上でロックの競合が発生することがあ ります。tempdb 内にテーブルが作成されると、このテーブルに関する情 報は sysobjects、syscolumns、sysindexes などのシステム・テーブルに 保管されます。複数のユーザ・プロセスが tempdb 内のテーブルを作成ま たは削除している場合は、システム・テーブル上で多くの競合が発生しま す。内部的に作成されるワークテーブルは、システム・テーブル内に情報 を保管しません。 tempdb システム・テーブルに対する競合が、同じテンポラリ・テーブル・ セットを繰り返し作成、削除しなければならないアプリケーションにとっ て問題である場合は、アプリケーションの開始時にテーブルを作成するよ うにします。次に insert...select を使用してテーブルを移植し、truncate table を実行してすべてのデータ・ローを削除します。insert...select はロ ギングを必要とするので select into よりも時間がかかりますが、これで ロックの問題は解決します。 tempdb 内のログの最小化 trunc log on checkpoint データベース・オプションが tempdb 内でオンに なっていても、tempdb に対する変更はトランザクション・ログに書き込 まれます。tempdb 内のログ・アクティビティを減らすには、次の方法が あります。 • create table と insert の代わりに select into を使う。 • テンポラリ・テーブルに保管する必要のあるテーブルだけを選択する。 select into の使用 tempdb 内でテンポラリ・テーブルを作成して移植するときは、できる限り、 create table や insert...select ではなく select into を使います。select into/bulkcopy データベース・オプションは tempdb 内ではデフォルトでオン であるため、select into を使えます。 select into オペレーションは、最小限のログしか取られないため、create table や insert...select よりも速く動作します。記録されるのはデータ・ ページの割り付けだけであり、各データ・ローの実際の変更内容ではあり ません。insert...select クエリでは各データ挿入が完全にログされるため、 オーバヘッドが多くなります。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 285 テンポラリ・テーブルの最適化 ローを短くする tempdb 内にテーブルを作成するアプリケーションがテーブルのごくわず かなカラムしか使わない場合は、次の方法でログ・レコードの数とサイズ を最小限に抑えることができます。 • テーブルにデータを挿入する際に、select * を使用するのではなく、 アプリケーションに必要なカラムだけを選択する。 • 選択するローを、アプリケーションが必要とするローだけに限定する。 どちらの方法も、テーブルのサイズをより小さく抑えることができます。 テンポラリ・テーブルの最適化 多くの場合、テンポラリ・テーブルはごく短い間だけ単純な仕組みで使わ れるため、最適化の必要はほとんどありません。ただし、tempdb 内のテー ブルに複数回アクセスする必要のあるアプリケーションでは、最適化の方 式を検討する必要があります。最適化には通常、テーブルの作成やイン デックスの作成と、テーブルへのアクセスをプロシージャやバッチを 1 つ ではなく複数にすることで分離することが必要となります。テンポラリ・ テーブルのインデックスの動作条件は次のとおりです。 • テーブルには、インデックスが作成される時点でデータが存在してい なければならない。テンポラリ・テーブルが作成され、空のテーブル にインデックスが設定された場合、Adaptive Server はヒストグラムや 密度といった、カラム統計値を作成しない。インデックスを作成した 後でデータ・ローが挿入されても、オプティマイザには不完全な統計 値しか存在しない。 • インデックスを作成したり、update statistics を実行した後にローを追 加したり、削除したりした場合、オプティマイザには、最適なプラン を選択できない可能性がある。 図 12-3 に示すように、テーブルが使われるのと同一のストアド・プロシー ジャまたはバッチでテーブルが作成される場合は、クエリ最適化の時点で テーブルが作成されていないため、クエリ・オプティマイザはテーブルの サイズを判断できません。このことは、テンポラリ・テーブルと正規の ユーザ・テーブルにもあてはまります。 286 Adaptive Server Enterprise 第 12 章 tempdb のパフォーマンスについて 図 12-3: テンポラリ・テーブルの最適化と作成 クエリ 解析および 正規化 ここでクエリが最適化される çÝìK⪠最適化 コンパイル ÉRÉìÉpÉCÉã ここでテーブルが作成される 実行 結果 この場合オプティマイザは、テーブルのデータ・ページ数を 10、ロー数 を 100 であるとみなします。テーブルのサイズが実際に大きい場合は、こ の前提に基づいてオプティマイザは最良のクエリ・プランの次に良いと思 われるクエリ・プランを選択します。 テンポラリ・テーブルの最適化を向上させるには、次の 2 つの方法があり ます。 • テンポラリ・テーブルにインデックスを作成する。 • テンポラリ・テーブルを複雑に使用する場合は、複数のバッチまたは プロシージャに分割して、オプティマイザがテーブルについての情報 を収集できるようにする。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 287 テンポラリ・テーブルの最適化 テンポラリ・テーブルにインデックスを作成する。 テンポラリ・テーブルにインデックスを定義できます。多くの場合、テン ポラリ・テーブルにインデックスを定義すると、tempdb を使うクエリの パフォーマンスが向上します。オプティマイザはこのインデックスを通常 のユーザ・テーブルのインデックスと同じように使います。テンポラリ・ テーブルのインデックスの動作条件は次のとおりです。 • テーブルには、インデックスが作成される時点でデータが存在してい なければならない。テンポラリ・テーブルが作成され、空のテーブル にインデックスが設定された場合、Adaptive Server はヒストグラムや 密度といった、カラム統計値を作成しない。インデックスを作成した 後でデータ・ローが挿入されても、オプティマイザには不完全な統計 値しか存在しない。 • インデックスは、インデックスを使うクエリが最適化される間存在し ていなければならない。インデックスを作成してから、同一のバッチ またはプロシージャ内のクエリにこのインデックスを使用すること はできない。 • インデックスを作成したり、update statistics を実行した後にローを 追加したり、削除した場合、オプティマイザには、最適なプランを選 択できない可能性がある。 テンポラリ・テーブルを作成してから、テンポラリ・テーブルに対して大 量のオペレーションを実行する複雑なプロシージャでは特に、オプティマ イザにインデックスを与えることによってパフォーマンスが著しく向上 します。 テンポラリ・テーブルを使ってネスト・プロシージャを作成する 前述のプロシージャを作成するには、実行する手順を増やす必要があり ます。select_proc が存在しない限り base_proc を作成できず、テンポ ラリ・テーブルが存在しない限り select_proc を作成できません。具体 的には、次の手順に従います。 1 プロシージャの外にテンポラリ・テーブルを作成します。テンポラ リ・テーブルは空でもかまいません。テンポラリ・テーブルは、ただ 存在し、select_proc と互換性のあるカラムを持っている必要があり ます。次のように指定します。 select * into #huge_result from ... where 1 = 2 288 2 前述のように select_proc プロシージャを作成します。 3 #huge_result を削除します。 4 base_proc プロシージャを作成します。 Adaptive Server Enterprise 第 12 章 tempdb のパフォーマンスについて tempdb を使用する処理を複数のプロシージャに分割する たとえば、次のクエリは #huge_result に関して最適化問題を発生させ ます。 create proc base_proc as select * into #huge_result from ... select * from tab, #huge_result where ... 2 つのプロシージャを使うとパフォーマンスが向上します。base_proc プ ロシージャが select_proc プロシージャを呼び出すときに、オプティマイ ザはテーブルのサイズを判断できます。次に例を示します。 create proc select_proc as select * from tab, #huge_result where ... create proc base_proc as select * into #huge_result from ... exec select_proc #huge_result の処理に、複数のアクセス、ジョイン、または while が指定 されたループなどの処理が必要とされる場合は、#huge_result にインデッ クスを作成するとパフォーマンスが向上します。base_proc 内でインデッ クスを作成して、select_proc が最適化されるときにインデックスを使用 可能にします。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 289 テンポラリ・テーブルの最適化 290 Adaptive Server Enterprise 第 1 3 章 カーソルとパフォーマンス この章では、カーソルに関連するパフォーマンス上の問題について説明し ます。カーソルとは、SQL select 文の結果に一度に 1 ローずつ (set cursors rows を使う場合は一度に複数ローずつ ) アクセスするためのメカニズム です。カーソルが使うモデルは、通常の集合指向の SQL と異なり、カー ソルがメモリを使う方法とロックを保持する方法が、アプリケーションの パフォーマンスに影響します。特に、ページおよびテーブル・レベルでの ロック、ネットワーク・リソース、命令の処理に伴うオーバヘッドがカー ソル・パフォーマンスの問題となります。 トピック名 意味 ページ 291 各ステージで必要とされるリソース 294 カーソル・モード 297 インデックス使用とカーソルの動作条件 297 カーソルがある場合とない場合のパフォーマンスの比較 299 読み込み専用カーソルを使ったロック 303 独立性レベルとカーソル 304 分割されたヒープ・テーブルとカーソル 305 カーソルを最適化するために 305 意味 カーソルとは、select 文に対応するシンボリック名です。カーソルを使 うと、select 文の結果に一度に 1 ローずつアクセスできます。図 13-1 に、 authors テーブルにアクセスするカーソルを示します。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 291 意味 図 13-1: カーソルの例 select * from authors where state = ’KY’ にカーソルを使用 プログラミングが実行できること: - ローを調べる - ローの値に基づいて処理を行う 結果セット A978606525 Marcello Duncan KY A937406538 Carton Nita KY A1525070956 Porczyk Howard KY A913907285 Lane Bier KY カーソルは、select 文の結果セットの「ハンドル」と考えることができ ます。カーソルを使うと一度に 1 つずつローを調べることができ、場合 によっては操作も可能です。 集合指向プログラミングとロー指向プログラミング SQL は集合指向言語であるとみなされてきました。Adaptive Server は、集 合指向モードで動作する場合に非常にパフォーマンスが高くなります。 ANSI SQL 標準ではカーソルが必須であり、カーソルが必要とされる状況 では非常に有益です。しかし、カーソルがパフォーマンスを低下させる場 合もあります。 たとえば、次のクエリは、where 句の条件を満たすすべてのローに対して 同一の処理を実行します。 update titles set contract = 1 where type = ’business’ オプティマイザは、更新を実行するための最も効率のよい方法を検出し ます。しかし、カーソルは各ローを調べ、条件が一致すると更新を 1 回実 行します。アプリケーションは、select 文に対するカーソルの宣言、カー ソルのオープン、ローのフェッチ、ローの処理、次のローのフェッチ、 以降繰り返しという順序で動作します。アプリケーションは現在のロー の値に基づくため、まったく異なるオペレーションをする場合があり、 カーソル・アプリケーションに対応するサーバの総合的なリソース使用 の効率は、サーバの集合レベルのオペレーションよりも低くなる可能性 があります。しかし、カーソルは必要に応じて集合指向プログラミング よりも柔軟性を発揮できます。 図 13-2 に、カーソルを使用する手順を示します。カーソルの機能は、フ ローチャートの中央にある手順、つまりユーザまたはアプリケーション・ コードがローを調べ、ローの値に基づいて実行する内容を決定すること です。 292 Adaptive Server Enterprise 第 13 章 カーソルとパフォーマンス 図 13-2: カーソルのフローチャート カーソルを宣言する カーソルをオープンする ローをフェッチする ローを処理する ( 検索/更新/削除 ) はい 次のローに 進みますか ? いいえ カーソルをクローズする カーソルを割り付け解除する 例 次に、上記の「ローを処理する」の手順を、疑似コードで記述したカーソ ルの単純な例を示します。 declare biz_book cursor for select * from titles where type = ’business’ go open biz_book go fetch biz_book go /* Look at each row in turn and perform ** various tasks based on values, ** and repeat fetches, until ** there are no more rows パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 293 各ステージで必要とされるリソース */ close biz_book go deallocate cursor biz_book go ローの内容によっては、次のようにユーザが現在のローを削除します。 delete titles where current of biz_book または、次のように現在のローを更新します。 update titles set title="The Rich Executive’s Database Guide" where current of biz_book 各ステージで必要とされるリソース カーソルはメモリを使い、テーブル、データ・ページ、インデックス・ ページに対するロックを必要とします。カーソルがオープンされると、 メモリがカーソルに割り付けられ、生成されるクエリ・プランを保管し ます。カーソルがオープンになっている間に、Adaptive Server は意図的 テーブル・ロックも保持し、場合によってはロー・ロックまたはページ・ ロックを保持します。図 13-3 は、カーソル・オペレーション中のロック が行われている時期を示しています。 294 Adaptive Server Enterprise 第 13 章 カーソルとパフォーマンス 図 13-3: カーソル文が使うリソース カーソルを宣言する カーソルをオープンする ローをフェッチする ローを処理する ( 検索/更新/削除 ) はい 次のローに 進みますか ? ロー または ページ ロック いいえ テーブル ロック ( 意図的 ): メモリ いくつか のロー または ページ ロック カーソルをクローズする カーソルを割り付け解除する 図 13-3 と表 13-1 に示したメモリ・リソースの説明は、isql か Client-Library を使って送られるクエリ用の特別なカーソルに関するものです。ほかの種 類のカーソルでは、ロックは同じですが、カーソルのタイプによってメモ リの割り付けと割り付け解除に多少の違いが生じます。詳細については、 「メモリ使用と実行カーソル」(296 ページ ) を参照してください。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 295 各ステージで必要とされるリソース 表 13-1: isql と Client-Library クライアント・カーソルに対するロックと メモリの使用状況 カーソル・コマンド declare cursor リソース使用状況 open カーソルがオープンされると、Adaptive Server はメモリ をカーソルに割り付け、生成されるクエリ・プランを保 管する。サーバはクエリを最適化し、インデックスを検 索して、メモリ変数を設定する。ワークテーブルを構築 する必要があるとき以外は、サーバはローにアクセスし ない。しかし、必要なテーブル・レベル・ロック ( 意図 的ロック ) を設定する。ローやページ・ロックの動作は、 独立性レベル、サーバの設定、クエリの型に依存する。 カーソルが宣言されると、Adaptive Server はクエリ・テキ ストを保管するのに十分なメモリだけを使用する。 詳細については、『システム管理ガイド』を参照。 fetch fetch が実行されると、Adaptive Server は 1 つまたは複数 の必要なローを取り出して、指定された値をカーソル変 数に読み込むか、そのローをクライアントに送る。カー ソルがローまたはページのロックを保持する必要がある 場合、そのロックは fetch がローまたはページの外にカー ソルを移動させるまで、またはカーソルがクローズされ るまで保持される。カーソルの記述方法に基づいて、共 有ロックと更新ロックのいずれかが設定される。 close カーソルがクローズされると、Adaptive Server は、ロック とメモリ割り付けの一部を解放する。必要に応じてカー ソルをもう一度オープンできる。 deallocate cursor カーソルが割り付け解除されると、Adaptive Server はカー ソルが使用していた残りのメモリ・リソースを解放する。 カーソルを再使用するには、カーソルをもう一度宣言す る必要がある。 メモリ使用と実行カーソル 表 13-1 の declare cursor と deallocate cursor の説明は、isql か ClientLibrary を使って送られる特別なカーソルについての説明です。ほかの種 類のカーソルは、次のようにメモリを割り付けます。 296 • ストアド・プロシージャに対して宣言されているカーソルの場合は、 declare cursor 時には少量のメモリしか割り付けられない。ストアド・ プロシージャに対して宣言されたカーソルは Client-Library またはプ リコンパイラを使って送られ、execute cursors と呼ばれる。 • ストアド・プロシージャの内部で宣言されているカーソルの場合は、 すでにストアド・プロシージャに対してメモリが割り付けられている ので、declare 文は追加のメモリを必要としない。 Adaptive Server Enterprise 第 13 章 カーソルとパフォーマンス カーソル・モード カーソルには、読み込み専用と更新という 2 つのモードがあります。名前 から想像されるように、読み込み専用カーソルは select 文の結果のデータ を表示するだけですが、更新カーソルを使うと指定の更新と削除を実行で きます。 読み込み専用モードでは、共有ページ・ロックまたはロー・ロックを使 います。read committed with lock が 0 に設定されていて、クエリが独立 性レベル 1 で実行される場合、読み込み専用モードは一時的なロックを 使用し、次のフェッチまでページ・ロックまたはロー・ロックを保持し ません。 読み込み専用モードが有効になるのは、for read only が指定されている 場合、またはカーソルの select 文に distinct、group by、union、または集 合関数が指定されている場合です。状況によっては、select 文に order by 句が指定されている場合にもこのモードが有効になります。 更新モードは更新ページ・ロックまたは更新ロー・ロックを使います。 このモードは次の場合に有効になります。 • for update が指定されている場合 • select 文に、distinct、group by、union、サブクエリ、集合関数、また は at isolation read uncommitted 句が指定されていない場合 • shared が指定されている場合 column_name_list を指定すると、そのカラムだけが更新可能になります。 カーソル処理中のロックの詳細については、 『システム管理ガイド』を参 照してください。 カーソルを宣言するときにカーソル・モードを指定します。select 文に指 定されるオプションによっては、更新モードを宣言してもカーソルが更新 できないことがあります。 インデックス使用とカーソルの動作条件 カーソル内でクエリが使用される場合、そのクエリは、カーソル外で使用 するのとは異なるインデックスを要求または選択することがあります。 全ページロック・テーブル 読み込み専用カーソルの場合は、独立性レベル 0 ( ダーティ・リード ) の クエリはユニーク・インデックスを要求します。独立性レベル 1 または 3 の読み込み専用カーソルは、カーソルの外の select 文と同一のクエリ・プ ランを生成します。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 297 インデックス使用とカーソルの動作条件 更新可能カーソルがインデックスを必要とすることは更新可能カーソル が読み取り専用カーソルとは異なるクエリ・プランを使うことがあるとい うことを意味します。更新可能カーソルがインデックスを必要とする条件 は次のとおりです。 • カーソルが更新カーソルとして宣言されていない場合は、ユニーク・ インデックスがテーブル・スキャンまたはユニークでないインデック スに優先する。 • for update of リストが指定されずにカーソルが更新カーソルとして 宣言される場合は、全ページロック・テーブル上にユニーク・イン デックスが必須である。ユニーク・インデックスが存在しない場合は エラーが返される。 • for update of リストが指定されてカーソルが更新カーソルとして宣 言される場合は、このリストのカラムが指定されないユニーク・イ ンデックスだけを、全ページロック・テーブル上で必要である。条 件を満たすユニーク・インデックスが存在しない場合は、エラーが 示される。 カーソルを使用する場合、ユニークであると宣言されていないインデック スであっても、IDENTITY カラムを含んでいればユニーク・インデックス とみなされます。場合によっては、IDENTITY カラムをインデックスに追 加してユニーク・インデックスにする必要があったり、カーソル・クエリ に最適状態ではないクエリ・プランをオプティマイザに強制的に選択させ ることがあります。 データオンリーロック・テーブル データオンリーロック・テーブルでは、固定ロー ID を使用してカーソル・ スキャンを配置します。そのため、ユニーク・インデックスは、ダーティ・ リードまたは更新カーソルには必要ありません。更新カーソル内にさまざ まなクエリ・プランがある理由は、有効なインデックスだけに指定された カラムが for update of リストに含まれている場合、テーブル・スキャンが 使用されるからということだけです。 ハロウィーン問題を避けるためのテーブル・スキャン ハロウィーン問題とは、カーソルを使用しているクライアントがそのカー ソル結果セットのローのカラムを更新し、ローがテーブルから返される順 番をそのカラムで定義するときに発生する、更新の異常のことです。たと えば、カーソルがあるインデックスを last_name と first_name 上で使う ことになっていて、これらのうち 1 つのカラムを更新する場合、そのロー が結果セットに 2 番目に現れることがあるというものです。 298 Adaptive Server Enterprise 第 13 章 カーソルとパフォーマンス データオンリーロック・テーブル上でこのハロウィーン問題を避けるた めに、ほかの有効なインデックスで指定したカラムが for update 句のカ ラム・リストに含まれている場合、Adaptive Server はテーブル・スキャン を選択します。 暗黙的に更新可能なカーソルが for update 句を使わないで宣言された場 合や、for update 句のカラム・リストが空のカーソルの場合、そのカーソ ルが使用するインデックス内のカラムを更新するカーソルにハロウィー ン問題が発生する可能性があります。 カーソルがある場合とない場合のパフォーマンスの比較 この項では、次のように異なる 2 つの方法で記述されるストアド・プロ シージャのパフォーマンスについて説明します。 • カーソルがないストアド・プロシージャ - テーブルを 3 回スキャンし、 本一冊ごとに価格を変更する。 • カーソルがあるストアド・プロシージャ - テーブルを 1 回だけス キャンする。 どちらの例でも、titles(title_id) にユニーク・インデックスが設定されてい ます。 カーソルがないストアド・プロシージャの例 次に、カーソルがないストアド・プロシージャの例を示します。 /* ** ** ** ** ** ** ** ** ** */ Increase the prices of books in the titles table as follows: If If it If current price is <= $30, increase it by 20% current price is > $30 and <= $60, increase by 10% current price is > $60, increase it by 5% All price changes must take effect, so this is done in a single transaction. create procedure increase_price as /* start the transaction */ begin transaction /* first update prices > $60 */ update titles パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 299 カーソルがある場合とない場合のパフォーマンスの比較 set price = price * 1.05 where price > $60 /* next, prices between $30 and $60 */ update titles set price = price * 1.10 where price > $30 and price <= $60 /* and finally prices <= $30 */ update titles set price = price * 1.20 where price <= $30 /* commit the transaction */ commit transaction return カーソルがあるストアド・プロシージャの例 次のプロシージャは、基本となるテーブルに対して、前述のカーソルがな いプロシージャの例と同一の変更を実行します。ただし、ここでは集合指 向プログラミングではなくカーソルを使います。各ローがフェッチされ、 調べられ、更新されるたびに、適切なデータ・ページにロックが設定され ます。また、コメントが示すとおり、各更新は作成されたとおりにコミッ トします。これは明示的なトランザクションがないためです。 /* Same as previous example, this time using a ** cursor. Each update commits as it is made. */ create procedure increase_price_cursor as declare @price money /* declare a cursor for the select from titles */ declare curs cursor for select price from titles for update of price /* open the cursor */ open curs /* fetch the first row */ fetch curs into @price /* ** ** ** 300 now loop, processing all the rows @@sqlstatus = 0 means successful fetch @@sqlstatus = 1 means error on previous fetch @@sqlstatus = 2 means end of result set reached Adaptive Server Enterprise 第 13 章 カーソルとパフォーマンス */ while (@@sqlstatus != 2) begin /* check for errors */ if (@@sqlstatus = 1) begin print "Error in increase_price" return end /* next adjust the price according to the ** criteria */ if @price > $60 select @price = @price * 1.05 else if @price > $30 and @price <= $60 select @price = @price * 1.10 else if @price <= $30 select @price = @price * 1.20 /* now, update the row */ update titles set price = @price where current of curs /* fetch the next row */ fetch curs into @price end /* close the cursor and return */ close curs return 以上の例から、カーソルのないストアド・プロシージャ (3 回のテーブル・ スキャンを実行 ) と、カーソルのあるストアド・プロシージャ ( カーソル による 1 回のスキャンを実行 ) とでは、どちらのパフォーマンスが高いか 判断してください。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 301 カーソルがある場合とない場合のパフォーマンスの比較 カーソルがある場合とない場合のパフォーマンスの比較 表 13-2 は、 ロー数 5,000 のテーブルについて収集された統計値を示します。 カーソル・コードはテーブルを 1 回しかスキャンしませんが、カーソルが ない場合の 4 倍以上の時間がかかっています。 表 13-2: ロー数 5,000 のテーブルの実行時間の例 プロシージャ increase_price アクセス・メソッド テーブル・スキャンを 3 回実行 時間 28 秒 increase_price_cursor カーソルを使い、テーブル・スキャン を 1 回実行 125 秒 こうしたテストの結果は、テストごとに大きく変わります。負荷の高い ネットワーク、多数のアクティブなデータベース・ユーザ、同一のテーブ ルにアクセスする複数のユーザのあるシステムでは、特に結果が変わりや すいと言えます。 カーソルを使うと、ロックだけでなく、集合操作の場合よりも多くのネッ トワーク・アクティビティが行われ、命令の処理に伴うオーバヘッドが生 じます。アプリケーション・プログラムは、クエリの結果ローごとに Adaptive Server とやりとりしなければなりません。このため、カーソル・ コードの方が、テーブルを 3 回スキャンするコードよりも完了までに長い 時間がかかります。 カーソルのパフォーマンス問題は次のとおりです。 • ページおよびテーブル・レベルでのロック • ネットワーク・リソース • 命令の処理に伴うオーバヘッド 同等の集合レベルのプログラミングがある場合は、テーブル・スキャンを 複数回実行するプログラミングであっても、そちらを選ぶことをおすすめ します。 302 Adaptive Server Enterprise 第 13 章 カーソルとパフォーマンス 読み込み専用カーソルを使ったロック この項では、カーソルの存在している間の各ポイントに設定されるロック を表示するために使用するカーソル・コードの例を示します。次の例では、 全ページロック・テーブルを使用します。図 13-4 のコードを実行し、矢 印が示す部分で休止して、sp_lock を実行することにより、設定されるロッ クを調べます。 図 13-4: 読み込み専用カーソルとロックを調べるコードの例 declare curs1 cursor for select au_id, au_lname, au_fname from authors where au_id like ’15%’ for read only go open curs1 go fetch curs1 go fetch curs1 go 100 close curs1 go deallocate cursor curs1 go 表 13-3 に調べた結果を示します。 表 13-3: カーソルがデータ・ページとインデックス・ページに対して保持する ロック イベント ロックが設定されているデータ・ページ declare のあと カーソルに関係するロックはない。 open のあと authors に意図的共有ロックがある。 最初の fetch のあと authors に意図的共有ロック、authors テーブル内の あるページに共有ページ・ロックがある。 100 回フェッチしたあと authors に意図的共有ロック、authors テーブル内の 別のページに共有ページ・ロック close のあと カーソルに関係するロックはない。 結果セットの最終ローがフェッチされたあとで、さらに fetch コマンドが 発行されると、最終ページのロックが解放されるため、カーソルに関係す るロックがなくなります。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 303 独立性レベルとカーソル データオンリーロック・テーブルの場合、次のように処理されます。 • カーソルのクエリが独立性レベル 1 で実行されて、read committed with lock が 0 に設定されている場合、ページ・ロックまたはロー・ ロックは発生しない。値はページまたはローからコピーされて、ロッ クは即座に解放される。 • read committed with lock が 1 に設定されているか、クエリが独立性レ ベル 2 または 3 で実行される場合、表 13-3 で示している共有ページ・ ロックのポイントで、共有ページ・ロックか共有ロー・ロックのどち らかが発生する。テーブルがデータロー・ロックを使用する場合、 sp_lock のレポートにはフェッチされたローのロー ID が含まれる。 独立性レベルとカーソル カーソルに対応するクエリ・プランは、カーソルがオープンされた時点で コンパイルされ、最適化されます。カーソルが動作する独立性レベルを変 更する場合、カーソルはオープンできず、set transaction isolation level を 使用します。 独立性レベル 0 を使用するカーソルは、ほかの独立性レベルを使用する カーソルとは異なった形式でコンパイルされるので、独立性レベル 0 で カーソルをオープンすると、そのレベルからレベル 1 または 3 でのオー プンとフェッチを実行することはできません。同様に、独立性レベル 1 ま たは 3 でカーソルをオープンすると、レベル 0 でのフェッチは実行でき ません。互換性のないレベルでカーソルからフェッチを実行しようとす ると、エラー・メッセージが表示されます。 特定の独立性レベルでカーソルを一度オープンしたあとは、カーソルを割 り付け解除してから独立性レベルの変更を行う必要があります。カーソル がオープンしているときに独立性レベルを変更すると、次のような影響が あります。 304 • カーソルを別の独立性レベルでクローズし再オープンしようとする と失敗し、エラー・メッセージが表示される。 • カーソルのクローズや再オープンをせずに独立性レベルを変更しても、 使用している独立性レベルに影響はなく、エラー・メッセージも表示さ れない。 Adaptive Server Enterprise 第 13 章 カーソルとパフォーマンス カーソル内で at isolation 句を使用して、独立性レベルを指定できます。 次の例に示すカーソルは、レベル 1 で宣言され、レベル 0 でフェッチで きます。これは、クエリ・プランが独立性レベルとの互換性を持つため です。 declare cprice cursor for select title_id, price from titles where type = "business" at isolation read uncommitted 分割されたヒープ・テーブルとカーソル 分割されていないヒープ・テーブルに対するカーソル・スキャンは、現在 あるデータをすべて読み込みます。このデータには、そのテーブルに対し て最後に挿入されたデータも含まれます。その挿入が、カーソル・スキャ ンが開始されたあとに始まる場合も同様です。 ヒープ・テーブルが分割されている場合、データが多くのページ・チェー ンのうちの 1 つに挿入される可能性があります。物理挿入ポイントは、現 在カーソル・スキャンを実行している位置の前または後ろに存在している 可能性があります。これは、分割されたテーブルに対するカーソル・ス キャンでは、そのテーブルに最後に挿入されたデータをスキャンできる保 証がないことを示します。 注意 カーソル・オペレーションで、すべての挿入が 1 つのページ・チェー ンの終端にまで実行されている必要がある場合は、カーソル・スキャンに 使用するテーブルを分割しないでください。 カーソルを最適化するために 次に、カーソルを最適化するためのいくつかのヒントを示します。 • 特定のクエリではなく、カーソルを使ってカーソル select 文を最適化 する。 • or 句または in リストの代わりに union か union all を使う。 • カーソルの意図を宣言する。 • for update 句にカラム名を指定する。 • クライアントにローを返す場合は、複数のローをフェッチする。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 305 カーソルを最適化するために • 複数のコミットおよびロールバックにわたってカーソルをオープン のままにする。 • 1 つの接続で複数のカーソルをオープンする。 カーソルを使ったカーソル select 文の最適化 独立した select 文の最適化は、暗黙的または明示的に更新可能なカーソルに 指定された同一の select 文の最適化とまったく異なります。カーソルを使う アプリケーションを開発する場合は、独立した select ではなく、カーソルを 使うときのクエリ・プランと I/O 統計値を常にチェックします。特に、更新 可能カーソルのインデックス制限では、必要となるアクセス・メソッドが まったく異なります。 or 句または in リストの代わりに union を使う カーソルでは、OR 方式が生成するロー ID の動的インデックスを使えま せん。独立した select 文で OR 方式を使うクエリは、通常、読み込み専用 カーソルを使ってテーブル・スキャンを実行します。更新可能カーソルの 場合は、ユニーク・インデックスを使う必要があり、クエリ句を評価する ために各データ・ローに順番にアクセスしなければなりません。 詳細については、このマニュアルの「アクセス・メソッドと or 句および in 句のコスト計算」(84 ページ ) を参照してください。 union を使う読み込み専用カーソルは、カーソルが宣言されるときにワー クテーブルを作成し、ワークテーブルをソートして重複を削除します。こ のワークテーブルに対してフェッチが実行されます。union all を使うカー ソルは重複を返せるため、ワークテーブルを必要としません。 カーソルの意図を宣言する 常にカーソルの意図、つまり読み込み専用か更新可能かを宣言してくだ さい。これによって、同時実行性の影響を十分に制御できます。意図が 指定されないと、Adaptive Server がユーザに代わって判断し、ほとんどの 場合更新可能カーソルを選択します。更新可能カーソルは更新ロックを 使うため、排他ロックおよびほかの更新ロックの設定を妨げます。更新 によってインデックス設定カラムが変更されると、オプティマイザはク エリの実行にテーブル・スキャンを選択しなければならないため、同時 実行性という困難な問題が発生する可能性があります。更新可能カーソ ルを使うクエリのクエリ・プランを慎重に検討して確かめてください。 306 Adaptive Server Enterprise 第 13 章 カーソルとパフォーマンス for update 句にカラム名を指定する Adaptive Server は、カーソル select 文の for update 句にリストされている カラムがあるすべてのテーブルのページまたはローに、更新ロックを設定 します。for update 句がカーソル宣言に含まれない場合は、from 句内で参 照されるすべてのテーブルに更新ロックが設定されます。 次のクエリは、for update 句内にカラム名が含まれていますが、for update 句に price が記述されているため、titles テーブルにのみ更新ロックを要求 します。このテーブルは全ページ・ロックを使用します。authors と titleauthor に対するロックは、共有ページ・ロックです。 declare curs3 cursor for select au_lname, au_fname, price from titles t, authors a, titleauthor ta where advance <= $1000 and t.title_id = ta.title_id and a.au_id = ta.au_id for update of price 表 13-4 は、次の操作の影響を示します。 • for update 句を完全に省略する。shared 句なし。 • for update 句からカラム名を省略する。 • for update 句に更新対象カラム名を指定する。 • for update of price 使用時に、titles テーブルの名前のあとに shared を 追加する。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 307 カーソルを最適化するために この表では、for update 句の 2 つのバージョンに対する追加のロック、つま りより制限的なロックの説明を強調しています。 表 13-4: for update 句と shared がカーソル・ロックに及ぼす影響 titles authors titleauthor 句 なし for update インデックスに sh_page データに sh_page データに sh_page インデックスに updpage インデックスに updpage データに updpage データに updpage for update of price データに updpage インデックスに sh_page データに updpage for update of price + shared データに sh_page データに sh_page データに sh_page インデックスに sh_page データに sh_page データに sh_page データに sh_page set cursor rows を使う SQL 規格では、カーソルに 1 ローずつのフェッチを行うよう規定してい ますが、これはネットワーク帯域幅の浪費につながります。set cursor rows クエリ・オプションと Open Client のフェッチのトランスペアレン ト・バッファ機能を使って次のように指定すると、パフォーマンスが向 上します。 ct_cursor(CT_CURSOR_ROWS) 実行頻度が高く、カーソルを使うアプリケーションで返されるロー数を選 択する場合には慎重に行います。つまり、ロー数をネットワークに合わせ て調整します。 このプロセスの詳細については、 「ネットワーク・パケット・サイズの変 更」(25 ページ ) を参照してください。 308 Adaptive Server Enterprise 第 13 章 カーソルとパフォーマンス 複数のコミットとロールバックにわたってカーソルをオープンに保つ ANSI 標準は、各トランザクションの終了時にカーソルをクローズするよ うに規定しています。Transact-SQL では、ANSI 標準が定める動作を満た さなければならないアプリケーションには、set オプションとして close on endtran を指定できます。ただし、デフォルトではこのオプションはオ フになっています。ANSI 稼働条件を満たさなくてもよい場合は、同時実 行性とスループットを維持するために、このオプションをオフのままにし てください。 ANSI 標準に準拠しなければならない場合は、Adaptive Server に対する影 響の処理方法を決定してください。たとえば、1 つのトランザクションで 多数の更新または削除を実行するかどうか、それともトランザクションを 短くするかどうかなどを決定します。 トランザクションを短くすると決めた場合は、カーソルがオープンされる たびに Adaptive Server が結果セットを実体化し直す必要があるため、カー ソルのクローズとオープンがスループットに影響します。トランザクショ ンごとにより多くの作業を実行することを選択すると、クエリがロックを 保持するために同時実行性の問題が起こる可能性があります。 1 つの接続で複数のカーソルをオープンする 開発の仕方によっては、DB-Library から 2 つ以上の接続を使うことに よって、カーソルをシミュレートすることもできます。1 つの接続は選択 を実行し、別の接続は同一のテーブルに対して更新または削除を実行し ます。このため、アプリケーション・デッドロックが生成される可能性 が非常に高くなります。たとえば、次のようになります。 • 接続 A はページに共有ロックを保持する。Adaptive Server から出さ れた保留中のローがあるかぎり、現在のページに共有ロックが保持 される。 • 接続 B は同一のページに排他ロックを要求し、待機状態に入る。 • アプリケーションは接続 B が成功するのを待ってから、共有ロック を削除するために必要な論理を呼び出す。しかし、実際にはこれが発 生することはない。 接続 A は接続 B が保持するロックを決して要求しないため、この状態は サーバ側のデッドロックではありません。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 309 カーソルを最適化するために 310 Adaptive Server Enterprise 第 1 4 章 抽象プランの概要 この章では、抽象プランの概要について説明します。 トピック名 意味 ページ 311 抽象プランの管理 312 クエリ・テキストとクエリ・プランの関係 313 完全なプランと部分プラン 314 抽象プラン・グループ 315 抽象プランのクエリへの関連付け 316 意味 Adaptive Server はクエリの抽象プランを生成して、テキストとそれに関 連付けられた抽象プランを sysqueryplans システム・テーブルに保存で きます。高速なハッシュ・メソッドを使用すると、受信した SQL クエリ と保存されているクエリ・テキストを比較し、一致するものがあった場 合に、対応する保存された抽象プランを使用してクエリが実行されます。 抽象プランは、専用の言語を使用してクエリの実行プランを記述します。 その言語には、オプティマイザによって生成される選択や動作を指定する 演算子が含まれます。たとえば、インデックス title_id_ix を使って titles テーブルのインデックス・スキャンを指定するには、抽象プランを次のよ うに記述します。 ( i_scan title_id_ix titles) 抽象プランによって、システム管理者とパフォーマンス管理者は、クエ リ・プランの変更がサーバの全体的なパフォーマンスに影響するのを防ぐ ことができます。クエリ・プランに対する変更は、次のような原因で発生 します。 • オプティマイザの選択やクエリ・プランに影響するような Adaptive Server ソフトウェアのアップグレード • クエリ・プランを変更するような新しい Adaptive Server 機能 • 並列度、テーブル分割、またはインデックスなどのチューニング・オ プションを変更する場合 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 311 抽象プランの管理 抽象プランは、主としてシステムの大がかりな変更の前後にクエリ・プラ ンを取得することを目的として作成します。変更前と後のクエリ・プラン のセットを比較することにより、行った変更がクエリにどのような効果を 及ぼすかを知ることができます。次のような機能もあります。 • テーブル・スキャンや再フォーマットなど、特別なタイプのプランを 検索する。 • 特定のインデックスを使用するプランを検索する。 • 効果的ではないクエリの全部または一部のプランを指定する。 • 最適化に時間がかかるクエリのプランを保存する。 抽象プランは、バッチまたはクエリの中でオプティマイザの判断を操作す るためにオプションを指定する代わりに使用します。抽象プランを使用す ると、SQL 文を、構文を変更せずに最適化結果を変更できます。クエリ・ テキストを格納しているテキストと比較して一致を見つける作業には処 理のためのオーバヘッドがかかりますが、保存されているプランを使うこ とによりクエリ最適化のためのオーバヘッドが減ります。 抽象プランの管理 システム管理者とデータベース所有者は、システム・プロシージャの完全 なセットを使用して、プラン、およびプラン・グループを管理できます。 個々のユーザは、実行したクエリのプランを表示、削除、およびコピーで きます。 詳細については、 「第 17 章 システム・プロシージャを使用した抽象プラ ンの管理」を参照してください。 312 Adaptive Server Enterprise 第 14 章 抽象プランの概要 クエリ・テキストとクエリ・プランの関係 多くの SQL クエリには、いくつもの実行プランが可能です。SQL では希 望する結果セットを記述できますが、その結果セットをデータベースから 取得する方法は記述しません。たとえば、次のような 3 つのテーブルを ジョインするクエリを想定してみます。 select t1.c11, t2.c21 from t1, t2, t3 where t1.c11 = t2.c21 and t1.c11 = t3.c31 ジョインはさまざまな順序で実行でき、さらにテーブルにあるインデッ クスにより、テーブル・スキャン、インデックス・スキャン、再フォー マット方式など多くのアクセス・メソッドが考えられます。個々のジョ インで、ネストループ・ジョインかマージ・ジョインが使われる可能性 もあります。このような多くのジョイン方法から、オプティマイザのク エリ・コスト計算アルゴリズムによって選択されますが、どれが選択さ れるかがクエリ自体に記述されているわけではありません。 抽象プランを取得すると、クエリは通常の方法で最適化されますが、オプ ティマイザが抽象プランを生成してクエリ・テキストと抽象プランを sysqueryplans に保存する場合もあります。 クエリ・プランに影響するオプションの制約 Adaptive Server は、オプティマイザによる選択に影響を与える次のような オプションを提供しています。 • 特定のジョイン順序を実行するための set forceplan、またはクエリ に使用するワーカー・プロセスの最大数を指定するための set parallel_degree のようなセッション・レベルのオプション • クエリ・テキストに含まれている、インデックスの選択、キャッシュ 方式、および並列度に影響を及ぼすオプション クエリ・テキストに対する set コマンドの使用やヒントの追加には、次の ような制限があります。 • サブクエリ付加などの一部のクエリ・プランには、効果がない。 • クエリ作成ツールの中には、クエリ内オプションをサポートしていな かったり、どのクエリもベンダに依存しないことを要件としているも のがある。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 313 完全なプランと部分プラン 完全なプランと部分プラン 抽象プランは、クエリ処理ステップとオプションをすべて記述した完全 なプランにも、一部のみを記述した部分プランにもできます。部分プラ ンでは、インデックス名やクエリのジョイン順序は指定せずに、単にイ ンデックスを特定のテーブルのスキャンにのみ使用するように指定でき ます。次に例を示します。 select t1.c11, t2.c21 from t1, t2, t3 where t1.c11 = t2.c21 and t1.c11 = t3.c31 完全な抽象プランには、次のような項目を記述します。 • ジョイン型。ネストループ用の nl_g_join またはマージ・ジョイン用 の m_g_join。このクエリのプランでは、ネストループ・ジョインを 指定する。 • nl_g_join 句に含まれるジョイン順。 • スキャン・タイプ。テーブル・スキャン用の t_scan またはインデッ クス・スキャン用の i_scan。 • そのテーブル用に選択されたインデックス名で、インデックス・ス キャンによりアクセスされるもの。 • スキャン・プロパティで、クエリ内の各テーブルの並列度、I/O サイズ、 およびキャッシュ方式。 上記のクエリ用抽象プランに、ジョイン順、クエリ内の各テーブルへのア クセス・メソッド、各テーブルのスキャン・プロパティを指定します。 ( nl_g_join ( t_scan t2 ) ( i_scan t1_c11_ix t1 ) ( i_scan t3_c31_ix t3 ) ) ( prop t3 ( parallel 1 ) ( prefetch 16 ) ( lru ) ) ( prop t1 ( parallel 1 ) ( prefetch 16 ) ( lru ) ) ( prop t2 ( parallel 1 ) ( prefetch 16 ) ( lru ) ) 314 Adaptive Server Enterprise 第 14 章 抽象プランの概要 抽象プランの言語および構文については、 「第 18 章 抽象プラン言語リファ レンス」を参照してください。 部分プランの作成 抽象プランを取得すると、完全な抽象プランが生成され、格納されます。 オプティマイザによる選択のサブセットのみを対象とする部分プランを 記述することもできます。上記のクエリが、t3 上のインデックスを使用 せず、それ以外のすべてのクエリ・プランが最適化された状態であれば、 create plan コマンドを使ってこのクエリの部分プランを作成してもかま いません。次の部分プランでは、t3 上のインデックスの選択のみを指定 しています。 create plan "select t1.c11, t2.c21 from t1, t2, t3 where t1.c11 = t2.c21 and t1.c11 = t3.c31" "( i_scan t3_c31_ix t3 )" また、select、delete、update、などの最適化可能なコマンドに plan 句を 使っても抽象プランを作成できます。 詳細については、「SQL によるプランの作成」(353 ページ ) を参照してく ださい。 抽象プラン・グループ 初めて Adaptive Server をインストールすると、次の 2 つの抽象プラン・グ ループが準備されます。 • ap_stdout - デフォルトでプランの取得に使用される。 • ap_stdin - デフォルトでプランの関連付けに使用される。 システム管理者は、ap_stdout にサーバワイドなプランの取得を設定でき ます。これにより、各クエリのクエリ・プランをすべて取得できます。 サーバワイドなプランの関連付けには、ap_stdin にあるクエリとプランが 使用されます。一部のクエリが特別にチューニングをしたプランを必要と する場合は、そのプランをサーバ全体で使えるようにできます。 システム管理者またはデータベース所有者は、別のプラン・グループを作 成し、既存のグループのプランをその新しいグループにコピーし、その 2 つのグループのプランを比較できます。 抽象プランの取得と、抽象プランとクエリの関連付けは、現在アクティブ なプラン・グループのコンテキストでのみ発生します。ユーザは、プラン の取得と関連付けをセッション・レベルの set コマンドを使って行います。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 315 抽象プランのクエリへの関連付け 抽象プラン・グループは、次のように使用できます。 • クエリのチューニングを行うときに、テスト用に作成したグループに 抽象プランを作成すると、同じシステム上のほかのユーザに影響を与 えずに済む。 • プラン・セットの「前後」にプラン・グループを使用すると、システ ムの変更または更新による変更のクエリの最適化に対する効果を決 定できる。 プランの取得および関連付けを可能にする方法については、 「第 16 章 抽 象プランの作成と使用」を参照してください。 抽象プランのクエリへの関連付け 抽象プランを保存すると、そのクエリ内の空白部 ( 改行、タブ、および複 数の空白文字 ) は 1 つの空白部にまとめられ、空白部が切りつめられた SQL 文のハッシュ・キー値が計算されます。切りつめられた SQL 文とそ のハッシュ・キーは、抽象プラン、ユニークなプラン ID、ユーザ ID、現 在の抽象プラン・グループの ID とともに sysqueryplans に格納されます。 抽象プランの関連付けを有効にすると、受け取った SQL 文のハッシュ・ キーが計算され、この値と対応するユーザ ID を使って現在の関連グルー プ内でのクエリと抽象プランの一致の検索が行われます。抽象プランの完 全な「関連付けキー」は、次の要素で構成されます。 • 現在のユーザのユーザ ID • 現在の関連付けグループのグループ ID • クエリ・テキスト全体 一致するハッシュ・キーが見つかると、その保存されたクエリのテキスト 全体が実行予定のクエリと比較され、完全に一致すればそのクエリが実行 されます。 関連付けキーがユーザ ID、グループ ID、およびクエリ・テキストの組み 合わせで構成されるということは、指定したユーザについて、1 つの抽象 プラン・グループにクエリ・テキストが同じでクエリ・プランが異なるク エリが 2 つ存在することはあり得ないことを意味します。 316 Adaptive Server Enterprise 第 1 5 章 クエリの抽象プランのユーザーズ・ガイド この章では、抽象プランを記述する場合のガイドラインについて説明し ます。 トピック名 概要 ページ 317 抽象プランを記述するためのヒント 339 「変更前」と「変更後」のプランの比較 340 ストアド・プロシージャの抽象プラン 342 アドホック・クエリと抽象プラン 343 概要 抽象プランでは、希望するクエリ実行プランを指定できます。抽象プラン を使うと、セッションレベルまたはクエリレベルのオプションを使って、 ジョイン順を強制したり、インデックス、I/O サイズ、またはほかのクエ リ実行オプションを指定する必要がありません。セッションレベルとクエ リレベルのオプションについては、 「第 16 章 抽象プランの作成と使用」で 説明しています。 最適化に必要な要素で、set コマンドやクエリ・テキストに含まれる句で 指定できないものがいくつかあります。以下は、その例です。 • サブクエリの付加 • フラット化されたサブクエリのジョイン順 • 再フォーマット方式 多くの場合、set コマンドを含めたり、クエリ・テキストを変更すること が必ずできるとは限らず、また望ましくない場合もあります。抽象プラン を使うことによって、オプティマイザの決定に影響を与える、より優れた 代替手段が提供されます。 抽象プランは、クエリ・テキストに含まれない関係代数式です。これら はシステム・カタログに格納され、受け取ったクエリのテキストに基づ いて、クエリに関連付けられます。 この項で使用するテーブルは、 「第 18 章 抽象プラン言語リファレンス」で 使用しているテーブルと同じものです。create table 文と create index 文 については、「プランの例に使用しているスキーマ」(374 ページ ) を参照 してください。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 317 概要 抽象プラン言語 抽象プラン言語には、以下の演算子を使用する関係代数が使われます。 • g_join - 一般ジョインを表す高レベル論理ジョイン演算子で、ネス トループ・ジョインまたはソートマージ・ジョインのいずれかを使 用して、内部、外部、および存在ジョインを記述する。 • nl_g_join - すべての内部、外部、および存在ジョインなどのネスト ループ・ジョインを表す。 • m_g_join - 内部および外部ジョインなどのマージ・ジョインを表す。 • union - 論理 union 演算子。union および union all SQL 構成体の両方 を記述する。 • scan - 格納されているテーブルをローの流れである抽象プランの抽 出テーブルに変換するための論理演算子。アクセス・メソッドを制限 しない部分プランを許可する。 • i_scan - 物理演算子で、scan を実装する。オプティマイザに、指定 されたテーブルでインデックス・スキャンを行うように指示する。 • t_scan - 物理演算子で、scan を実装する。オプティマイザに、指定さ れたテーブルで完全なテーブル・スキャンを実行するように指示する。 • store - 論理演算子で、抽象プランの抽出テーブルを格納されたワー クテーブルに記述する。 • nested - フィルタで、ネストされたサブクエリの配置と構造を記述 する。 この項で例として使っている create table と create index については、 「プランの例に使用しているスキーマ」(374 ページ ) を参照してください。 抽象プランでは、次のようなキーワードが、グループ化と識別に使用され ます。 318 • plan は、プランが複数のステップを必要とするときにそれらの要素 をグループ化する。 • hints は、部分プランのためのヒントをグループ化する。 • prop は、テーブル用のスキャン・プロパティ prefetch と lru|mru、 parallel を導入する。 • table は、サブクエリやビューの中で、または、相関名が使用される ときに、テーブルを識別する。 • work_t はワークテーブルを識別する。 Adaptive Server Enterprise 第 15 章 クエリの抽象プランのユーザーズ・ガイド • in は table とともに使用して、サブクエリ (subq) またはビュー (view) で指定されたテーブルを識別する。 • subq は、ネストされた演算子とともに使用され、ネストされたサブ クエリに付加ポイントを示し、サブクエリの抽象プランを取り込む。 クエリ、アクセス・メソッド、抽象プラン 個々のテーブルでは、特定のクエリへアクセスするときに、いくつかのイ ンデックスを使用するインデックス・スキャン、テーブル・スキャン、OR 方式、再フォーマットなどいくつかの方法が利用できる場合があります。 次の簡単なクエリでもいくつかのアクセス・メソッドから選ぶことができ ます。 select * from t1 where c11 > 1000 and c12 < 0 以下の抽象プランでは、3 種類のアクセス・メソッドを指定しています。 • インデックス i_c11 を使用する。 (i_scan i_c11 t1) • インデックス i_c12 を使用する。 (i_scan i_c12 t1) • 完全なテーブル・スキャンを実行する。 (t_scan t1) 抽象プランには、クエリにオプティマイザのすべての選択を指定する完全 プランと、クエリで 1 つのテーブルに使用するインデックスなどの選択を 指定するが、テーブルのジョイン順は指定しないような部分プランがあり ます。たとえば、部分プランを使用して、上記のクエリに、あるインデッ クスを使用させ、オプティマイザに i_c11 と i_c12 のいずれかを選択させ るが、完全なテーブル・スキャンは行わないように指定できます。イン デックス名の代わりに、次のように空のカッコを使用します。 (i_scan () t1) さらに、クエリは 2K または 16K のいずれかの I/O を使用でき、逐次また は並列で実行できます。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 319 概要 抽出テーブル 抽出テーブルはクエリ式の評価によって定義されます。これは、システ ム・カタログにも記述されず、ディスクにも格納されないという点で、通 常のテーブルとは異なります。Adaptive Server では、抽出テーブルは、SQL 抽出テーブルの場合と、抽象プランの抽出テーブルの場合があります。 • SQL 抽出テーブルは、クエリ式の評価によって、1 つまたは複数の テーブルにより定義されます。SQL 抽出テーブルはクエリ式の中で 定義され、クエリの実行中のみ存在します。SQL 抽出テーブルの詳 細については、『ASE Transact-SQL ユーザーズ・ガイド』を参照して ください。 • 「抽象プランの抽出テーブル」は、クエリの処理、最適化、実行の過 程で使用されます。抽象プランの抽出テーブルは抽象プランの一部で あり、エンド・ユーザには表示されない点で、SQL 抽出テーブルと 異なります。 テーブルの識別 抽象プランでは、抽象プランの中で名前を付けたテーブルを SQL クエリ 内のテーブルのオカレンスにリンクできるように、クエリのテーブルのす べてに明確に名前を付ける必要があります。ほとんどの場合、必要なのは テーブル名だけですクエリがデータベースと所有者名を使用してテーブ ル名を修飾している場合は、抽象プランでテーブルを完全に識別するため にこの 2 つの要素も必要です。たとえば、次の例では修飾されていない テーブル名が使用されています。 select * from t1 抽象プランでは、修飾されていない名前も使用されます。 ( t_scan t1 ) 次のように、データベース名や所有者名がクエリで指定されている場合は、 select * from pubs2.dbo.t1 次のように、抽象プランでもその修飾を使用する必要があります。 (t_scan pubs2.dbo.t1) しかし、次の例のように、同じテーブルが 1 つのクエリで数回出現する場 合があります。 select * from t1 a, t1 b 上の例で相関名 a と b は、SQL で 2 つのテーブルを識別しています。抽 象プランでは、table 演算子が個々の相関名をテーブルのオカレンスと対 応させます。 320 Adaptive Server Enterprise 第 15 章 クエリの抽象プランのユーザーズ・ガイド ( g_join ( t_scan ( table ( a t1 ) ) ) ( t_scan ( table ( b t1 ) ) ) ) テーブル名がビューとサブクエリであいまいなことがあります。そのよう な場合にも table 演算子をビューとサブクエリでテーブルの識別に使用す ることができます。 サブクエリでは、in と subq 演算子が、サブクエリによる構文的な包含関 係でテーブル名を修飾します。次の例では、同じテーブルが外部クエリと サブクエリに使用されています。 select * from t1 where c11 in (select c12 from t1 where c11 > 100) 抽象プランは、これらを明確に識別します。 ( g_join ( t_scan t1 ) ( i_scan i_c11_c12 ( table t1 ( in ( subq 1 ) ) ) ) ) ビューでは、in と view 演算子が識別を行います。次の例のクエリは、 ビューで使用されるテーブルを参照します。 create view v1 as select * from t1 where c12 > 100 select t1.c11 from t1, v1 where t1.c12 = v1.c11 抽象プランは次のようになります。 ( g_join ( t_scan t1 ) ( i_scan i_c12 ( table t1 ( in ( view v1 ) ) ) ) ) インデックスの識別 i_scan 演算子には、次に示すようにインデックス名とテーブル名の 2 つ のオペランドが必要です。 (i_scan i_c12 t1) インデックスを指定しないで、何かインデックスが必要であることを指定 するには、インデックス名の代わりに空のカッコを使用します。 (i_scan ( ) t1) パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 321 概要 ジョイン順の指定 Adaptive Server は、3 つ以上のテーブルのジョインでは、2 つのテーブル をジョインし、そのジョインから「抽象プランの抽出テーブル」を次の ジョイン順のテーブルにジョインします。この抽象プランの抽出テーブ ルは、クエリの実行で前にあるネストループ・ジョインからのものと同 様に、ローの流れです。 次のクエリは、3 つのテーブルをジョインします。 select * from t1, t2, t3 where c11 = c21 and c12 = c31 and c22 = 0 and c32 = 100 次の例では、g_join 演算子を使用して、ジョイン・アルゴリズムのバイナ リ性を示します。このプランは、t2、t1、t3 のジョイン順を指定します。 (g_join (g_join (scan t2) (scan t1) ) (scan t3) ) t2-t1 のジョインの結果が t3 にジョインされます。 この例の scan 演算子は、 テーブル・スキャンまたはインデックス・スキャンの選択をオプティマイ ザに委ねます。 ジョインの省略形の表記 一般的に、t1、t2、t3...、tN-1、tN というようなジョイン順の N 通りのジョ インは、次のように記述します。 (g_join (g_join ... (g_join (g_join (scan t1) (scan t2) ) (scan t3) ) ... (scan tN-1) ) (scan tN) ) 322 Adaptive Server Enterprise 第 15 章 クエリの抽象プランのユーザーズ・ガイド この表記法は、g_join 演算子の省略形として使用できます。 (g_join (scan (scan (scan ... (scan (scan ) t1) t2) t3) tN-1) tN) この表記は、g_join、nl_g_join、および m_g_join に使用できます。 ジョイン順の例 オプティマイザは、次の 3 通りのジョイン・クエリに対するプランをいく つかのプランから選択できます。 select * from t1, t2, t3 where c11 = c21 and c12 = c31 and c22 = 0 and c32 = 100 例をいくつか示します。 • t2 に対する探索引数として c22 を使用し、c11 で t1 とジョインした後、 c31 で t3 とジョインする。 (g_join (i_scan i_c22 t2) (i_scan i_c11 t1) (i_scan i_c31 t3) ) • t3 に対して探索引数を使用し、ジョイン順の t3、t1、t2 を使用する。 (g_join (i_scan i_c32 t3) (i_scan i_c12 t1) (i_scan i_c21 t2) ) • t2 が小さく、キャッシュに入る場合は、t3、t1、t2 のジョイン順を使 用したまま、t2 の完全テーブル・スキャンを実行する。 (g_join (i_scan i_c32 t3) (i_scan i_c12 t1) (t_scan t2) ) パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 323 概要 • t1 が非常に大きく、t2 と t3 が個別に t1 の大きな部分を修飾するが、 一緒にすると非常に小さな部分に限定できる場合、このプランは STAR ジョインを指定する。 (g_join (i_scan i_c22 t2) (i_scan i_c32 t3) (i_scan i_c11_c12 t1) ) これらのすべてのプランは、ジョイン順の選択を完全に指定し、オプティ マイザにはジョインの種類のみを選択させます。 一般的な g_join 演算子は、外部ジョイン、内部ジョイン、存在ジョイン を実装します。存在ジョインを実行するフラット化されたサブクエリの例 については、 「サブクエリのフラット化」(330 ページ) を参照してください。 実行方法と抽象プランの照合 クエリの種類によって、ジョイン順とジョインの種類にいくつかの制約が あります。例として次のような外部ジョインがあります。 select * from t1, t2 where c11 *= c21 Adaptive Server では、ジョイン処理の間、外部ジョインの外部メンバは外 部テーブルでなければなりません。そのため、次の抽象プランは無効です。 (g_join (scan t2) (scan t1) ) このプランを使おうとすると、エラー・メッセージが表示され、クエリは コンパイルされません。 ビューを使用してクエリにジョイン順を指定する 抽象プランを使用して、結合されるビューのジョイン順を設定できます。 次の例ではビューが作成され、そのビューが t2 と t3 とのジョインを実行 します。 create view v2 as select * from t2, t3 where c22 = c32 次のクエリはビューで t2 とのジョインを実行します。 select * from t1, v2 where c11 = c21 and c22 = 0 324 Adaptive Server Enterprise 第 15 章 クエリの抽象プランのユーザーズ・ガイド 次の抽象プランは、t2、t1、t3 のジョイン順を指定します。 (g_join (scan (table t2 (in (view v2)))) (scan t1) (scan (table t3 (in (view v2)))) ) 次の例は、ビューで t3 とジョインします。 select * from t1, v2 where c11 = c31 and c32 = 100 次のプランは、t3、t1、t2 のジョイン順を使用します。 (g_join (scan (table t3 (in (view v2)))) (scan t1) (scan (table t2 (in (view v2)))) ) これは、set forceplan を使用できないときに、クエリにジョイン順を指定 するために、必要に応じて抽象プランを使用する例です。 ジョイン型の指定 Adaptive Server は、ネストループまたはマージ・ジョインのいずれかを実行 できます。g_join 演算子を使うと、オプティマイザはコスト計算に基づき、 最適なジョイン・アルゴリズムを自由に選択できます。ネストループ・ジョ インを指定するには、nl_g_join 演算子を使用します。ソートマージ・ジョ インには、m_g_join 演算子を使用します。Adaptive Server が取得する抽象プ ランには、常にアルゴリズムを指定する演算子が含まれ、g_join 演算子は 含まれません。 各演算子に表示される “g” は、”generic” ( 一般的 ) を指し、内部ジョイン と外部ジョインに適用されることを意味します。g_join と nl_g_join も存 在ジョインに適用できます。 次のクエリは t1 と t2 のジョインを指定します。 select * from t1, t2 where c12 = c21 and c11 = 0 次の抽象プランは、ネストループ・ジョインを指定します。 (nl_g_join (i_scan i_c11 t1) (i_scan i_c21 t2) ) パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 325 概要 このネストループ・プランは、インデックス i_c11 を使用して、検索句を 使用したスキャンを制限し、次にジョイン・カラムにこのインデックスを 使用して t2 とのジョインを実行します。 次のマージ・ジョイン・プランでは、複数のインデックスが使用されます。 (m_g_join (i_scan i_c12 t1) (i_scan i_c21 t2) ) マージ・ジョインは、i_c12 と i_c21 のジョイン・カラムにマージ・キー としてインデックスを使用します。このクエリは完全なマージ・ジョイン を実行し、ソートは必要ありません。 マージ・ジョインは、i_c11 に対してインデックスを使用し、t1 からロー を選択してワークテーブルへ入れます。このマージでは i_c21 に対してイ ンデックスが使用されます。 (m_g_join (i_scan i11 t1) (i_scan i21 t2) ) ワークテーブルを作成するステップは、このプランで指定されていません。 オプティマイザが、ジョインキーの順序付けにワークテーブルとソートが 必要なときに検出します。 部分プランとヒントの指定 完全なプランを必要としない場合があります。たとえば、クエリ・プラン の問題点として、オプティマイザがノンクラスタード・インデックスを使 用する代わりにテーブル・スキャンを選択のみである場合、抽象プランは インデックスの選択のみを指定し、そのほかの判断はオプティマイザに委 ねることができます。 オプティマイザは、次のクエリに i_c31 を使用する代わりに t3 のテーブ ル・スキャンを選択することもできます。 select * from t1, t2, t3 where c11 = c21 and c12 < c31 and c22 = 0 and c32 = 100 326 Adaptive Server Enterprise 第 15 章 クエリの抽象プランのユーザーズ・ガイド オプティマイザによって生成された次のプランは、t2、t1、t3 のジョイン 順を指定します。しかし、このプランは t3 のテーブル・スキャンを指定 します。 (g_join (i_scan i_c22 t2) (i_scan i_c11 t1) (t_scan t3) ) この完全プランを修正して、代わりに i_c31 を使用するように指定するこ ともできます。 (g_join (i_scan i_c22 t2) (i_scan i_c11 t1) (i_scan i_c31 t3) ) ただし、部分プランのみを指定する方が、解決法として柔軟性があります。 そのクエリのほかのテーブルのデータが変化するのに従って、最適なジョ イン順が変化する可能性があります。部分プランでは、1 つの部分プラン 項目しか指定できません。t3 のインデックス・スキャンを指定する場合、 部分プランを使用すると次のように簡単に記述できます。 (i_scan i_c31 t3) オプティマイザは、t1 と t2 のジョイン順とアクセス・メソッドを選択し ます。 複数のヒントのグループ化 プランのフラグメントが 2 つ以上必要な場合があります。たとえば、ク エリの各テーブルに特定のインデックスを使用するように指定し、ジョ イン順はオプティマイザに委ねる場合などです。複数のヒントが必要な 場合は、hints 演算子を使って次のようにグループ化できます。 (hints (i_scan () t1) (i_scan () t2) (i_scan () t3) ) この場合、hints 演算子は単に構文上必要なだけで、スキャンの順序には 影響を与えません。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 327 概要 何をヒントとして使用できるかについては特に決まりはありません。部 分的なジョイン順は、部分的なアクセス・メソッドと混在してもかまい ません。次のヒントは、t2 がジョイン順で t1 の外側にあり、t3 のスキャ ンにはインデックスを使用する必要があるが、t3 に対するそのインデッ クスの選択、t1 と t2 のアクセス・メソッド、およびジョイン順で t3 をど こに配置するかはオプティマイザが選択できることを指定します。 (hints (g_join (scan t2) (scan t1) ) (i_scan () t3) ) ヒントを使用する整合性のない無効なプラン 次のプランのように、矛盾するジョイン順を指定するヒントを使用した 結果、整合性のないプランとなってしまうこともあります。 (hints (g_join (scan (scan ) (g_join (scan (scan ) ) t2) t1) t1) t2) このプランと関連付けされているクエリを実行すると、クエリのコンパイ ルに失敗し、エラーが発生します。 ほかの整合性のないヒントでは例外が発生しないかもしれませんが、指定 したアクセス・メソッドは、どれも使用される可能性があります。次のプ ランは、同じテーブルにインデックス・スキャンとテーブル・スキャンを 指定します。 (hints (t_scan t3) (i_scan () t3) ) この場合、どちらのアクセス・メソッドも選択される可能性があるため、 動作は不定になります。 328 Adaptive Server Enterprise 第 15 章 クエリの抽象プランのユーザーズ・ガイド サブクエリの抽象プランの作成 サブクエリは Adaptive Server によりいくつかの方法で解析され、抽象プラ ンには次のクエリ実行ステップが反映されます。 • マテリアライゼーション - サブクエリが実行され、結果がワーク テーブルまたは内部変数に格納される。詳細については、 「実体化さ れたサブクエリ」(329 ページ ) を参照してください。 • フラット化 - クエリがフラット化され、メイン・クエリのテーブル とジョインされる。詳細については、 「サブクエリのフラット化」(330 ページ ) を参照してください。 • ネスト - サブクエリが個々の外部クエリ・ローに対して 1 回だけ実行 される。詳細については、 「ネストされたサブクエリ」(332 ページ ) を 参照してください。 抽象プランでは、基本的なサブクエリの解決方法を選択することはできま せん。この選択はルールに基づいて決定され、クエリの最適化中には変更 できません。しかし、抽象プランを外部および内部クエリにあるプランを 変更するために使用できます。ネストされたサブクエリでは、抽象プラン を使用して、そのサブクエリを外部クエリのどこにネストするかも指定で きます。 実体化されたサブクエリ 次のクエリには、相関のないサブクエリが含まれており、これを実体化で きます。 select * from t1 where c11 = (select count(*) from t2) この抽象プランの最初のステップでは、サブクエリでスカラ集合関数を実 体化します。次のステップでは、 その結果を使用して t1 をスキャンします。 ( plan ( i_scan i_c21 ( table t2 ( in (subq 1 ) ) ) ) ( i_scan i_c11 t1 ) ) 次のクエリには、サブクエリのベクトル集合関数が含まれます。 select * from t1 where c11 in (select max(c21) from t2 group by c22) パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 329 概要 この抽象プランは、最初のステップでサブクエリを実体化し、次のステッ プでそれを外部クエリにジョインします。 ( plan ( store Worktab1 ( t_scan ( table t2 ( in (subq 1 ) ) ) ) ) ( nl_g_join ( t_scan t1 ) ( t_scan ( work_t Worktab1 ) ) ) ) サブクエリのフラット化 サブクエリの中にはジョインとしてフラット化できるものがあります。 g_join と nl_g_join 演算子を使うと、存在ジョインが必要なときの検出を オプティマイザが行います。たとえば、次のクエリには存在とともに取得 されたサブクエリが含まれます。 select * from t1 where c12 > 0 and exists (select * from t2 where t1.c11 = c21 and c22 < 100) このクエリのセマンティックは、t1 と t2 の間に存在ジョインを要求して います。t1、t2 のジョイン順は、オプティマイザにより存在ジョインと解 釈され、t2 のスキャンは t1 で条件を満たした各ローに対して、t2 の最初 に一致するローで停止します。 (g_join (scan t1) (scan (table t2 (in (subq 1) ) )) ) t2、t1 のジョイン順は、重複部分を確実に削除するほかの手段を必要とし ます。 (g_join (scan (table t2 (in (subq 1) ) ) ) (scan t1) ) この抽象プランを使用して、オプティマイザは以下の手順を使用する決定 を行えます。 330 • ユニーク・インデックスがある場合、t2.c21 に対してユニーク・イン デックスと通常のジョイン。 • ユニーク・インデックスがない場合、ユニークな再フォーマット方式。 この場合、クエリは c22 のインデックスを使用して、ローを選択して ワークテーブルに入れると思われる。 Adaptive Server Enterprise 第 15 章 • クエリの抽象プランのユーザーズ・ガイド 重複削除ソート最適化方式。通常のジョインを実行し、その結果を選 択してワークテーブルに入れた後、ワークテーブルをソートする。 抽象プランでは、最後の 2 つのオプションに必要なワークテーブルの作成 とスキャンを指定する必要がありません。 サブクエリのフラット化の詳細については、 「サブクエリのフラット化」 (330 ページ ) を参照してください。 例:フラット化されたサブクエリでジョイン順を変更する クエリは、次のように存在ジョインにフラット化できます。 select * from t1, t2 where c11 = c21 and c21 > 100 and exists (select * from t3 where c31 != t1.c11) “!=” の相関により、t3 をスキャンするコストが高くなることがあります。 ジョイン順が t1、t2 の場合、ジョイン順で t3 の最適な配置場所は、t1 と t2 をジョインした結果、ローの数が増加するか、減少するかによって異な るため、コストの高いテーブル・スキャンを実行しなければならない回数 によって決まります。オプティマイザが t3 の正しいジョイン位置を見つ けられない場合は、そのジョインにより t3 をスキャンしなければならな い回数が減少する場合に次の抽象プランを使用できます。 (g_join (scan t1) (scan t2) (scan (table t3 (in (subq 1) ) ) ) ) ジョインにより、t3 をスキャンしなければならない回数が増加すると、こ の抽象プランはジョインの前に t3 のスキャンを実行します。 (g_join (scan t1) (scan (table t3 (in (subq 1) ) ) ) (scan t2) ) パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 331 概要 ネストされたサブクエリ ネストされたサブクエリは、次のように抽象プランで明示的に記述でき ます。 • そのサブクエリの抽象プランを提供する。 • メイン・クエリにそのサブクエリを付加するロケーションを指定する。 抽象プランを使用すると、サブクエリのクエリ・プランに影響を与え、外 部クエリでサブクエリの付加ポイントを変更できます。 nested 演算子は、外部クエリでのサブクエリの位置を指定します。サブク エリは、特定の抽象プランの抽出テーブルに対して「ネスト」されます。オ プティマイザは、その外部クエリのすべての相関カラムを利用できる場所、 およびサブクエリの実行回数が最も少なくて済むと予想される位置を選択 します。 次の SQL 文には、相関式のサブクエリが含まれます。 select * from t1, t2 where c11 = c21 and c21 > 100 and c12 = (select c31 from t3 where c32 = t1.c11) 次の抽象プランは、t1 のスキャンに対してネストされるサブクエリを示し ます。 ( g_join ( nested ( i_scan i_c12 t1 ) ( subq 1 (t_scan ( table t3 ( in ( subq 1 ) ) ) ) ) ) ( i_scan i_c21 t2 ) ) サブクエリの識別と付加 サブクエリは、左からの開きカッコ “(” の順番に従って、番号で識別され ます。 次の例には 2 つのサブクエリがあり、そのうちの 1 つは select リストにあ ります。 select (select c11 from t1 where c12 = t3.c32), c31 from t3 where c32 > (select c22 from t2 where c21 = t3.c31) 332 Adaptive Server Enterprise 第 15 章 クエリの抽象プランのユーザーズ・ガイド 抽象プランでは、t1 を含むサブクエリには “1” という番号が付けられ、t2 を含むサブクエリには “2” という番号が付けられます。サブクエリ 1 と 2 は、t3 のスキャンに対してネストされます。 ( nested ( nested ( t_scan t3 ) ( subq 1 ( i_scan i_c11_c12 ( table t1 (in ( subq 1 ) ) ) ) ) ) ( subq 2 ( i_scan i_c21 ( table t2 ( in ( subq 2 ) ) ) ) ) ) このクエリでは、2 番目のサブクエリは 1 番目のサブクエリにネストされ ます。 select * from t3 where c32 > all (select c11 from t1 where c12 > all (select c22 from t2 where c21 = t3.c31)) このようにネストされている場合でも、t1 を含むサブクエリにも "1" と いう番号が付けられ、t2 を含むサブクエリにも "2" という番号が付けら れます。このプランでは、サブクエリ 2 は、サブクエリ 1 で実行される t1 のスキャンに対してネストされます。サブクエリ 1 は、メイン・クエ リの t3 のスキャンに対してネストされます。 ( nested ( t_scan t3 ) ( subq 1 ( nested ( i_scan i_c11_c12 ( table t1 ( in ( subq 1 ) ) ) ) ( subq 2 ( i_scan i_c21 ( table t2 ( in ( subq 2 ) ) ) ) ) ) ) パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 333 概要 そのほかのサブクエリの例:読み込み順と付加 nested 演算子には、最初のオペランドとして抽象プランの抽出テーブル があり、2 番目のオペランドとしてネストされたサブクエリがあります。 このため、縦に見ていけばジョイン順とサブクエリの配置を容易に理解で きます。 select * from t1, t2, t3 where c12 = 0 and c11 = c21 and c22 = c32 and 0 < (select c21 from t2 where c22 = t1.c11) このプランのジョイン順は t1、t2、t3 で、サブクエリは t1 のスキャンに 対してネストされます。 ( g_join ( nested ( i_scan i_c11 t1 ) ( subq 1 ( t_scan ( table t2 ( in (subq 1 ) ) ) ) ) ( i_scan i_c21 t2 ) ( i_scan i_c32 t3 ) ) サブクエリのネストの修正 サブクエリの付加ポイントを修正する場合は、すべての相関カラムを利用 できるポイントを選択する必要があります。このクエリは、外部クエリの 両方のテーブルと相関関係があります。 select * from t1, t2, t3 where c12 = 0 and c11 = c21 and c22 = c32 and 0 < (select c31 from t3 where c31 = t1.c11 and c32 = t2.c22) このプランでは、t1、t2、t3 のジョイン順を使用し、サブクエリは t1-t2 の ジョインに対してネストされます。 ( g_join ( nested ( g_join ( i_scan i_c11_c12 t1 ) ( i_scan i_c22 t2 ) ) ( subq 1 ( t_scan ( table t3 ( in (subq 1 ) ) ) ) 334 Adaptive Server Enterprise 第 15 章 クエリの抽象プランのユーザーズ・ガイド ) ) ( i_scan i_c32 t3 ) ) このサブクエリは、両方の外部テーブルのカラムを必要とするため、サ ブクエリを t1 のスキャンや t2 のスキャンに対してネストするのは間違い です。このようなエラーは、最適化中にメッセージを表示せずに解決さ れます。 実体化されたビューの抽象プラン 次のビューは、クエリ処理中に実体化されます。 create view v3 as select distinct * from t3 次のクエリは実体化されたビューとのジョインを実行します。 select * from t1, v3 where c11 = c31 最初のステップで、ビュー v3 がワークテーブルに実体化されます。次の ステップで、それがメイン・クエリのテーブル t1 とジョインされます。 ( plan ( store Worktab1 ( t_scan ( table t3 ( in (view v3 ) ) ) ) ) ( g_join ( t_scan t1 ) ( t_scan ( work_t Worktab1 ) ) ) ) パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 335 概要 集合関数を含むクエリの抽象プラン 次のクエリはスカラ集合関数を返します。 select max(c11) from t1 最初のステップで、スカラ集合関数を計算し、内部変数内に格納します。 次のステップは、変数を返すだけであるため、空で、最適化の対象となる ものはありません。 ( plan ( t_scan t1 ) ( ) ) ベクトル集合関数も 2 つのステップからなるクエリです。 select max(c11) from t1 group by c12 最初のステップで集合関数が処理され、ワークテーブルに入ります。次の ステップでワークテーブルのスキャンが行われます。 ( plan ( store Worktab1 ( t_scan t1 ) ) ( t_scan ( work_t Worktab1 ) ) ) ネストされた集合関数は、Transact-SQL の拡張機能です。 select max(count(*)) from t1 group by c11 最初のステップでベクトル集合関数が処理され、ワークテーブルに入り ます。次のステップでそのスキャンが行われ、ネストされたスカラ集合 関数が処理されて内部変数に入ります。3 番目のステップで値が返され ます。 ( plan ( store Worktab1 ( i_scan i_c12 t1 ) ) ( t_scan ( work_t Worktab1 ) ) ( ) ) 集合クエリの拡張カラムは、Transact-SQL の拡張機能です。 select max(c11), c11 from t1 group by c12 336 Adaptive Server Enterprise 第 15 章 クエリの抽象プランのユーザーズ・ガイド 最初のステップでベクトル集合関数が処理され、次のステップでそれが ジョインされてベース・テーブルに返され、拡張カラムが処理されます。 ( plan ( store Worktab1 ( t_scan t1 ) ) ( g_join ( t_scan t1 ) ( i_scan i_c11 ( work_t Worktab1 ) ) ) ) 次の例では、結合されたビューに集合関数が含まれます。 create view v4 as select max(c11) as c41, c12 as c42 from t1 group by c12 select * from t2, v4 where c21 = 0 and c22 > c41 最初のステップでベクトル集合関数の処理が行われ、次のステップでそれ がメイン・クエリのテーブルにジョインされます。 ( plan ( store Worktab1 ( t_scan ( table t1 ( in (view v4 ) ) ) ) ) ( g_join ( i_scan i_c22 t2 ) ( t_scan ( work_t Worktab1 ) ) ) ) 次の例には、実体化されたビューを使用して処理された集合関数が含まれ ます。 create view v5 as select distinct max(c11) as c51, c12 as c52 from t1 group by c12 select * from t2, v5 where c21 = 0 and c22 > c51 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 337 概要 最初のステップで、ベクトル関数が処理され、ワークテーブルに入り ます。2 番目のステップで、それがスキャンされて 2 番目のワークテー ブルに入り、実体化されたビューが処理されます。3 番目のステップで この 2 番目のワークテーブルがメイン・クエリにジョインされます。 ( plan ( store Worktab1 ( t_scan ( table t1 ( in (view v5 ) ) ) ) ) ( store Worktab2 ( t_scan ( work_t Worktab1 ) ) ) ( g_join ( i_scan i_c22 t2 ) ( t_scan ( work_t Worktab2 ) ) ) ) 再フォーマット方式の指定 次のクエリでは、t2 が非常に大きく、インデックスがありません。 select * from t1, t2 where c11 > 0 and c12 = c21 and c22 = 0 再フォーマット方式を t2 に指定する抽象プランは、次のようになります。 ( g_join (t_scan t1 (scan (store Worktab1 (t_scan t2) ) ) ) 再フォーマット方式の場合、store 演算子は scan のオペランドです。store 演算子が plan 演算子のオペランドでないのはこの場合だけです。 OR 方式の制限事項 OR 方式には、 最終ステップを実行するのに必要な RID スキャンを記述する、 一致する抽象プランがありません。Adaptive Server で OR 方式のために生成 されるすべての抽象プランには、scan 演算子のみが指定されます。抽象プ ランを使用して、OR 方式に重複を削除させるクエリ用のインデックスの選 択に影響を与えることはできません。 338 Adaptive Server Enterprise 第 15 章 クエリの抽象プランのユーザーズ・ガイド store 演算子が指定されていない場合 ワークテーブルを必要とする複数のステップからなるクエリの中には、別 のワークテーブル・ステップを使った複数のステップからなるプランを必 要とせず、かつ、ワークテーブルを作成するために store 演算子を使用し ないものがあります。具体的には、次のサブクエリです。 • distinct を使用するクエリのソート・ステップ • マージ・ジョインに必要なワークテーブル • union クエリに必要なワークテーブル • フラット化されたサブクエリが重複の削除にソートを必要とすると きのソート・ステップ 抽象プランを記述するためのヒント 次に、抽象プランの記述と使用のための上記以外の注意点を示します。 • • そのクエリの現在のプランを確認し、さらに記述する必要があるプラ ンと同じクエリ実行ステップを使用しているプランを確認する。新し いプランを最初から記述するよりも、既存のプランを修正する方が簡 単な場合が多い。 • クエリのプランを取得する。 • sp_help_qplan を使用して SQL テキストとプランを表示する。 • この出力を編集して create plan コマンドを生成するか、または plan 句を使用して SQL クエリに編集したプランを付加する。 オプティマイザのほとんどの選択が適切だが、たとえばインデックス の選択のみを改善する必要があるような場合は、クエリのチューニン グに部分プランを指定するのが最善の方法であることが多い。 部分プランを使用すると、オプティマイザは、ほかのテーブルのデー タの変化に合わせて、ほかのテーブルへの別のパスを選択できる。 • 一旦保存された抽象プランは静的である。データ量や分散状態が変化 すると、保存されている抽象プランが最適でなくなる場合がある。 インデックスの付加、テーブルの分割、またはバッファ・プールの追 加によるその後のチューニングの変更により、保存されたプランの中 に現在の条件で十分機能しなくなるプランが出てくる場合がある。多 くの場合、特定の問題を解決する少数の抽象プランを使用することが 望ましい。 定期的にプランを確認して、オプティマイザが選択するプランよりも 保存されているプランの方が優れていることを確認する。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 339 「変更前」と「変更後」のプランの比較 「変更前」と「変更後」のプランの比較 クエリの抽象プランを使用して、Adaptive Server ソフトウェアのアップグ レードまたはシステム・チューニングの変更がクエリ・プランに与える影 響を評価することができます。変更を行う前にプランを保存し、アップグ レードやチューニングの変更を行った後、もう一度プランを保存して、2 つのプランを比較します。基本的な手順は次のとおりです。 1 設定パラメータ abstract plan dump を 1 に設定して、サーバワイドな 取得モードを有効にする。これにより、すべてのプランがデフォル ト・グループの ap_stdout に取得される。 2 取得されたプランが、システムで実行されているほとんどのクエリを 代表するように十分な時間を取る。次のように、sysqueryplans の ap_stdout グループのローの数が変化しているかどうかをチェックす ることにより、ほかのプランが生成されているかどうかをチェックで きる。 select count(*) from sysqueryplans where gid = 2 3 sp_copy_all_qplans を使用して、ap_stdout から ap_stdin まで ( また はサーバワイドなプラン・ロード・モードを使用しないときはほかの グループ ) のすべてのプランをコピーする。 4 sp_drop_all_qplans を使用して、ap_stdout からすべてのクエリ・プ ランを削除する。 5 アップグレードまたはチューニングの変更を行う。 6 プランが ap_stdout に取得されるのに十分な時間を取る。 7 sp_cmp_all_qplans の diff モード・パラメータを使用して、ap_stdout と ap_stdin のプランを比較する。たとえば、次のクエリは ap_stdout と ap_stdin のすべてのプランを比較する。 sp_cmp_all_qplans ap_stdout, ap_stdin, diff 2 つのグループで異なるプランについての情報だけが表示される。 340 Adaptive Server Enterprise 第 15 章 クエリの抽象プランのユーザーズ・ガイド サーバワイドな取得モードの影響 サーバワイドな取得モードを有効にすると、最適化可能なすべてのクエ リのプランが、サーバ上のすべてのデータベースに保存されます。これ により、システム管理上、次のような影響が考えられます。 • プランを取得すると、プランは sysqueryplans に保存され、ログ・レ コードが生成される。プランとログ・レコードに必要なスペースは、 SQL 文とクエリ・プランのサイズと複雑さによって異なる。各デー タベースのユーザが操作するためのスペースをチェックする。 特に、多くの新しいプランが生成されているサーバワイドな取得の初 期段階では、トランザクション・ログを頻繁にダンプしなければなら ない場合がある。 • ユーザが master データベースからシステム・プロシージャを実行し、 サーバワイドなプランの取得を有効にして installmaster をロードし た場合、システム・プロシージャで最適化可能な文のプランは、 master..sysqueryplans に保存される。 これは、プランの取得を有効にしているときに作成されたユーザ定義 のプロシージャの場合も同様である。master のスペースが限られて いる場合は、システム管理者を含むすべてのユーザがログインすると きにデフォルト・データベースを提供できる。 • sysqueryplans テーブルは、データロー・ロックを使用してロックの 競合を減少させる。しかし、特に大量の新しいプランを保存している ときは、パフォーマンスに多少の影響がある場合がある。 • サーバワイドな取得モードが有効になっているときに、bcp を使用す ると、クエリ・プランが master データベースに保存される。大量の テーブルやビューを使用して bcp を実行する場合、sysqueryplans お よび master にあるトランザクション・ログをチェックする。 プランをコピーするための時間と領域 ap_stdout に大量のクエリ・プランがある場合、コピーを開始する前に、 system セグメントにそれらをコピーする十分な領域があることを確認し ます。sp_spaceused を使用して sysqueryplans のサイズをチェックし、 sp_helpsegment を使用してシステム・セグメントのサイズをチェックし ます。 プランをコピーする場合も、トランザクション・ログに領域が必要です。 sp_copy_all_qplans は、グループにあるコピー対象の各プランに sp_copy_qplan を呼び出します。sp_copy_all_qplans が領域の不足やほ かの問題で失敗した場合、正常にコピーされたプランはターゲットのク エリ・プラン・グループに残ります。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 341 ストアド・プロシージャの抽象プラン ストアド・プロシージャの抽象プラン ストアド・プロシージャ内の最適化可能な SQL 文のために取得する抽象 プランについて、次の点に注意します。 • プロシージャは、プラン取得モードまたはプラン結合モードが有効に なっているときに作成する必要がある ( これにより、プロシージャの テキストが sysprocedures に保存される )。 • プロシージャを実行するには、プラン取得モードを有効にし、プロ シージャはプロシージャ・キャッシュからではなくディスクから読み 込む必要がある。 この一連のステップにより、次のプロシージャ内のすべての最適化可能な 文にクエリ・テキストと抽象プランが取得されます。 set plan dump dev_plans on go create procedure myproc as ... go exec myproc go プロシージャがキャッシュにあるためにそのプロシージャのプランが取 得されないときには、with recompile プロシージャを実行する必要があ ります。同様に、クエリの抽象プランを使用して、ストアド・プロシー ジャを実行すると、プロシージャ・キャッシュにあるプランが使用され るため、プロシージャがディスクから読み込まれる場合を除き、クエリ・ プランの関連付けは行われません。 プロシージャとプランの所有者 プラン取得モードが有効になっていると、ストアド・プロシージャ内の最 適化可能な文の抽象プランは、プロシージャの所有者のユーザ ID ととも に保存されます。 プラン関連付けモードの間、ストアド・プロシージャの関連付けは、プロ シージャを実行するユーザではなく、プロシージャの所有者のユーザ ID に基づいて行われます。これは、あるプロシージャのクエリに対する抽象 プランを作成すると、プロシージャを実行する許可を持つすべてのユーザ が同じ抽象プランを使用することを意味します。 342 Adaptive Server Enterprise 第 15 章 クエリの抽象プランのユーザーズ・ガイド 可変実行パスと最適化を使用するプロシージャ ストアド・プロシージャを実行すると、最適化可能な各文について抽象プ ランが保存されます。これは、そのストアド・プロシージャにプロシー ジャやほかの条件のパラメータによって異なる文を実行するフロー制御 文が含まれる場合でも同じです。異なるコード・パスを使用する別のパラ メータを使ってクエリを再実行すると、最適化可能な文があればそのプラ ンは前の実行時に保存され、その文の抽象プランがクエリと関連付けられ ます。 しかし、プロシージャの抽象プランは、条件やパラメータによって異なる 最適化が行われるような文を持つプロシージャについては問題を解決し ません。1 つの例として、次のようなクエリで使用する、ユーザが between 句に低い値と高い値を指定するプロシージャがあります。 select title_id from titles where price between @lo and @hi パラメータによって、最適なプランはインデックス・アクセスの場合、ま たはテーブル・スキャンの場合があります。このようなプロシージャにつ いては、抽象プランが、プロシージャが最初に実行されたときのパラメー タによって、どちらかのアクセス・メソッドを指定することもあります。 プロシージャの最適化の詳細については、このマニュアルの関連する章を 参照してください。 アドホック・クエリと抽象プラン 抽象プランを取得すると、SQL 文の完全なテキストが保存され、SQL ク エリの完全なテキストに基づいて抽象プランの関連付けが行われます。 ユーザがストアド・プロシージャや ESQL を使用する代わりに、特定の SQL 文を送信すると、クエリ句の個々の異なる組み合わせに対して抽象 プランが保存されます。これにより、非常に多くの抽象プランが作成され ます。 ユーザが select 文を使用して、特定の title_id の価格をチェックすると、 各文につき抽象プランが 1 つ保存されます。次の 2 つのクエリのそれぞれ が 1 つの抽象プランを生成します。 select price from titles where title_id = "T19245" select price from titles where title_id = "T40007" さらに、各ユーザにつき 1 つのプランがあります。つまり、何人かのユー ザが title_id “T40007” をチェックすると、各ユーザ ID につきプランが 1 つ 保存されます。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 343 アドホック・クエリと抽象プラン そのようなクエリがストアド・プロシージャに含まれていると、次のよう な 2 つの利点があります。 • たとえば次のようなクエリに、 たった 1 つの抽象プランが保存される。 select price from titles where title_id = @title_id • プランはストアド・プロシージャを所有するユーザのユーザ ID と一 緒に保存され、抽象プランの関連付けはプロシージャの所有者の ID に基づいて行われる。 ESQL を使用すると、たった 1 つの抽象プランがホスト変数とともに保存 されます。 select price from titles where title_id = :host_var_id 344 Adaptive Server Enterprise 第 1 6 章 抽象プランの作成と使用 この章では、抽象プランを取得し、受け取った SQL クエリを保存されてい るプランと関連付けるためのコマンドについて一般的な説明を行います。 すべてのユーザは、セッション・レベルのコマンドを使ってセッション中 にプランを取得し、ロードすることができます。システム管理者はサーバ 全体での抽象プランの取得と関連付けを行えます。この章では、SQL を 使って抽象プランを指定する方法についても説明します。 トピック名 set コマンドを使ってプランの取得と関連付けを行う ページ 345 set plan exists check オプション 350 抽象プランにほかの set オプションを使用する 351 サーバ全体での抽象プランの取得と関連付けモード 352 SQL によるプランの作成 353 set コマンドを使ってプランの取得と関連付けを行う セッション・レベルでは、すべてのユーザは、set plan dump コマンドお よび set plan load コマンドを使って抽象プランを取得、使用する機能を 実行可能にしたり、不可能にしたりできます。set plan replace コマンド を使うと、既存のプランを変更したプランで上書きするかどうかを指定で きます。 抽象プランの各モードの有効/無効の指定は、このコマンドが含まれてい るバッチの最後に有効となります (showplan の場合と同様 )。次のような 独立したバッチでモードを切り換えてから、クエリを実行します。 set plan dump on go /*queries to run*/ go ストアド・プロシージャでどの set plan コマンドを使用しても、そのコマ ンドが含まれているプロシージャには影響しませんが、そのプロシージャ を終了してもその効果は有効です。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 345 set コマンドを使ってプランの取得と関連付けを行う set plan dump を使ってプラン取得モードを有効にする set plan dump コマンドを使うと、抽象プランの取得機能を有効にしたり 無効にしたりできます。set plan dump をグループ名を指定しないで実行 すると、デフォルト・グループの ap_stdout にプランを保存できます。 set plan dump on プランを取得して、特定のプラン・グループに入れるには、グループ名を 指定します。下の例では、グループ dev_plans を取得先グループとして設 定しています。 set plan dump dev_plans on 指定するグループは、set コマンドを実行する前に存在しなければなりま せん。システム・プロシージャ sp_add_qpgroup を使うと、抽象プラン・ グループを作成できますが、このコマンドを実行できるのはシステム管理 者かデータベース所有者だけです。抽象プラン・グループがすでに存在す れば、ユーザはだれでもプランをそのグループにダンプできます。プラ ン・グループの作成の詳細については、 「グループの作成」(358 ページ ) を参照してください。 プランの取得機能を無効にするには、次のコマンドを実行します。 set plan dump off 取得モードを終了するときには、グループ名を指定する必要はありません。 保存または比較するには、一度につき 1 つの抽象プラン・グループしかア クティブにできません。あるグループにプランを保存中の場合は、次に示 すようにプランの plan dump モードをいったん無効にし、新しいグループ のために再度有効にする必要があります。 set plan dump on /*save to the default group*/ go /*some queries to be captured */ go set plan dump off go set plan dump dev_plans on go /*additional queries*/ go set plan dump コマンドが有効な間に use database コマンドを実行すると、 plan dump モードは結果的に無効にされます。 346 Adaptive Server Enterprise 第 16 章 抽象プランの作成と使用 格納されているプランにクエリを関連付ける set plan load コマンドを使うと、クエリと格納されている抽象プランとを 関連付ける機能を有効にしたり無効にしたりできます。 デフォルト・グループの ap_stdin を使用する関連付けモードにするには、 次のコマンドを使用します。 set plan load on 別の抽象プラン・グループを使用する関連付けモードを有効にするには、 次のようにグループ名を指定します。 set plan load test_plans on プランの関連付けを行うには、一度に 1 つの抽象プラン・グループしかア クティブにできません。あるグループに対してプランの関連付け機能をア クティブにしている場合には、次のように現在のグループを非アクティブ にし、新しいグループの関連付け機能を開始する必要があります。 set plan load test_plans on go /*some queries*/ go set plan load off go set plan load dev_plans on go set plan load コマンドが有効な間に use database コマンドを実行すると、 plan load モードは結果的に無効にされます。 プランの取得中に plan replace モードを使用する プラン取得モードがアクティブな間に、set plan replace コマンドを有効 あるいは無効にすることにより、同じクエリに対して既存のプランを別の プランと置き換えるかどうかを指定できます。次のコマンドを使うと、 plan replace モードをアクティブにできます。 set plan replace on set plan replace を実行するときには、グループ名を指定する必要はあり ません。現在アクティブな取得グループに影響します。 プランの置換機能を無効にするには、次のコマンドを実行します。 set plan replace off set plan replace コマンドが有効な間に use database コマンドを実行す ると、plan replace モードは結果的に無効にされます。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 347 set コマンドを使ってプランの取得と関連付けを行う どのような場合に plan replace モードを使用するか プランの取得中に、クエリにすでに保存されているプランと同じクエリ・ テキストがある場合は、plan replace モードが有効でないかぎり既存のプ ランは置換されません。特定のクエリに抽象プランを取得し、かつデータ ベースにオプティマイザによる選択に影響するような物理的な変更を行 う場合は、既存のプランを置換して、変更を保存する必要があります。 プランの置換が必要となるような動作には、次のようなものがあります。 • インデックスの追加または削除、あるいはインデックス内のキーある いはキー順の変更 • テーブル上の分割の変更 • バッファ・プールの追加または削除 • クエリ・プランに影響するような設定パラメータの変更 プランを置換するには、多くの場合 plan load モードを無効にしておく必 要があります。プランの関連付けが有効だと、プランの指定がオプティマ イザに入力されます。たとえば、クエリの完全プランに prefetch プロパ ティと 2K の I/O サイズが含まれていて、ユーザが 16K プールを作成し、 プランにあるプリフェッチの指定を置換しようとする場合は、plan load モードを有効にしないでください。 テーブル内のデータの分布が変更された場合、インデックスの再構築、統 計の更新、あるいはロック・スキームの変更後にクエリ・プランをチェッ クし、一部の抽象プランを置換する必要がある場合があります。 plan dump モード、plan load モード、および plan replace モードを同時に使用する plan dump モードと plan load モードは、同時にアクティブにできます。 このとき plan replace モードはアクティブ、非アクティブのどちらでもか まいません。 同じグループに対して dump と load を使用する 同じグループに対して plan dump と plan load を有効にし、plan replace モードが無効な場合、 348 • そのクエリに対して有効なプランがある場合は、そのプランはロード され、クエリの最適化に使用される。 • 無効なプランがあると ( つまり、インデックスが削除されなかった ため )、新しいプランが生成され、クエリの最適化に使用されるが保 存されない。 • そのプランが部分プランの場合は、完全なプランが生成されるが、既 存の部分プランは置換されない。 Adaptive Server Enterprise 第 16 章 • 抽象プランの作成と使用 そのクエリ用のプランがない場合は、プランが生成され、保存される。 plan replace モードも有効な場合、 • そのクエリに対して有効なプランがある場合は、そのプランはロード され、クエリの最適化に使用される。 • そのプランが有効ではない場合、新しいプランが生成され、クエリの 最適化に使用され、既存のプランは置換される。 • そのプランが部分プランの場合は、完全プランが生成されて使用され、 既存の部分プランは置換される。部分プランの指定内容は、オプティ マイザの入力に使用される。 • そのクエリ用のプランがない場合は、プランが生成され、保存される。 別々のグループに対して dump と load を使用する あるグループに対して dump を有効にしていながら、plan replace モード が無効になっている状態で、別のグループから load を有効にした場合、 次のようになります。 • そのロード・グループ内でクエリに対し既存の有効なプランがある 場合、そのプランがロードされ、使用される。そのダンプ・グルー プに既存のクエリ用のプランがないと、そのプランはそのダンプ・グ ループに保存される。 • ロード・グループにあるプランが無効な場合、新しいプランが生成さ れる。そのダンプ・グループに既存のクエリ用のプランがないと、そ の新しいプランがそのダンプ・グループに保存される。 • ロード・グループにあるプランが部分プランの場合は、既存のプラ ンがないかぎり、完全プランが生成され、そのダンプ・グループに 保存される。部分プランの指定内容は、オプティマイザの入力に使 用される。 • ロード・グループにそのクエリ用のプランがない場合は、そのダン プ・グループにそのクエリ用のプランがないかぎり、そのプランが生 成され、そのダンプ・グループに保存される。 plan replace モードも有効になっている場合、次のようになります。 • そのロード・グループ内でクエリに対し既存の有効なプランがある 場合、そのプランがロードされ、使用される。 • ロード・グループにあるプランが無効な場合、新しいプランが生成 され、クエリの最適化に使用される。新しいプランは、そのダンプ・ グループに保存される。 • ロード・グループにあるプランが部分プランの場合は、完全なプラン が生成され、そのダンプ・グループに保存される。部分プランの指定 内容は、オプティマイザの入力に使用される。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 349 set plan exists check オプション • そのクエリのプランがそのロード・グループにない場合は、新しいプ ランが生成される。新しいプランは、そのダンプ・グループに保存さ れる。 set plan exists check オプション クエリ・プランの関連付けの間に exists check モードを使用すると、ユー ザが抽象プラン・グループから 20 個未満の抽象プランを要求する場合に パフォーマンスのスピードが向上します。少数のクエリに最適化の効率を アップするためのプランが必要な場合は、exists check モードを有効にす ると、抽象プランがないクエリは sysqueryplans でプランをチェックする 必要がないので、その実行速度が向上します。 set plan load と set exists check の 2 つのコマンドを有効にすると、ロー ド・グループ内で最大 20 個までのクエリのハッシュ・キーをキャッシュ に入れて、ユーザが利用できるようになります。そのロード・グループに クエリが 20 以上ある場合は、exists check モードは無効になります。送 られてくるすべてのクエリがハッシュされます。ハッシュ・キーが抽象プ ランのキャッシュに入っていない場合は、そのクエリが使用できるプラン はなく、検索は行われません。これにより、プランが保存されていないク エリ全部をより速くコンパイルできます。 構文は次のとおりです。 set plan exists check { on | off } プランのハッシュ・キーのキャッシュ機能を有効にする前に、ロード・ モードを有効にする必要があります。 システム管理者は、設定パラメータ abstract plan cache を使ってプラン のハッシュ・キーのキャッシングをサーバ全体に設定できます。プラン のキャッシングをサーバ全体で有効にするには、次のコマンドを実行し ます。 sp_configure "abstract plan cache", 1 350 Adaptive Server Enterprise 第 16 章 抽象プランの作成と使用 抽象プランにほかの set オプションを使用する set plan dump および set plan load にほかの set チューニング・オプショ ンを結合できます。 showplan を使用する set plan load を使って抽象プラン関連付けモードを有効にしているとき に showplan を有効にすると、showplan は次の文の showplan 出力の先 頭に、一致する抽象プランのプラン ID を表示します。 QUERY PLAN FOR STATEMENT 1 (at line 1). Optimized using an Abstract Plan (ID : 832005995). plan 句を SQL 文に追加してクエリを実行すると、showplan の出力結果は 次のようになります。 Optimized using the Abstract Plan in the PLAN clause. noexec を使用する noexec モードでは、実際にクエリを実行せずに抽象プランを取得でき ます。noexec モードを有効にすると、クエリの最適化が行われ、抽象 プランが保存されますが、クエリの結果は返されません。 noexec モードを使用して、かつ抽象プランを取得するには、noexec モー ドを有効にする前に必要なプロシージャ (sp_add_qpgroup など ) とほか の set オプション (set plan dump など ) を実行します。このステップの典 型的な例を示します。 sp_add_qpgroup pubs_dev go set plan dump pubs_dev on go set noexec on go select type, sum(price) from titles group by type go パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 351 サーバ全体での抽象プランの取得と関連付けモード forceplan を使用する set forceplan on が有効になっているセッションでクエリの関連付けを有 効にすると、完全な抽象プランを使ってクエリの最適化を行う場合に forceplan は無視されます。部分プランでジョイン順を完全に指定してい ない場合は、次のようになります。 • まず、抽象プラン内のテーブルが指定に従って順序付けられる。 • 次に、残りのテーブルが from 句の指定どおりに順序付けられる。 • 2 つのテーブル・リストが結合される。 サーバ全体での抽象プランの取得と関連付けモード システム管理者は、サーバ全体に対して、以下の設定パラメータを使って プランの取得、関連付け、および置換モードを有効にできます。 • abstract plan dump - デフォルトの抽象プラン取得グループの ap_stdout へのダンプを可能にする。 • abstract plan load - デフォルトの抽象プラン・ロード・グループの ap_stdin からのロードを可能にする。 • abstract plan replace - plan dump モードも有効であれば、プランの 置換を有効にする。 • abstract plan cache - 抽象プラン・ハッシュ ID のキャッシングを有 効にする。同時に abstract plan load も有効にしておく必要がある。 詳細については、 「set plan exists check オプション」(350 ページ ) を参 照してください。 デフォルトで、上の設定パラメータはすべて 0、つまり取得モードと関連 付けモードがオフに設定されています。いずれかのモードを有効にする には、次のようにしてその設定値を 1 に設定します。 sp_configure "abstract plan dump", 1 サーバ全体に対して抽象プランの各モードを有効にした場合、動的に切り 換えが行われるので、サーバをリブートする必要はありません。 サーバ全体に対して抽象プランの取得および関連付けを有効にすると、シ ステム管理者は、そのサーバ上のすべてのユーザのすべてのプランを取得 できます。サーバ全体を対象としたモードをセッション・レベルで上書き することはできません。 352 Adaptive Server Enterprise 第 16 章 抽象プランの作成と使用 SQL によるプランの作成 クエリの抽象プランは、次の方法で直接指定できます。 • create plan コマンドを使用する。 • plan 句を select、insert...select、update、delete、return の各コマンド、 および if 句と while 句に追加する。 プランの記述方法については、 「第 15 章 クエリの抽象プランのユーザー ズ・ガイド」を参照してください。 create plan を使用する create plan コマンドは、クエリのテキストとそのクエリ用に保存する抽 象プランの指定に使用します。 次の例では、抽象プランを作成します。 create plan "select avg(price) from titles" "( plan ( i_scan type_price_ix titles ) ( ) )" このプランは、現在アクティブなプラン・グループに保存されます。次の ように、グループ名を指定することもできます。 create plan "select avg(price) from titles" "( plan ( i_scan type_price_ix titles ) ( ) )" into dev_plans 現在のプラン・グループ、あるいは指定したプラン・グループに、すでに 指定したクエリ用のプランが存在する場合は、あらかじめ replace モード を有効にしておかないと既存のプランを上書きできません。 作成するプランのプラン ID を知りたい場合には、create plan を実行する と ID が変数として返されます。この変数は、最初に宣言しておく必要が あります。次の例では、プラン ID が返されます。 declare @id int create plan "select avg(price) from titles" "( plan ( i_scan type_price_ix titles ) ( ) )" into dev_plans パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 353 SQL によるプランの作成 and set @id select @id create plan を使用すると、そのプランの中のクエリは実行されません。こ れは次のことを意味します。 • クエリのテキストの解析が行われないため、そのクエリが SQL 構文 に準拠しているかのチェックが行われない。 • そのプランが抽象プラン構文に準拠しているかチェックが行われ ない。 • そのプランが、 SQL テキストと互換性があるかチェックが行われない。 エラーやトラブルの発生を避けるためには、showplan を有効にして指定 したクエリをただちに実行する必要があります。 plan 句を使用する plan 句を次の SQL 文で使用すると、次のクエリを実行するために使用す るプランを指定できます。 • select • insert...select • delete • update • if • while • return 次の例は、クエリを実行するために使用するプランを指定しています。 select avg(price) from titles plan "( plan ( i_scan type_price_ix titles ) ( ) )" クエリに抽象プランを指定すると、そのクエリの実行に指定したプランが 使われます。showplan を有効にしておくと、次のメッセージが出力され ます。 Optimized using the Abstract Plan in the PLAN clause. 354 Adaptive Server Enterprise 第 16 章 抽象プランの作成と使用 クエリに plan 句を使用すると、SQL テキストのエラー、プランの構文の エラー、プランと SQL テキストの誤った組み合わせがエラーとしてレ ポートされます。たとえば、次のプランでは、集合を返すステップの範囲 を指定する空のカッコが抜けています。 /* step missing! */ select avg(price) from titles plan " ( plan ( i_scan type_price titles ) )" 次のメッセージが返されます。 Msg 1005, Level 16, State 1: Server ‘smj’, Line 2: Abstract Plan (AP) :The number of operands of the PLAN operator in the AP differs from the number of steps needed to compute the query.The extra items will be ignored.Check the AP syntax and its correspondence to the query. plan 句で指定したプランは、プランの取得機能が有効な場合にのみ sysqueryplans に保存されます。そのクエリのプランがすでに現在の取得 グループにある場合は、plan replace モードを有効にしておかないと既存 のプランは置換されません。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 355 SQL によるプランの作成 356 Adaptive Server Enterprise 第 1 7 章 システム・プロシージャを使用した 抽象プランの管理 この章では、抽象プランを管理するためのシステム・プロシージャの基本 的な機能と使い方について説明します。個々のプロシージャの詳細につい ては、 『ASE リファレンス・マニュアル』を参照してください。 トピック名 抽象プラン管理のためのシステム・プロシージャ ページ 357 抽象プラン・グループの管理 358 抽象プランの検索 362 個々の抽象プランの管理 363 グループにあるすべてのプランの管理 366 プラン・グループのインポートとエクスポート 370 抽象プラン管理のためのシステム・プロシージャ 抽象プランを管理するためのシステム・プロシージャは、個々のプラン、 または抽象プラン・グループを対象とします。 • • 抽象プラン・グループの管理 • sp_add_qpgroup • sp_drop_qpgroup • sp_help_qpgroup • sp_rename_qpgroup 抽象プランの検索 • • sp_find_qplan 個々の抽象プランの管理 • sp_help_qplan • sp_copy_qplan • sp_drop_qplan • sp_cmp_qplans • sp_set_qplan パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 357 抽象プラン・グループの管理 • • グループにあるすべてのプランの管理 • sp_copy_all_qplans • sp_cmp_all_qplans • sp_drop_all_qplans プラン・グループのインポートとエクスポート • sp_export_qpgroup • sp_import_qpgroup 抽象プラン・グループの管理 システム・プロシージャを使うと、抽象プラン・グループの作成、削除、 名前の変更、および抽象プラン・グループに関する情報の表示を行えます。 グループの作成 sp_add_qpgroup は、抽象プラン・グループの作成と命名に使用します。 プランをデフォルトの取得先グループ ap_stdout 以外のグループに取得 する場合は、プランの取得を開始する前にプラン・グループを作成する必 要があります。たとえば、dev_plans というグループにプランの保存を開 始するのであれば、set plan dump コマンドを実行してグループ名を指定 します。 sp_add_qpgroup dev_plans set plan dump dev_plans on /*SQL queries to capture*/ 抽象プラン・グループを追加できるのは、システム管理者とデータベース 所有者だけです。一度グループを作成すると、どのユーザもそのグループ へプランをダンプしたり、そこからロードしたりできます。 358 Adaptive Server Enterprise 第 17 章 システム・プロシージャを使用した抽象プランの管理 グループの削除 sp_drop_qpgroup は、抽象プラン・グループを削除します。 sp_drop_qpgroup には、次の制約があります。 • 抽象プラン・グループを削除できるのは、システム管理者とデータ ベース所有者だけです。 • プランが含まれているグループを削除することはできません。あるグ ループからすべてのプランを削除するには、グループ名を指定して sp_drop_all_qplans を実行します。 • デフォルトの抽象プラン・グループである ap_stdin と ap_stdout は 削除できません。 次のコマンドを実行すると dev_plans プラン・グループを削除できます。 sp_drop_qpgroup dev_plans グループについての情報の取得 sp_help_qpgroup は、1 つの抽象プラン・グループ、または 1 つのデー タベースにあるすべての抽象プラン・グループについての情報を出力し ます。 sp_help_qpgroup にグループ名を指定せずに実行すると、すべての抽象プ ラン・グループの名前、グループ ID、および個々のグループにあるプラ ンの数を出力できます。 sp_help_qpgroup Query plan groups in database ‘pubtune’ Group GID Plans ------------------------------ ----------- ----------ap_stdin 1 0 ap_stdout 2 2 p_prod 4 0 priv_test 8 1 ptest 3 51 ptest2 7 189 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 359 抽象プラン・グループの管理 sp_help_qpgroup にグループ名を指定して実行すると、指定したグルー プにあるプランについての統計を示したレポートが出力されます。次の 例では、グループ ptest2 に関するレポートが出力されます。 sp_help_qpgroup ptest2 Query plans group ’ptest2’, GID 7 Total Rows Total QueryPlans ----------- ---------------452 189 sysqueryplans rows consumption, number of query plans per row count Rows Plans ----------- ----------5 2 3 68 2 119 Query plans that use the most sysqueryplans rows Rows Plan ----------- ----------5 1932533918 5 1964534032 Hashkeys ----------123 There is no hash key collision in this group. sp_help_qpgroup は、個々のグループについて次の事項をレポートします。 • 抽象プランの総数、 および sysqueryplans テーブルにあるローの総数。 • sysqueryplans にある複数のローを持つプランの数。プランは、ロー の数の多い方から降順にリストが作成される。 • ハッシュ・キーの数字およびハッシュ・キーの衝突に関する情報。抽 象プランは、クエリ全体に関するハッシュ・アルゴリズムに基づいて クエリに関連付けされる。 システム管理者またはデータベース所有者がプロシージャ sp_help_qpgroup を実行すると、データベース、あるいは指定したグ ループにあるすべてのプランについてのレポートが作成されます。そ のほかのユーザが sp_help_qpgroup を実行すると、そのユーザが所有 するプランについてのレポートが作成されます。 360 Adaptive Server Enterprise 第 17 章 システム・プロシージャを使用した抽象プランの管理 sp_help_qpgroup には、次の表に示すようなレポート・モードがあります。 モード full 返される情報 stats 完全なレポートからハッシュ・キーに関する情報を除いたすべての 情報。 hash 指定したグループにあるのローの数および抽象プランの数、ハッ シュ・キーの数字、およびハッシュ・キーの衝突に関する情報。 list 指定したグループにあるローの数と抽象プランの数、およびクエリ とプランの個々の組み合わせに関するハッシュ・キー、プラン ID、 クエリの最初の数文字、およびプランの最初の数文字。 queries 指定したグループにあるローの数と抽象プランの数、および個々の クエリに関するハッシュ・キー、プラン ID、クエリの最初の数文字。 plans 指定したグループにあるローの数と抽象プランの数、および個々の プランに関するハッシュ・キー、プラン ID、プランの最初の数文字。 counts 指定したグループにあるローの数と抽象プランの数、および個々の プランに関するローの数、文字数、ハッシュ・キー、プラン ID、ク エリの最初の数文字。 指定したグループにあるローの数およびプランの数、2 つ以上のロー を持つプランの数、最も長いプランのローの数およびプラン ID、ハッ シュ・キーの数およびハッシュ・キーの衝突に関する情報。これは デフォルトのレポート・モードです。 次の例は、counts モードの出力を示します。 sp_help_qpgroup ptest1, counts Query plans group ’ptest1’, GID 3 Total Rows Total QueryPlans ----------- ---------------48 19 Query plans in this group Rows Chars ----- --------3 623 3 576 3 513 3 470 3 430 3 425 3 421 3 382 3 355 3 347 2 379 hashkey id query ----------- ----------- ---------------------------1801454852 876530156 select title from titles ... 476063777 700529529 select au_lname, au_fname... 444226348 652529358 select au1.au_lname, au1.... 792078608 716529586 select au_lname, au_fname... 789259291 684529472 select au1.au_lname, au1.... 1929666826 668529415 select au_lname, au_fname... 169283426 860530099 select title from titles ... 571605257 524528902 select pub_name from publ... 845230887 764529757 delete salesdetail where ... 846937663 796529871 delete salesdetail where ... 1400470361 732529643 update titles set price =... パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 361 抽象プランの検索 グループの名前の変更 システム管理者やデータベース所有者は、sp_rename_qpgroup を使って 抽象プラン・グループの名前を変更できます。次の例では、グループ名を dev_plans から prod_plans に変更します。 sp_rename_qpgroup dev_plans, prod_plans 新しいグループ名には、既存のグループと同じ名前は指定できません。 抽象プランの検索 sp_find_qplan は、クエリ・テキストとプラン・テキストをチェックして、 特定のパターンに一致するプランを検索します。 次の例は、クエリに文字列 “from titles” が含まれているすべてのプランを 検索します。 sp_find_qplan "%from titles%" 次の例では、テーブル・スキャンが実行されるすべての抽象プランを検索 します。 sp_find_qplan "%t_scan%" プロシージャ sp_find_qplan をシステム管理者またはデータベース所有者 が実行すると、すべてのユーザが所有するプランについて検索とレポート が行われます。そのほかのユーザがこのプロシージャを実行すると、その ユーザが所有するプランについて検索とレポートが行われます。 1 つの抽象プラン・グループのみを検索したい場合は、グループ名を指 定して sp_find_qplan を実行します。次の例では、test_plans グループ のみを対象として特定のインデックスを使用するすべてのプランを検索 します。 sp_find_qplan "%i_scan title_id_ix%", test_plans 一致するプランがあると、sp_find_qplan はそのグループ ID、プラン ID、 クエリ・テキスト、および抽象プラン・テキストを出力します。 362 Adaptive Server Enterprise 第 17 章 システム・プロシージャを使用した抽象プランの管理 個々の抽象プランの管理 システム・プロシージャを使うと、クエリの出力、個々のプランのテキス トの出力、個々のプランのコピー、削除、比較、あるいは特定のクエリに 関連付けられているプランの変更を行えます。 プランの表示 sp_help_qplan は、個々の抽象プランのレポートを作成します。作成でき るレポートの種類は brief、full、list の 3 種類です。brief を指定すると、ク エリとプランの最初の 78 文字のレポートが作成されます。full を指定す ると、クエリまたはプランの全体を見られます。list を指定すると、クエ リおよびプランの最初の 20 文字のみを表示できます。 次の例では、デフォルトの簡単なレポートが作成されます。 sp_help_qplan 588529130 gid hashkey id ----------- ----------- ----------8 1460604254 588529130 query --------------------------------------------------------------select min(price) from titles plan --------------------------------------------------------------( plan ( i_scan type_price titles ) ( ) ) ( prop titles ( parallel ... システム管理者またはデータベース所有者は、sp_help_qplan を実行して データベースにあるどのプランについてもレポートを作成できます。ほか のユーザは、自分が所有するプランのみを表示できます。 sp_help_qpgroup を実行すると、1 つのグループ内のすべてのプランのレ ポートを作成できます。詳細については、 「グループについての情報の取 得」(359 ページ ) を参照してください。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 363 個々の抽象プランの管理 別のグループへのプランのコピー sp_copy_qplan を実行すると、あるグループにある抽象プランを既存の別 のグループにコピーできます。次の例では、プラン ID が 316528161 のプ ランを現在のグループから prod_plans グループへコピーします。 sp_copy_qplan 316528161, prod_plans sp_copy_qplan は、コピー先のグループに同じクエリがすでに存在するか どうかをチェックします。重複の可能性があると、sp_cmp_qplans を実 行してコピー先グループにあるプランをチェックします。sp_cmp_qplans によって出力されるメッセージのほかに、以下の場合に sp_copy_qplan に よりメッセージが出力されます。 • コピーしようとしているクエリやプランが、すでにコピー先グループ にある場合 • 同じグループ内の別のプランのユーザ ID とハッシュ・キーが同じ場合 • 同じグループ内の別のプランのハッシュ・キーが同じで、クエリが違 う場合 ハッシュ・キーの競合があっても、プランはコピーされます。コピー先グ ループにすでに同じプランがある場合、あるいはコピーにより関連付け キ ー の 競 合 が 発 生 す る 場 合 は、プ ラ ン の コ ピ ー は 行 わ れ ま せ ん。 sp_copy_qplan によって出力されるメッセージにはコピー先グループに あるプランのプラン ID が含まれているので、sp_help_qplan を使ってそ のクエリとプランをチェックできます。 システム管理者またはデータベース所有者は、どの抽象プランでもコピー できます。そのほかのユーザは、自分が所有するプランのみをコピーでき ます。sp_copy_qplan を実行しても、元のプランおよびグループには何の 影響もありません。コピーされたプランには、新しいプラン ID、コピー 先グループの ID、およびそのプランを作成したクエリを実行したユーザ のユーザ ID が割り当てられます。 個々の抽象プランの削除 sp_drop_qplan は、個々の抽象プランを削除するときに使用します。次の 例では、指定されたプランが削除されます。 sp_drop_qplan 588529130 システム管理者またはデータベース所有者は、データベースにあるどの抽 象プランでも削除できます。そのほかのユーザは、自分が所有するプラン のみを削除できます。 抽象プラン ID を見つけるには、sp_find_qplan を使ってクエリとプランの パターンを利用してプランの検索を行うか、sp_help_qpgroup を使ってグ ループ内のプランのリストを表示します。 364 Adaptive Server Enterprise 第 17 章 システム・プロシージャを使用した抽象プランの管理 2 つの抽象プランの比較 2 つのプラン ID があるときに、sp_cmp_qplans を使うとその抽象プラン と関連付けられているクエリを比較できます。次に例を示します。 sp_cmp_qplans 588529130, 1932533918 sp_cmp_qplans を実行すると、次のようにクエリの比較結果のレポート とそのプランについてのレポートが出力されます。 • 2 つのクエリについては、次のいずれか • • 2 つのクエリが同一である。 • 2 つのクエリが異なる。 • 2 つのクエリは異なるが、同じハッシュ・キーを持つ。 プランについて、 • 2 つのクエリ・プランが同一である。 • 2 つのクエリ・プランが異なる。 次の例では、クエリとプランの両方が一致する 2 つのプランを比較してい ます。 sp_cmp_qplans 411252620, 1383780087 The queries are the same. The query plans are the same. 次の例では、クエリは一致するがプランが異なる 2 つのプランを比較して います。 sp_cmp_qplans 2091258605, 647777465 The queries are the same. The query plans are different. sp_cmp_qplans は、比較結果を示すステータス値を返します。ステータ ス値を表 17-1 に示します。 表 17-1: sp_cmp_qplans が返すステータス値 戻り値 0 意味 +1 2 つのクエリおよびハッシュ・キーが異なる。 +2 2 つのクエリは異なるが、ハッシュ・キーは同じ。 +10 2 つの抽象プランが異なる。 100 片方または両方のプラン ID がない。 2 つのクエリ・テキストおよび抽象プランが同一である。 システム管理者またはデータベース所有者は、データベースにあるどの 2 つの抽象プランでも比較できます。そのほかのユーザは、自分が所有す るプランのみを比較できます。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 365 グループにあるすべてのプランの管理 既存のプランの変更 sp_set_qplan を使うと、既存のプランの ID の抽象プランを、その ID ま たはクエリ・テキストを変更せずに変更できます。このプロシージャは、 プランのテキストが 255 文字以下の場合にだけ使用できます。 sp_set_qplan 588529130, "( i_scan title_ix titles)" システム管理者またはデータベース所有者は、保存されているどのクエリ の抽象プランでも変更できます。そのほかのユーザは、自分が所有するプ ランのみを変更できます。 sp_set_qplan を実行すると、新しい抽象プランがクエリに有効かどうか、 あるいはテーブルとインデックスがすでにあるかどうかをチェックする ためのクエリ・テキストとの比較は行われません。そのプランの有効性を チェックするには、そのプランに関連付けられているクエリを実行する必 要があります。 その抽象プランをクエリに指定するには、create plan と plan 句を使用し ます。詳細については、 「SQL によるプランの作成」(353 ページ ) を参照 してください。 グループにあるすべてのプランの管理 次のシステム・プロシージャがプランのグループの管理に使われます。 • sp_copy_all_qplans • sp_cmp_all_qplans • sp_drop_all_qplans グループにあるすべてのプランのコピー sp_copy_all_qplans を使うと、ある抽象プラン・グループにあるすべて の プ ラ ン を 別 の グ ル ー プ に コ ピ ー で き ま す。次 の 例 を 実 行 す る と、 test_plans グループにあるすべてのプランが helpful_plans グループにコ ピーされます。 sp_copy_all_qplans test_plans, helpful_plans helpful_plans グループは、sp_copy_all_qplans を実行する前に存在して いる必要があります。このプロシージャには、別のプランを追加できます。 sp_copy_all_qplans は、sp_copy_qplan を実行してそのグループの個々 のプランをコピーするので、sp_copy_qplan が失敗するような要因があ れば、このプロシージャも失敗します。 「2 つの抽象プランの比較」(365 ページ ) を参照してください。 366 Adaptive Server Enterprise 第 17 章 システム・プロシージャを使用した抽象プランの管理 各プランのコピーはそれぞれ独立したトランザクションで行われるので、 1 つのプランのコピーに失敗しても sp_copy_all_qplans は失敗しません。 しかし、何らかの理由で失敗し、再実行する必要があるときには、すでに 正常にコピーされたプランについてのメッセージ・セットが表示され、ど のプランがすでにコピー先グループにあるかがわかります。 コピーされた各プランには、新しいプラン ID が割り当てられます。コピー されたプランには元のユーザ ID が割り当てられます。抽象プランをコ ピーしてそれに新しいユーザ ID を割り当てるには、sp_export_qpgroup と sp_import_qpgroup を使う必要があります。詳細については、 「プラン・ グループのインポートとエクスポート」(370 ページ) を参照してください。 システム管理者またはデータベース所有者は、データベースにあるどのプ ランでもコピーできます。そのほかのユーザは、自分が所有するプランの みをコピーできます。 グループにあるすべてのプランの比較 sp_cmp_all_qplans は、2 つのグループにあるすべての抽象プランを比 較し、次の事項をレポートします。 • 2 つのグループで共通のプランの数 • 同じ関連付けキーを持つが、抽象プランが異なるプランの数 • 片方のグループにあって、もう 1 つのグループにないプランの数 次の例では ap_stdout と ap_stdin のプランを比較します。 sp_cmp_all_qplans ap_stdout, ap_stdin If the two query plans groups are large, this might take some time. Query plans that are the same count ----------338 Different query plans that have the same association key count ----------25 Query plans present only in group ’ap_stdout’ : count ----------0 Query plans present only in group ’ap_stdin’ : count ----------1 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 367 グループにあるすべてのプランの管理 さらにレポート・モード・パラメータを 1 つ追加すると、 sp_cmp_all_qplans は ID、クエリ、およびグループにあるクエリの抽象 プランを含む詳細な情報を出力します。このモード・パラメータを使用 すると、すべてのプラン、または特定の違いがあるプランについての詳 細情報を取得できます。表 17-2 に、レポート・モードと各モードでレ ポートされる情報の種類を示します。 表 17-2: sp_cmp_all_qplans のレポート・モード 368 モード counts レポート内容 brief counts で取得される情報のほかに、プラン自体は異なるが関連付 けキーが同じであるような各グループにある抽象プランの ID、お よび片方のグループにあって別のグループにはないプランの ID。 same クエリとプランが一致するすべての抽象プランの総数、ID、クエリ、 およびプラン。 diff クエリとプランが異なるすべての抽象プランの総数、ID、クエリ、 およびプラン。 first 1 番目のプラン・グループにあるが 2 番目のプラン・グループに はないすべての抽象プランの総数、ID、クエリ、およびプラン。 second 2 番目のプラン・グループにあるが 1 番目のプラン・グループに はないすべての抽象プランの総数、ID、クエリ、およびプラン。 offending 関連付けキーが異なり、かつ両方のグループには存在しないすべ ての抽象プランの総数、ID、クエリ、およびプラン。これは、diff、 first、second の 3 つのモードのレポート結果を合わせたものと同 じである。 full すべての抽象プランの総数 ID、クエリ、およびプラン。これは、 same と offending の 2 つのモードのレポート内容を合わせたもの と同じである。 同一のプラン、同じ関連付けキーを持つプラン、同一あるいは同 じ関連付けキーを持つが別のグループに属するプラン、同じグ ループにあるプラン、同じグループにあるが別のグループにはな いプランの数。これはデフォルトのレポート・モードです。 Adaptive Server Enterprise 第 17 章 システム・プロシージャを使用した抽象プランの管理 次の例は、brief レポート・モードを示しています。 sp_cmp_all_qplans ptest1, ptest2, brief If the two query plans groups are large, this might take some time. Query plans that are the same count ----------39 Different query plans that have the same association key count ----------4 ptest1 ptest2 id1 id2 ----------- ----------764529757 1580532664 780529814 1596532721 796529871 1612532778 908530270 1724533177 Query plans present only in group ’ptest1’ : count ----------3 id ----------524528902 1292531638 1308531695 Query plans present only in group ’ptest2’ : count ----------1 id ----------2108534545 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 369 プラン・グループのインポートとエクスポート 1 つのグループのすべての抽象プランの削除 sp_drop_all_qplans は、1 つのグループにあるすべての抽象プランを削除 します。次の例では、dev_plans グループにあるすべての抽象プランを削 除します。 sp_drop_all_qplans dev_plans システム管理者あるいはデータベース所有者が sp_drop_all_qplans を実 行すると、指定したグループからすべてのユーザに属するすべてのプラン が削除されます。それ以外のユーザがこのプロシージャを実行すると、そ のユーザが所有するプランのみが対象となります。 プラン・グループのインポートとエクスポート sp_export_qpgroup および sp_import_qpgroup を実行すると、 sysqueryplans とユーザ・テーブルの間で相互にプラン・グループをコピーできます。シ ステム管理者あるいはデータベース所有者がこのプロシージャを実行する と、次の操作が可能です。 • 抽象プランを 1 つのデータベースから同じサーバ上にある別のデー タベースにコピーする • bcp を使って現在のサーバから外部へコピーできるテーブルを作成し、 それを別のサーバにコピーする • 同じデータベースにある既存のプランに別のユーザ ID を割り当てる プランのユーザ・テーブルへのエクスポート sp_export_qpgroup は、抽象プラン・グループにある特定のユーザのすべ てのプランをユーザ・テーブルにコピーします。次の例では、fast_plans グループからデータベース所有者 (dbo) が所有するプランをコピーし、 transfer というテーブルを作成します。 sp_export_qpgroup dbo, fast_plans, transfer sp_export_qpgroup は、select...into を使って sysqueryplans と同じカラム と デ ー タ 型 を 持 つ テ ー ブ ル を 作 成 し ま す。そ の デ ー タ ベ ー ス で select into/bulkcopy/pllsort オプションを有効に設定していないときには、 別のデータベース名を指定できます。このコマンドを実行すると、tempdb にエクスポート・テーブルが作成されます。 sp_export_qpgroup mary, ap_stdout, "tempdb..mplans" 370 Adaptive Server Enterprise 第 17 章 システム・プロシージャを使用した抽象プランの管理 テーブルは、bcp を使って外部にコピーすることも、別のサーバにある テーブルにコピーすることも可能です。プランは、同じサーバ上の別の データベースにある sysqueryplans にインポートすることも、同じデータ ベースにある sysqueryplans に別のグループ名またはユーザ ID を使って インポートすることもできます。 ユーザ・テーブルからのプランのインポート sp_import_qpgroup は、プランを sp_export_qpgroup を使って作成され たテーブルから sysqueryplans にあるグループにコピーします。次の例 では、プランがテーブル tempdb..mplans から ap_stdin にコピーされ、そ のデータベース所有者のユーザ ID が割り当てられます。 sp_import_qpgroup "tempdb..mplans", dbo, ap_stdin 指定したユーザのプランにすでに含まれているグループへは、プランをコ ピーできません。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 371 プラン・グループのインポートとエクスポート 372 Adaptive Server Enterprise 第 1 8 章 抽象プラン言語リファレンス この章では、抽象プラン言語の演算子とそのほかの言語要素について説明 します。 トピック名 キーワード ページ 373 オペランド 373 プランの例に使用しているスキーマ 374 キーワード 次の語は、クエリの抽象プラン言語のキーワードです。これらは予約語で ないため、抽象プランで使用するテーブルやインデックスに同じ名前を 使っても競合しません。たとえば、テーブルやインデックスに hints とい う名前を付けてもかまいません。 オペランド 抽象プランの構文では、次のオペランドが使用されます。 表 18-1: 使用される識別子 識別子 table_name 説明 correlation_name クエリの中で、テーブルに対して指定される相関名 derived_table 保管されているテーブルのスキャンの結果、作成される テーブル stored_table ベース・テーブルまたはワーク・テーブル worktable_name ワーク・テーブルの名前 view_name ビューの名前 index_name インデックスの名前 subquery_id クエリ内のサブクエリの順序を示す整数 ベース・テーブル ( ユーザ・テーブルまたはシステム・ テーブル ) の名前 table_name と view_name は、database.owner.object_name の表記を使用して 指定できます。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 373 プランの例に使用しているスキーマ 抽象プランの抽出テーブル クエリ実行時に保管されたテーブルにアクセスした結果、抽象プランの抽 出テーブルが生成されます。抽象プランの抽出テーブルには、次の種類が あります。 • クエリによって生成された結果セット。 • クエリ実行中の中間結果。つまりジョイン順で最初の 2 つのテーブル のジョインの結果で、次に 3 番めのテーブルとジョインされる。 抽象プランの抽出テーブルは、アクセス・メソッドを指定する scan 演算 子の 1 つから作成されます。たとえば、scan、i_scan、または t_scan (i_scan title_id_ix titles) などです。 注意 抽象プランの抽出テーブルを SQL 抽出テーブルと混同しないでくだ さい。SQL 抽出テーブルの詳細については、 『Transact-SQL ユーザーズ・ ガイド』を参照してください。 プランの例に使用しているスキーマ 以下の抽象プランのサンプル例を単純にするために、この項では次のテー ブルを使用します。 create table t1 (c11 int, c12 int) create table t2 (c21 int, c22 int) create table t3 (c31 int, c32 int) 使用するインデックスは次のとおりです。 create create create create create create create 374 index index index index index index index i_c11 on t1(c11) i_c12 on t1(c12) i_c11_c12 on t1(c11, c12) i_c21 on t2(c21) i_c22 on t2(c22) i_c31 on t3(c31) i_c32 on t3(c32) Adaptive Server Enterprise 第 18 章 抽象プラン言語リファレンス g_join 説明 ジョイン型 ( ネストループまたはソート・マージ ) を指定せずに複数の抽 象プランの抽出テーブルのジョインを指定する。 構文 ( g_join derived_table1 derived_table2 ) ( g_join ) ( derived_table1 ) ( derived_table2 ) ... ( derived_tableN ) パラメータ derived_table1...derived_tableN 結合される抽象プランの抽出テーブル。 戻り値 指定した抽象プランの抽出テーブルのジョインである抽象プランの抽出 テーブル。 例 例1 select * from t1, t2 where c21 = 0 and c22 = c12 (g_join ( i_scan i_c21 t2 ) ( i_scan i_c12 t1 ) ) テーブル t2 はジョイン順の外部テーブルで、t1 は内部テーブルである。 例2 select * from t1, t2, t3 where c21 = 0 and c22 = c12 and c11 = c31 (g_join ( i_scan i_c21 t2 ) ( i_scan i_c12 t1 ) ( i_scan i_c31 t3 ) ) テーブル t2 は t1 とジョインされ、その抽象プランの抽出テーブルは t3 と ジョインされる。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 375 g_join 使用法 • g_join 演算子は、すべてのバイナリ・ジョイン ( 内部ジョイン、外部 ジョイン、 または存在ジョイン) を記述する一般的な論理演算子である。 • g_join 演算子は、生成されたプランでは使用しない。nl_g_join およ び m_g_join は使用されるジョイン型を示す。 • g_join 演算子を使用すると、オプティマイザはネストループ・ジョイ ンとソートマージ・ジョインのいずれかを選択する。ソートマージ・ ジョインを指定するには、m_g_join を使用する。ネストループ・ジョ インを指定するには、nl_g_join を使用する。 • この構文は、複数のテーブルに関するジョインを記述する省略形を使 用している。次に構文を示す。 ( g_join ( scan ( scan ( scan ... ( scan ( scan t1) t2) t3) tN-1) tN) ) 上記は、次の構文の省略形である。 ( g_join ( g_join ... ( g_join (g_join ( scan t1) ( scan t2) ) ( scan t3) ) ... ( scan tN-1) ) ( scan tN) ) 376 Adaptive Server Enterprise 第 18 章 • 抽象プラン言語リファレンス g_join を使用して、クエリのすべてのテーブルではなく、いくつかの テーブルのジョイン順を指定すると、オプティマイザは指定された ジョイン順を使用するが、g_join オペランドの間にほかのテーブルを 挿入する場合がある。たとえば、次のクエリがあるとする。 select * from t1, t2, t3 where ... 上記に対して、次の部分抽象プランは、t1 と t2 のジョイン順のみを 記述する。 ( g_join ( scan t2) ( scan t1) ) オプティマイザは、t3-t2-t1、t2-t3-t1、または t2-t1-t3 の 3 つのジョイ ン順のどれでも選択できる。 参照 • テーブルは、g_join 句で指定した順序でジョインされる。 • set forceplan on が有効になっているセッションでクエリの関連付け を有効にすると、完全な抽象プランを使ってクエリの最適化を行う場 合に forceplan は無視される。部分プランでジョイン順を完全に指定 していない場合は、 • まず、抽象プラン内のテーブルが指定どおりに順序付けられる。 • 次に、残りのテーブルが from 句の指定どおりに順序付けられる。 • 2 つのテーブル・リストが結合される。 m_g_join, nl_g_join パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 377 hints hints 説明 部分プランに各項目を導入し、グループ化する。 構文 ( hints ( derived_table ) ... ) パラメータ derived_table 抽象プランの抽出テーブルを生成する 1 つまたは複数の式。 戻り値 抽象プランの抽出テーブル 例 select * from t1, t2 where c12 = c21 and c11 > 0 and c22 < 1000 ( hints ( g_join ( t_scan t2 ) ( i_scan () t1 ) ) ) t2 のテーブル・スキャン、t1 でのインデックスの使用、t1-t2 のジョイン 順などの部分プランを指定する。t1 のインデックスとジョイン型 ( ネスト ループまたはソートマージ ) の選択は、オプティマイザに委ねられる。 使用法 • クエリの最適化の間、指定した hints が使用される。 • hints 演算子は、複数のステップを含む部分プランのルートとして表 示される。部分プランに式が 1 つしか含まれていない場合、hints は 省略可能。 • hints 演算子は、オプティマイザが生成するプランには使用されない。 なぜならば、オプティマイザが生成するプランは常に完全プランだか らである。 • hints は、以下を実行してクエリと関連付けることができる。 • 378 • sp_set_qplan を使用して、既存クエリのプランを変更する。 • plan 句を使用して、クエリにプランを指定する。クエリと hints を保存するには、set plan dump を有効にする必要がある。 • create plan コマンドを使用する。 SQL 文の plan 句で hints を指定すると、プランが有効であることを確 認するためのチェックが行われる。sp_set_qplan を使用して hints を 指定すると、プランを保存する前にチェックは行われない。 Adaptive Server Enterprise 第 18 章 抽象プラン言語リファレンス i_scan 説明 ベース・テーブルのインデックス・スキャンを指定する。 構文 ( i_scan index_name base_table ) ( i_scan () base_table ) パラメータ index_name 指定した保管されているテーブルのインデックス・スキャンに使用す るインデックスの名前またはインデックス ID。空のカッコを使用する と、テーブル・スキャンではなくインデックス・スキャンを実行する ことを指定するが、インデックスの選択はオプティマイザに委ねる。 base_table スキャンするベース・テーブルの名前。 戻り値 ベース・テーブルのスキャンによって生成される抽象プランの抽出テー ブル。 例 例1 select * from t1 where c11 = 0 ( i_scan i_c11 t1 ) インデックス i_c11 を使用して t1 をスキャンするように指定する。 例2 select * from t1, t2 where c11 = 0 and c22 = 1000 and c12 = c21 ( g_join ( scan t2 ) ( i_scan () t1 ) ) ジョイン順を示して部分プランを指定するが、t2 へのアクセス・メソッド と t1 のインデックスの選択はオプティマイザに委ねる。 select * from t1 where c12 = 0 ( i_scan 2 t1 ) t1 のインデックスを名前ではなく、インデックス ID で識別する。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 379 in 使用法 参照 • 指定したインデックスを使用してテーブルのスキャンが行われる。イ ンデックスを指定しなくても、テーブル・スキャンではなく任意のイ ンデックスを使ってスキャンが行われる。 • i_scan 演算子の後に空のカッコを使用すると、オプティマイザにイン デックスの選択をまかせ、テーブルにインデックスが存在しない場合 は、テーブル・スキャンの実行を許可する。 • i_scan 演算子が指定されているときに、必要なカラムがすべてインデッ クスに含まれていれば、必ずカバード・インデックス・スキャンが実行 される。カバード・インデックス・スキャンを記述するために、抽象プ ランを指定する必要はない。 • i_scan 演算子を使用すると、指定したインデックスが存在しない場合 でも、再フォーマット方式と OR 方式の選択はされない。オプティマ イザは別の利用できるインデックスを選択し、アドバイス・メッセー ジが出力される。i_scan にインデックスを指定しない場合やインデッ クスが存在しない場合は、テーブル・スキャンが実行され、アドバイ ス・メッセージが出力される。 • インデックス ID を使用してインデックスを指定することは抽象クエ リ・プランで有効であるが、インデックス ID の使用はすすめられな い。これは、インデックスが削除され、異なる順序で再作成された場 合に、プランが無効になるか、または最適状態でない状態で実行され るからである。 scan, t_scan in 説明 サブクエリやビューで指定されるテーブルのロケーションを示す。 構文 ( in ( [ subq subquery_id | view view_name ] ) ) パラメータ subq subquery_id サブクエリを識別する整数。抽象プランでは、サブクエリの番号は、ク エリ内にあるサブクエリの左からの開きカッコの順番に従って付けら れる。 view view_name ビューの名前。プランの関連付けを行うために、抽象プランで指定す るデータベースと所有者名は、クエリで使用するデータベースと所有 者名と同じでなければならない。 380 Adaptive Server Enterprise 第 18 章 例 抽象プラン言語リファレンス 例1 create view v1 as select * from t1 select * from v1 ( t_scan ( table t1 ( in ( view v1 ) ) ) ) テーブル t1 が使用されているビューを識別する。 例2 select * from t2 where c21 in (select c12 from t1) ( g_join ( t_scan t2 ) ( t_scan ( table t1 ( in ( subq 1 ) ) ) ) ) サブクエリ 1 のテーブル t1 のスキャンを識別する。 例3 create view v9 as select * from t1 where c11 in (select c21 from t2) create view v10 as select * from v9 where c11 in (select c11 from v9) select * from v10, t3 where c11 in (select c11 from v10 where c12 = t3.c31) パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 381 lru ( ( ( ( ( ( ( ( ( ( ) g_join t_scan i_scan i_scan i_scan i_scan i_scan i_scan i_scan i_scan t3 ) i_c21 i_c11 i_c11 i_c11 i_c21 i_c11 i_c21 i_c21 ( ( ( ( ( ( ( ( table table table table table table table table t2 ( in ( subq 1 ) ( view v9 ) ( view v10 t1 ( in ( view v9 ) ( view v10 )))) t1 ( in ( view v9 ) ( view v10 ) ( subq 1 t1 ( in ( view v9 ) ( subq 1 ) ( view v10 t2 ( in ( subq 1 ) ( view v9 ) ( subq 1 ) t1 ( in ( view v9 ) ( subq 1 ) ( view v10 t2 ( in ( subq 1 ) ( view v9 ) ( view v10 t2(in( subq 1 )( view v9 )( subq 1 )( view )))) )))) )))) ( view v10 )))) ) ( subq 1 )))) ) ( subq 1 )))) v10 ) ( subq 1)))) ビューとサブクエリの複数のネストの例。 使用法 • SQL クエリのビューやサブクエリのテーブルのオカレンスを識別する。 • in リストでは、最も内側の項目 ( それ自身が深くネストされている項 目 ) が左、テーブル名の近くにあり、最も外側の項目 ( 最上位のクエ リで発生する項目 ) が右にある。たとえば、次の条件があるとする。 (table t2 (in (subq 1) (view v9) (subq 1) (view v10) (subq 1) ) ) 上記は、どちらの方向にも読める。 参照 • table から始め、左から右へ読む場合:ベース・テーブル t2 は、 ビュー v9 の最初のサブクエリでスキャンされ、ビュー v9 は ビュー v10 の最初のサブクエリで出現し、ビュー v10 はメイン・ クエリの最初のサブクエリで出現する。 • メイン・クエリから始め、右から左へ読む場合:メイン・クエリ には最初のサブクエリがあり、これはビュー v10 をスキャンし、 ビュー v10 にはビュー v9 をスキャンする最初のサブクエリが含 まれ、ビュー v9 にはベース・テーブル t2 をスキャンする最初の サブクエリが含まれる。 nested, subq, table, view lru 説明 保管されているテーブルのスキャンに LRU キャッシュ方式を指定する。 構文 ( prop table_name ( lru ) ) パラメータ table_name プロパティを適用するテーブル。 382 Adaptive Server Enterprise 第 18 章 例 抽象プラン言語リファレンス select * from t1 ( prop t1 ( lru) ) t1 のスキャンに LRU キャッシュ方式を使用するように指定する。 使用法 参照 • LRU 方式が、結果として作成されるクエリ・プランで使用される。 • 部分プランは、クエリ・プランのほかの部分を指定せずにスキャン・ プロパティを指定できる。 • 完全なクエリ・プランには、常にすべてのスキャン・プロパティが含 まれる。 mru, prop m_g_join 説明 2 つの抽象プランの抽出テーブルのマージ・ジョインを指定する。 構文 ( m_g_join ( ( derived_table1 ) ( derived_table2 ) ) パラメータ derived_table1...derived_tableN 結合される抽象プランの抽出テーブル。derived_table1 は常に外部テー ブルで、derived_table2 は内部テーブルである。 戻り値 指定した抽象プランの抽出テーブルのジョインである抽象プランの抽出 テーブル。 例 例1 select t1.c11, t2.c21 from t1, t2, t3 where t1.c11 = t2.c21 and t1.c11 = t3.c31 ( nl_g_join ( m_g_join ( i_scan i_c31 t3 ) ( i_scan i_c11 t1 ) ) ( t_scan t2 ) ) パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 383 m_g_join テーブル t1 と t3 の右マージ・ジョインを指定し、次にテーブル t2 とのネ ストループ・ジョインを指定する。 例2 select * from t1, t2, t3 where t1.c11 = t2.c21 and t1.c11 = t3.c31 and t2.c22 =7 ( nl_g_join ( m_g_join ( i_scan i_c21 t2 ) ( i_scan i_c11 t1 ) ) ( i_scan i_c31 t3 ) ) テーブル t2 ( 外部 ) と t1 ( 内部 ) の完全なマージ・ジョインを指定し、次に ジョイン順で、t3 とのネストループ・ジョインが行われるように指定する。 例3 select c11, c22, c32 from t1, t2, t3 where t1.c11 = t2.c21 and t2.c22 = t3.c32 ( m_g_join (nl_g_join (i_scan i_c11 t1) (i_scan i_c12 t2) ) (i_scan i_c32_ix t3) ) t1 と t2 のネストループ・ジョインを指定し、次に t3 とのマージ・ジョイ ンを指定する。 使用法 参照 384 • テーブルは、m_g_join 句で指定した順序でジョインされる。 • ソートマージ・ジョインのクエリ処理に必要なソート・ステップと ワーク・テーブルは、抽象プランに示されていない。 • m_g_join 演算子がマージ・ジョインとして実行できないジョインを 指定するのに使用された場合、その指定は特にメッセージを表示しな いで無視される。 g_join, nl_g_join Adaptive Server Enterprise 第 18 章 抽象プラン言語リファレンス mru 説明 保管されているテーブルのスキャンに MRU キャッシュ方式を指定する。 構文 ( prop table_name ( mru) ) パラメータ table_name プロパティを適用するテーブル。 例 select * from t1 ( prop t1 ( mru ) ) テーブルに MRU キャッシュ方式を使用するように指定する。 使用法 参照 • MRU 方式は、結果として作成されるクエリ・プランで指定される。 • 部分プランは、クエリ・プランのほかの部分を指定せずにスキャン・ プロパティを指定できる。 • 生成されたクエリ・プランには、常にすべてのスキャン・プロパティ が含まれる。 • sp_cachestrategy がテーブルやインデックスの MRU 置換を無効に するために使用され、クエリ・プランが MRU を指定する場合、抽象 プランの指定は、特にメッセージを表示しないで無視される。 lru, prop nested 説明 抽象プランの抽出テーブルのサブクエリのネストを記述する。 構文 ( nested ( derived_table ) ( subquery_specification ) ) パラメータ derived_table 指定したサブクエリをネストする抽象プランの抽出テーブル。 subquery_specification derived_table に対してネストするサブクエリ。 戻り値 抽象プランの抽出テーブル パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 385 nested 例1 例 select c11 from t1 where c12 = (select c21 from t2 where c22 = t1.c11) ( nested ( t_scan t1 ) ( subq 1 ( t_scan ( table t2 ( in ( subq 1 ) ) ) ) ) ) ネストされた 1 つのサブクエリ。 例2 select c11 from t1 where c12 = (select c21 from t2 where c22 = t1.c11) and c12 = (select c31 from t3 where c32 = t1.c11) ( nested ( nested ( t_scan t1 ) ( subq 1 ( t_scan ( table t2 ( in ( subq 1 ) ) ) ) ) ) ( subq 2 ( t_scan ( table t3 ( in ( subq 2 ) ) ) ) ) ) 2 つのサブクエリが両方ともメイン・クエリにネストされている。 例3 select c11 from t1 where c12 = (select c21 from t2 where c22 = (select c31 from t3 where c32 = t1.c11)) 386 Adaptive Server Enterprise 第 18 章 抽象プラン言語リファレンス ( nested ( t_scan t1 ) ( subq 1 ( nested ( t_scan ( table t2 ( in ( subq 1 ) ) ) ) ( subq 2 ( t_scan ( table t3 ( in ( subq 2 ) ) ) ) ) ) ) ) レベル 2 のサブクエリは、メイン・クエリにネストされているレベル 1 の サブクエリにネストされている。 使用法 参照 • サブクエリは、クエリ・プランの指定した付加ポイントで実行される。 • 実体化され、フラット化されたサブクエリは、nested 演算子のブロッ クには表示されない。例については、「subq」(395 ページ ) を参照。 in, subq nl_g_join 説明 複数の抽象プランの抽出テーブルのネストループ・ジョインを指定する。 構文 ( nl_g_join ... ) ( derived_table1 ) ( derived_table2 ) ( derived_tableN ) パラメータ derived_table1...derived_tableN 結合される抽象プランの抽出テーブル。 戻り値 指定した抽象プランの抽出テーブルのジョインである抽象プランの抽出 テーブル。 例 例1 select * from t1, t2 where c21 = 0 and c22 = c12 ( nl_g_join ( i_scan i_c21 t2 ) ( i_scan i_c12 t1 ) ) テーブル t2 はジョイン順の外部テーブルで、t1 は内部テーブルである。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 387 parallel 例2 select * from t1, t2, t3 where c21 = 0 and c22 = c12 and c11 = c31 ( nl_g_join ( i_scan i_c21 t2 ) ( i_scan i_c12 t1 ) ( i_scan i_c31 t3 ) ) テーブル t2 は t1 とジョインされ、その抽象プランの抽出テーブルは t3 と ジョインされる。 使用法 参照 • テーブルは、nl_g_join 句で指定された順序でジョインされる。 • nl_g_join 演算子は、すべてのバイナリ・ジョイン ( 内部ジョイン、外部 ジョイン、 またはセミジョイン) を記述する一般的な論理演算子である。 ジョインは、ネストループ・クエリの実行方法を使用して実行される。 g_join, m_g_join parallel 説明 保管されているテーブルのスキャンに並列度を指定する。 構文 ( prop table_name ( parallel degree ) ) パラメータ table_name プロパティを適用するテーブル。 degree スキャンに使用する並列度。 例 select * from t1 (prop t1 ( parallel 5 ) ) t1 テーブルのスキャンに 5 つのワーカー・プロセスを使用するように指定 する。 388 Adaptive Server Enterprise 第 18 章 使用法 抽象プラン言語リファレンス • スキャンは、指定した数のワーカー・プロセスを使用して実行される ( 指定した数だけある場合 )。 • 部分プランは、クエリ・プランのほかの部分を指定せずにスキャン・ プロパティを指定できる。 • 保存されたプランでいくつかのワーカー・プロセスの使用が指定され ているが、クエリを実行するときにセッション・レベルまたはサー バ・レベルの値が異なる場合、 • 現在の設定で許可されているよりも多いワーカー・プロセスがプ ランで指定されている場合、現在の設定が使用されるか、または 逐次プランを使用してクエリが実行される。 • 現在の設定で許可されているよりも少ないワーカー・プロセスが プランで指定されている場合、プランの値が使用される。 クエリ・プランへのこれらの変更はユーザに透過的に実行されるた め、警告メッセージは発行されない。 参照 prop plan 説明 ワーク・テーブルが必要なクエリや、集約値を計算するクエリなど、複数 のステップから成るクエリのクエリ・プラン・ステップをグループ化する メカニズムを提供する。 構文 (plan ) query_step1 ... query_stepN パラメータ query_step1...query_stepN - クエリの各ステップを実行するために抽象プランのステップを指定 する。 戻り値 抽象プランの抽出テーブル 例 例1 select max(c11) from t1 group by c12 ( plan ( store Worktab1 ( t_scan t1 ) ) ( t_scan ( work_t Worktab1 ) ) ) パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 389 plan ベクトル集合関数を返す。プラン演算子の最初のオペランドは、Worktab1 を作成し、ベース・テーブルのテーブル・スキャンを指定する。2 番めの オペランドは、ワーク・テーブルをスキャンし、その結果を返す。 例2 select max(c11) from t1 ( plan ( t_scan t1 ) ( ) ) スカラ集合関数を返す。スカラ集合関数は結果の値をワーク・テーブルで はなく内部変数に蓄積するため、最後の抽象プランの抽出テーブルは空で ある。 例3 select * from t1 where c11 = (select count(*) from t2) ( plan ( i_scan i_c21 (table t2 ( in_subq 1) ) ) ( i_scan i_c11 t1 ) ) 実体化されたサブクエリの実行を指定する。 例4 create view v3 as select distinct * from t3 select * from t1, v3 where c11 = c31 ( plan ( store Worktab1 ( t_scan (table t3 (in_view v3 ) ) ) ) ( nl_g_join ( t_scan t1 ) ( t_scan ( work_t Worktab1 ) ) ) ) 実体化されたビューの実行を指定する。 390 Adaptive Server Enterprise 第 18 章 使用法 • テーブルは、指定したアクセス・メソッドで、指定した順序でアクセ スされる。 • plan 演算子は、以下のような複数のステップから成るクエリに必要 である。 • 参照 抽象プラン言語リファレンス • ソートを実行するクエリやベクトル集合関数を計算するクエリ など、ワーク・テーブルを生成するクエリ • スカラ集合関数を計算するクエリ • 実体化されたサブクエリを含むクエリ クエリ実行の各ステップが plan キーワードで始まる場合は、複数の 実行ステップが必要なクエリの抽象プランに、各ステップのオペラン ドを含める必要がある。部分プランを導入するために、hints 演算子 を使用する。 hints prefetch 説明 保管されているテーブルのスキャンに使用する I/O サイズを指定する。 構文 ( prop table_name ( prefetch size ) ) パラメータ table_name プロパティを適用するテーブル。 size 有効な I/O サイズ:2、4、8、または 16。 例 select * from t1 ( prop t1 (prefetch 16 ) ) t1 のスキャンに 16K の I/O サイズが使用される。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 391 prop 使用法 • テーブルが使用するキャッシュに指定したサイズのプールが存在す る場合、結果として作成されるクエリ・プランに、指定した I/O サイ ズが使用される。 • 部分プランは、クエリ・プランのほかの部分を指定せずにスキャン・ プロパティを指定できる。 • 保存されたプランに大容量 I/O を指定すると、現在のプール設定やほ かのオプションに合わない場合は、以下を実行する。 • 参照 • プランは 16K の I/O を指定するが 16K のプールが存在しない場 合は、使用できる I/O サイズで次に大きなものを使用する。 • セッションやサーバ・レベル・オプションにより、大容量 I/O が クエリに使用できない場合 ( セッションに対する set prefetch や テーブルに対する sp_cachestrategy) は、2K の I/O を使用する。 スキャン・プロパティに 2K の I/O のみを指定するプランを保存し、 後で大容量 I/O プールを作成する場合で、これらのプランでより大き な I/O サイズを使用するときは、replace モードを有効にし、新しい プランを保存する。 prop prop 説明 保管されているテーブルのスキャンに使用するプロパティを指定する。 構文 ( prop table_name ( property_specification ) ... ) property_specification: ( prefetch size ) ( lru | mru ) ( parallel degree ) パラメータ 例 table_name プロパティを適用するテーブル。 select * from t1 ( t_scan t1 ) ( prop t1 ( parallel 1 ) ( prefetch 16 ) ( lru ) ) t1 のスキャンで使用されたプロパティ値を表示する。 392 Adaptive Server Enterprise 第 18 章 使用法 参照 抽象プラン言語リファレンス • 指定したプロパティをテーブルのスキャンに使用する。 • 部分プランは、クエリ・プランのほかの部分を指定せずにスキャン・ プロパティを指定できる。 • 生成されたプランには、クエリの各テーブルに使用された並列、プリ フェッチ、キャッシュ方式のプロパティが含まれる。 lru, mru, parallel, prefetch scan 説明 スキャンのタイプを指定せずに、保管されているテーブルのスキャンを指 定する。 構文 ( scan stored_table ) パラメータ stored_table スキャンするベース・テーブルの名前。これはベース・テーブルでも ワーク・テーブルでもよい。 戻り値 保管されているテーブルのスキャンによって生成される抽象プランの抽 出テーブル。 例 例1 select * from t1 where c11 > 10 ( scan t1 ) t1 のスキャンを指定し、テーブル・スキャンやインデックス・スキャンを 実行するかどうかの選択は、オプティマイザに委ねる。 例2 select * from t1, t2 where c11 = 0 and c22 = 1000 and c12 = c21 ( nl_g_join ( scan t2) ( i_scan i_c22 t1 ) ) ジョイン順を示して部分プランを指定するが、t2 へのアクセス・メソッド はオプティマイザに委ねる。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 393 store 使用法 • 保管されているテーブルへのアクセス・メソッドは、オプティマイザ が選択する。 • スキャンのタイプの選択をオプティマイザにまかせるときは、scan 演算子を使用する。使用されるアクセス・メソッドは次のいずれかで ある。 • 参照 • 完全なテーブル・スキャン • データ・ページへアクセスするインデックス・スキャン • データ・ページへアクセスしないカバード・インデックス・ス キャン • OR 方式に使用する RID スキャン 再フォーマット方式を指定する抽象プランの例については、store を 参照。 i_scan, store, t_scan store 説明 スキャンの結果をワーク・テーブルに格納する。 構文 ( store worktable_name ( [scan | i_scan | t_scan ] table_name ) ) パラメータ worktable_name 作成するワーク・テーブルの名前。 table_name スキャンするベース・テーブルの名前。 戻り値 例 スキャンの結果のワーク・テーブル。 select c12, max(c11) from t1 group by c12 ( plan ( store Worktab1 ( t_scan t1 ) ) ( t_scan ( work_t Worktab1 ) ) ) ベクトル集合関数を選択してワーク・テーブルに入れる 2 つのステップか ら成るプロセスを指定し、次に、ワーク・テーブルの結果を選択する。 394 Adaptive Server Enterprise 第 18 章 使用法 抽象プラン言語リファレンス • 指定したテーブルをスキャンし、その結果をワーク・テーブルに格納 する。 • 抽象プランでの store 演算子の有効な場所は次のとおりである。 • plan または union 演算子の下。ここで store 演算子がワーク・ テーブル生成のための前処理を示す。 • scan 演算子の下 (ただし、i_scan や t_scan 演算子の下ではない)。 • プラン取得モードの間、ワーク・テーブルは Worktab1、Worktab2 な どと識別される。手動で入力したプランには、どのような命名規則も 使用できる。 • 再フォーマット方式の使用は、scan (store ( )) 演算子の組み合わせを使 用して抽象プランで記述できる。たとえば、t2 にインデックスがなく、 非常に大きい場合、次の抽象プランは、t2 をテーブル・スキャンで 1 回スキャンし、その結果をワーク・テーブルに格納するように示す。 select * from t1, t2 where c11 > 0 and c12 = c21 and c22 between 0 and 10000 ( nl_g_join (i_scan i_c11 t1) ( scan (store (t_scan t2 ))) ) 参照 scan subq 説明 サブクエリを識別する。 構文 ( subq subquery_id ) パラメータ subquery_id サブクエリを識別する整数。抽象プランでは、サブクエリの番号は、ク エリ内のサブクエリの左からのカッコの順番に従って付けられる。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 395 subq 例 例1 select c11 from t1 where c12 = (select c21 from t2 where c22 = t1.c11) ( nested ( t_scan t1 ) ( subq 1 ( t_scan ( table t2 ( in ( subq 1 ) ) ) ) ) ) ネストを含んだ単一のサブクエリ。 例2 select c11 from t1 where c12 = (select c21 from t2 where c22 = t1.c11) and c12 = (select c31 from t3 where c32 = t1.c11) ( nested ( nested ( t_scan t1 ) ( subq 1 ( t_scan ( table t2 ( in ( subq 1 ) ) ) ) ) ) ( subq 2 ( t_scan ( table t3 ( in ( subq 2 ) ) ) ) ) ) 2 つのサブクエリが両方ともメイン・クエリにネストされている。 396 Adaptive Server Enterprise 第 18 章 抽象プラン言語リファレンス 例3 select c11 from t1 where c12 = (select c21 from t2 where c22 = (select c31 from t3 where c32 = t1.c11)) ( nested ( t_scan t1 ) ( subq 1 ( nested ( t_scan ( table t2 ( in ( subq 1 ) ) ) ) ( subq 2 ( t_scan ( table t3 ( in ( subq 2 ) ) ) ) ) ) ) ) レベル 2 のサブクエリは、メイン・クエリにネストされているレベル 1 の サブクエリにネストされている。 使用法 • • subq 演算子は、抽象プランの式で次の 2 つの意味を持つ。 • nested 演算子の下では、ネストされたサブクエリのテーブルへの 付加を記述する。 • in 演算子の下では、サブクエリに含まれるベース・テーブルと ビューのネストを記述する。 プランを指定せずに、サブクエリの付加を指定するには、空のヒント を使用する。 ( nested ( t_scan t1) ( subq 1 () ) ) • サブクエリの抽象プランを記述し、付加を指定しない場合は、nested 演算子で空のヒントを抽象プランの抽出テーブルとして指定する。 ( nested () ( subq 1 (t_scan ( table t1 ( in ( subq 1 ) ) ) ) ) ) パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 397 t_scan • サブクエリがジョインにフラット化されているときには、その抽象プ ランのサブクエリへの唯一の参照は、そのサブクエリで指定されてい るテーブルである。 select * from t2 where c21 in (select c12 from t1) ( nl_g_join ( t_scan t1 ) ( t_scan ( table t2 ( in ( subq 1 ) ) ) ) • サブクエリが実体化されるとき、実体化ステップで、スキャンされる テーブルを識別して、そのサブクエリは store オペレーションに入る。 select * from t1 where c11 in (select max(c22) from t2 group by c21) ( plan ( store Worktab1 ( t_scan ( table t2 ( in ( subq 1 ) ) ) ) ) ( nl_g_join ( t_scan t1 ) ( t_scan ( work_t Worktab1 ) ) ) ) 参照 in, nested, table t_scan 説明 保管されているテーブルのテーブル・スキャンを指定する。 構文 ( t_scan stored_table ) パラメータ stored_table スキャンするベース・テーブルの名前。 戻り値 保管されているテーブルのスキャンによって生成される抽象プランの抽 出テーブル。 例 select * from t1 ( t_scan t1 ) t1 のテーブル・スキャンを実行する。 398 Adaptive Server Enterprise 第 18 章 使用法 参照 抽象プラン言語リファレンス • オプティマイザに、保管されているテーブルでテーブル・スキャンを 実行するように指示する。 • t_scan を指定すると、再フォーマット方式と OR 方式の使用が禁止さ れる。 i_scan, scan, store table 説明 サブクエリまたはビューで発生するベース・テーブル、またはクエリの from 句で相関名が割り当てられるベース・テーブルを識別する。 構文 ( table table_name [ qualification ] ) パラメータ table_name ベース・テーブル。クエリでデータベース名や所有者名を使用する場 合は、抽象プランでもそれらを指定する必要がある。 ( table ( correlation_name table_name) ) correlation_name 相関名がクエリで使用されている場合は、その相関名。 qualification in (subq subquery_id) または in (view view_name) のいずれか。 例 例1 select * from t1 table1, t2 table2 where table1.c11 = table2.c21 ( nl_g_join ( t_scan ( table ( table1 t1 ) ) ) ( t_scan ( table ( table2 t2 ) ) ) ) テーブル t1 と t2 は、 クエリで使用されている相関名への参照で識別される。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 399 table 例2 select c11 from t1 where c12 = (select c21 from t2 where c22 = t1.c11) ( nested ( t_scan t1 ) ( subq 1 ( t_scan ( table t2 ( in ( subq 1 ) ) ) ) ) ) サブクエリのテーブル t2 は、サブクエリへの参照で識別される。 例3 create view v1 as select * from t1 where c12 > 100 select t1.c11 from t1, v1 where t1.c12 = v1.c11 ( nl_g_join ( t_scan t1 ) ( i_scan 2 ( table t1 ( in ( view v1 ) ) ) ) ビューのテーブル t1 は、ビューへの参照で識別される。 使用法 • 抽象プランで指定された抽象プランの抽出テーブルは、クエリで指定 された位置的に対応するテーブルと照合される。 • table 演算子は、抽象プランにあるテーブル名を、テーブルのビュー、 サブクエリ、相関名を含むクエリの SQL 中で対応するテーブルにリ ンクするために使用される。 • 相関名を使用するときは、スキャン・プロパティ・セクションの参照 など、テーブルへのすべての参照が次のフォームで記述される。 ( table ( correlation_name table_name) ) table 演算子は、props 演算子の下にあるテーブルへのスキャン・プ ロパティを含めてテーブルへのすべての参照に使用される。 参照 400 in, subq, view Adaptive Server Enterprise 第 18 章 抽象プラン言語リファレンス union 説明 複数の抽象プランの抽出テーブルの union を記述する。 構文 (union derived_table1 ... derived_tableN ) パラメータ derived_table1...derived_tableN 結合される抽象プランの抽出テーブル。 戻り値 指定したオペランドの union である抽象プランの抽出テーブル。 例 例1 select * from t1 union select * from t2 union select * from t3 (union (t_scan t1) (t_scan t2) (t_scan t3) ) 3 つの完全なテーブル・スキャンの union を返す。 例2 select 1,2 union select * from t2 (union ( ) (tscan t2) ) union の最初の項は最適化可能なクエリでないため、最初の union のオペ ランドは空である。 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 401 view 使用法 参照 • 抽象プランで指定された抽象プランの抽出テーブルは、クエリで指定 された位置的に対応するテーブルと照合される。 • union 演算子は、次の処理を記述する。 • union、重複した値を削除する。 • union all、重複した値を保存する。 • 抽象クエリ・プランの union 演算子は、SQL クエリと同数の union の 項を持つ必要があり、抽象プランのオペランドの順序は、クエリの テーブルの順序と同じでなければならない。 • union クエリの処理に必要なソート・ステップとワーク・テーブルは、 抽象プランに示されていない。 • union クエリにより、最適化できない要素をリストする場合は、空の オペランドが必要である。from 句のない select クエリは、例に示さ れている。 i_scan, scan, t_scan view 説明 スキャンの対象となるベース・テーブルが含まれるビューを示す。 構文 view view_name パラメータ view_name クエリで指定されているビューの名前。クエリでデータベース名や所有 者名を使用する場合は、抽象プランでもそれらを指定する必要がある。 例 create view v1 as select * from t1 select * from v1 ( t_scan ( table t1 ( in ( view v ) ) ) ) テーブル t1 が使用されているビューを識別する。 クエリにビューが含まれる場合は、table (tablename ( in view_name )) を使用してテーブルを識別する必要がある。 使用法 • 参照 in, table 402 Adaptive Server Enterprise 第 18 章 抽象プラン言語リファレンス work_t 説明 格納先のワーク・テーブルを記述する。 構文 ( work_t [ worktable_name | (correlation_name worktable_name) ] ) パラメータ worktable_name ワーク・テーブルの名前。 correlation_name ワーク・テーブルに指定されている相関名。 戻り値 格納済みのテーブル。 例 select c12, max(c11) from t1 group by c12 ( plan ( store Worktab1 ( t_scan t1 ) ) ( t_scan ( work_t Worktab1 ) ) ) ベクトル集合関数を選択してワーク・テーブルに入れる 2 つのステップか ら成るプロセスを指定し、次に、ワーク・テーブルの結果を選択する。 使用法 • 格納先のテーブルをクエリ・プランのワーク・テーブルと照合する。 • store 演算子はワーク・テーブルを作成する。work_t 演算子は、あと で抽象プランで保管されているワーク・テーブルにアクセスするとき にそのワーク・テーブルを識別する。 • プラン取得モードの間、ワーク・テーブルは Worktab1、Worktab2 な どと識別される。手動で入力したプランには、どのような命名規則も 使用できる。 • ワーク・テーブルのスキャンを scan 演算子で明示的に指定しない場 合は、ワーク・テーブルに名前を付ける必要はなく、work_t 演算子 を省略できる。次のプランでは、例で使用した t_scan と work_t によ る指定の代わりに空の scan 演算子 “( )” を使用する。 ( plan ( store ( t_scan titles ) ) () ) パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 403 work_t • ワーク・テーブルの相関名は、次の例のように、セルフジョインの実 体化されたビューのみに必要である。 create view v as select distinct c11 from t1 select * from v v1, v v2 where ... ( plan ( store Worktab1 ( t_scan ( table t1 (in ( view v ) ) ) ) ) ( g_join ( t_scan (work_t ( v1 Worktab1 ) ) ) ( t_scan (work_t ( v2 Worktab1 ) ) ) ) ) 参照 404 store, view Adaptive Server Enterprise 索引 B 記号 # ( シャープ記号 ) テンポラリ・テーブルの識別プレフィクス () ( カッコ ) 空、i_scan 演算子用 380 空、union クエリ内 402 空、サブクエリ 397 空、ワーク・テーブルのスキャン 403 > ( より大きい ) 最適化 14 @@tempdbid グローバル変数 263 A abstract plan cache 設定パラメータ 352 abstract plan dump 設定パラメータ 352 abstract plan load 設定パラメータ 352 abstract plan replace 設定パラメータ 352 all キーワード union、最適化 136 ALS 使用するとき 50 ユーザ・ログ・キャッシュ 49 ログ・ライタ 51 ALS の使用が適する場合 50 ALS、「非同期ログ・サービス」参照 48 alter database コマンドと tempdbs 266 alter table コマンド 並列ソート 218 and キーワード サブクエリ 134 any キーワード サブクエリの最適化 126 asc インデックス・オプション 79–80 279 bcp ( バルク・コピー・ユーティリティ ) テンポラリ・テーブル 279 between 演算子選択性 統計値 20 between キーワード 最適化 9 C close on endtran オプション、set 309 close コマンド メモリ 296 count col_name 集合関数 最適化 89 count(*) 集合関数 最適化 89 CPU 使用率 157, 162 並列クエリのガイドライン 159 飽和 158, 160 CPU 使用率 CPU 集約クエリ 157 並列クエリ 162 create index コマンド number of sort buffers パラメータ 211, 220–225 with consumers 句 218 空き領域の動作条件 227 ログの考慮 228 cursor rows オプション、set 308 D dbcc ( データベース一貫性チェッカ ) 非同期プリフェッチ 241 非同期プリフェッチの設定 252 dbcc addtempdb と tempdbs 273 dbcc pravailabletempdbs と tempdbs 272 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 405 索引 deallocate cursor コマンド メモリ 296 declare cursor コマンド メモリ 296 desc インデックス・オプション 79–80 disk i/o structures 設定パラメータ 非同期プリフェッチ 244 distinct キーワード 並列最適化 209 DSS ( 意思決定支援システム ) アプリケーション 並列クエリ 139, 162 dump database コマンド 並列ソート 228 I exists check モード 350 exists キーワード 並列最適化 201 exists キーワード サブクエリの最適化 126 I/O 「大容量 I/O」参照 prefetch キーワード 42 キャッシュ間での分散 284 クエリに I/O サイズを指定 42 更新オペレーション 92 再フォーマットによる削減 125 直接更新 91 範囲クエリ 42 非同期プリフェッチ 237–254 飽和 158 I/O サイズ 指定 391 i_scan 演算子 379 IDENTITY カラム カーソル 298 in 演算子 ( 抽象プラン ) 380–382 in キーワード 最適化 84 サブクエリの最適化 126 F J FALSE、戻り値 127 for update オプション、declare cursor 最適化 307 forceplan 抽象プラン 377 forceplan オプション、set 37 ほかの選択 38 リスク 38 jtc オプション、set E G g_join 演算子 375–377 H hints 演算子 406 378 52 L like の最適化 9 lru スキャン・プロパティ LRU 置換方式 指定 46 382–383 M m_g_join 演算子 383–384 max async i/os per engine 設定パラメータ 非同期プリフェッチ 244 max async i/os per server 設定パラメータ 非同期プリフェッチ 244 max parallel degree 設定パラメータ 149, 192, 193 ソート 216 max scan parallel degree 設定パラメータ 149, 187 Adaptive Server Enterprise 索引 P max 集合関数 min との組み合わせ 90 最適化 89, 90 min 集合関数 max との組み合わせ 90 最適化 89, 90 model データベース、拡張 266 mru スキャン・プロパティ 385 MRU 置換方式 指定 46 非同期プリフェッチ 250 無効化 47 parallel キーワード、select コマンド 205 parallel スキャン・プロパティ 388–389 plan dump オプション、set 345 plan load オプション、set 347 plan replace オプション、set 347 plan 演算子 389–391 prefetch キーワード I/O サイズ 42 prefetch スキャン・プロパティ 391–392 prop 演算子 392–393 R N nested 演算子 385–387 nl_g_join 演算子 387–388 null カラム 更新の最適化 99 number of sort buffers 設定パラメータ 並列ソート 211, 220–225 並列ソート・メッセージ 230 number of worker processes 設定パラメータ RAID デバイス create index 218 コンシューマ 218 分割されたテーブル 159 S 149 O OAM「オブジェクト・アロケーション・マップ」参照 OLTP ( オンライン・トランザクション処理 ) 並列クエリ 171 open コマンド メモリ 296 or キーワード コストの見積もり 86 最適化 84 サブクエリ 134 ジョイン句の最適化 136 処理 85 OR 方式 85 カーソル 306 order by 句 並列最適化 201 order by 句 最適化 79 並列最適化 209 sa を専用の tempdb にバインドする 261 SARG「探索引数」参照 scan 演算子 393–394 select * コマンド ロギング 286 select into コマンド 並列クエリ 202 並列最適化 202 select into/bulkcopy/pllsort データベース・オプション 並列ソート 210 select コマンド parallel 句 153 インデックスの指定 40 set forceplan on 抽象プラン 377 set plan dump コマンド 346 set plan exists check 350 set plan load コマンド 347 set plan replace コマンド 347 set コマンド forceplan 37 jtc 52 noexec と statistics io の相互作用 59 parallel degree 152 plan dump 345 plan exists 350 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 407 索引 plan load 347 plan replace 347 scan_parallel_degree 152 sort_merge 51 sort_resources 229 statistics io 59 サブクエリ・キャッシュ情報 135 shared キーワード カーソル 297 sort_merge オプション、set 51 sort_resources オプション、set 229–232 sp_add_qpgroup システム・プロシージャ 358 sp_bindcache と tempdbs 271 sp_cachestrategy システム・プロシージャ 47 sp_changedbowner と tempdbs 272 sp_chgattribute システム・プロシージャ concurrency_opt_threshold 55 sp_cmp_qplans システム・プロシージャ 365 sp_copy_all_qplans システム・プロシージャ 366 sp_copy_qplan システム・プロシージャ 364 sp_dboption tempdbs 271, 272 sp_defaultloc と tempdbs 272 sp_drop_all_qplans システム・プロシージャ 370 sp_drop_qpgroup システム・プロシージャ 359 sp_drop_qplan システム・プロシージャ 364 sp_dropuser と tempdbs 272 sp_export_qpgroup システム・プロシージャ 370 sp_find_qplan システム・プロシージャ 362 sp_help_qpgroup システム・プロシージャ 359 sp_help_qplan システム・プロシージャ 363 sp_helpdb と tempdbs 271 sp_import_qpgroup システム・プロシージャ 371 sp_renamedb と tempdbs 272 sp_set_qplan システム・プロシージャ 366 sp_sysmon システム・プロシージャ ソート 234 並列ソート 234 sp_tempdb ストアド・プロシージャ 260 構文 260 SQL 抽出テーブル 320 最適化 7 SQL 標準 カーソル 292 statistics subquerycache オプション、set 135 store 演算子 394–395 実体化されたサブクエリ 398 subq 演算子 395–398 sysattributes と tempdbs 262 sysdatabases と tempdbs 262 408 T t_scan 演算子 398–399 table count オプション、set 39 table 演算子 399–400 tempdb データベース ストライプ化 280 セグメント 282 データ・キャッシュ 284 配置 282 パフォーマンス 277–288 領域の割り付け 283 ログイン 285 tempdb のストライプ化 280 ソートのパフォーマンス 227 tempdb_id() 関数 263 @@tempdbid グローバル変数 263 tempdbs Adaptive Server の以前のバージョンへの ダウングレード 276 alter database 266 dbcc addtempdb 273 dbcc pravailabletempdbs 272 sa を専用の tempdb にバインドする 261 sp_bindmsg 271 sp_changedbowner 272 sp_dboption 271, 272 sp_diskdefault 272 sp_dropkey 272 sp_helpdb 271 sp_renamedb 272 sp_tempdb 260 sp_tempdb の構文 260 sysattributes 262 sysdatabases 262 tempdb_id() 関数 263 @@tempdbid グローバル変数 263 アプリケーション用のサイズ指定と設定 274 インストールに関する注意事項 273 オープン・データベース数の設定 271 オブジェクトの明示的バインド 256 拡張 266 キャッシュ特性 266 共有テンポラリ・テーブル 258, 274 グローバル・リスト 259 高可用性 268 高可用性の設定 268 高可用性フェールオーバでの正常な コンパニオン動作 270 Adaptive Server Enterprise 索引 削除 258, 265 システム・テーブルの変更 262 ストアド・プロシージャ、処理 267 セッションによるテンポラリ・テーブルの 明示的な削除 257 セッションのバインド 261 セッション・テンポラリ・テーブル 257 説明 255 ソフト・バインド 261 ダンプ 270 データベースのキャッシュ・バインドを 変更する 267 ハード・バインド 261 バインド 256 フェールオーバ シナリオ 269 フェールオーバ時のマウント 270 複数データベースのトランザクション 273 プライベート・テンポラリ・テーブル 257 プロキシ・データベースのサポート 269 プロシージャ・テンポラリ・テーブル 257 プロシージャ・テンポラリ・テーブル、削除 258 並列クエリ 273 ユーザ作成の tempdbs をデータ・キャッシュに バインドする 267 ユーザ作成のストアド・プロシージャの更新 275 ユーザ作成のテンポラリ・データベース 256 ロード 270 ロールバックとリカバリ 264 ログ・トランケーション 263 tempdbs とシステム tempdb 255 tempdbs のダンプ 270 tempdbs のロード 270 TRUE、戻り値 127 U union 演算子 並列最適化 201 union 演算子 401–402 カーソル 306 サブクエリ・キャッシュの番号付け ジョインの最適化 136 並列最適化 210 135 V view 演算子 402 W with consumers 句、create index work_t 演算子 403–404 218 あ 空き領域 ワークテーブル・ソート時の動作条件 227 アクセス 「アクセス・メソッド」参照 オプティマイザ・メソッド 172–184 アクセス・メソッド 172 選択 184 パーティションベース 172 ハッシュベース 172 ハッシュベース・スキャン 172 並列 172–185 レンジベース・スキャン 172 値 不定、最適化 32 アプリケーション開発 インデックスの指定 40 カーソル 309 テンポラリ・テーブル 281 アプリケーション用の tempdbs のサイズ設定 274 い インストールと tempdbs に関する注意事項 インデックス カーソルによる使用 297 クエリへの指定 40 更新オペレーション 91, 92 更新モード 99 作成 209 ソートの回避 77 大容量 I/O 42 テンポラリ・テーブル 279, 288 動的 88 並列作成 209 インデックス結果のマージ 215 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 273 409 索引 インデックスの遅延更新 94 インデックス・カバーリング ソート・オペレーション 83 インデックス・キー 順序付けの asc オプション 79–80 順序付けの desc オプション 79–80 インデックス・スキャン i_scan 演算子 379 式サブクエリ 131 集合 89, 201 ジョイン順 189–192 テンポラリ・テーブル 286 プロシージャのパラメータ 21 並列クエリ 169–208 問題の原因 7 問題の診断 6, 206 オペランド リスト 373 う ウォッシュ・エリア 並列ソート 226 え エラー・メッセージ process_limit_action 204 実行時調整 204 演算子 探索引数内 15 不等、探索引数内 16 エンジン 数 157 お 応答時間 並列最適化 170 オーバヘッド カーソル 302 遅延更新 94 並列クエリ 171 置き換え更新 91 遅いクエリ 6 オブジェクト・アロケーション・マップ コスト計算 64 オプティマイザ 4–32, 61–100, 101–136, 169–208 「並列クエリ最適化」参照 or 句 84 上書き 35 限定述語サブクエリ 126 更新 98 再フォーマット方式 125 サブクエリ 126 410 か カーソル OR 方式による最適化 88 インデックス 297 更新可能 297 実行 296 ストアド・プロシージャ 296 独立性レベル 304 ハロウィーン問題 298 複数 309 モード 297 読み込み専用 297 ロック 294 カーソルのフェッチ メモリ 296 外部ジョイン 108 順列 106 ジョイン順 106 拡張 model データベース 266 tempdbs 266 数(量) エンジン 157 オプティマイザが検討するテーブル数 39 カーソル・ロー 308 カバード・クエリ キャッシュ方式の指定 45 カバーリング・ノンクラスタード・インデックス コスト 72 範囲クエリのコスト 72 非同期プリフェッチ 241 不等演算子 16 空のカッコ i_scan 演算子 380 Adaptive Server Enterprise 索引 union クエリ 402 サブクエリ 397 ワーク・テーブルのスキャン 関連付けキー sp_cmp_all_qplans 367 sp_copy_qplan 364 定義 316 プランの関連付け 316 クエリとプランの関連付け セッションレベル 347 プラン・グループ 315 クエリの最適化 6 OAM スキャン 64 クエリ分析 61–100, 101–136 sp_cachestrategy 47 ツール 57–60 クエリ・プラン オプティマイザ 4 更新可能カーソル 306 最良の次に良い 40 実行時調整 202–203 クラスタード・インデックス create index の動作条件 217 空き領域の動作条件 227 スキャンと非同期プリフェッチ 範囲クエリのコスト 70 非同期プリフェッチとスキャン プリフェッチ 42 ポイント・クエリのコスト 69 403 き キーワード リスト 373 キー、インデックス 更新オペレーション 91 記号 SQL 文内 xx キャッシュ特性と tempdbs 266 キャッシュ方式のプロパティ 指定 382, 385 キャッシュ、データ tempdb の専用キャッシュへのバインド サブクエリの結果 135 ソート 221–222 テーブル・スキャン 63 並列ソート 220 キャッシュ・ヒット率 分割 162 キャンセル 調整クエリ・プラン 204 競合 tempdb 内のシステム・テーブル 285 共有テンポラリ・テーブル 258, 274 共有ロック 読み込み専用カーソル 297 く クエリ I/O サイズの指定 42 インデックスの指定 40 並列 169–208 クエリ処理 手順 4 並列 138–167 241 241 284 け 検索、抽象プラン 362 限定述語サブクエリ 最適化 126 集合関数 132 こ 高可用性 tempdb 268 tempdbs の設定 268 tempdbs のマウント 270 高可用性フェールオーバでの正常な コンパニオン動作と tempdbs 高コストの直接更新 93 降順 (desc キーワード ) 79, 82 カバード・クエリ 83 降順スキャン デッドロック 83 更新オペレーション 91 更新カーソル 297 更新モード インデックス 99 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 270 411 索引 置き換え 91 高コストの直接更新モード 93 最適化 98 ジョイン 94 遅延 93 遅延インデックス 94 直接 94 低コストの直接更新モード 92 トリガ 98 更新ロック カーソル 297 コーディネーティング・プロセス 139, 215 コスト クラスタード・インデックスを使う範囲クエリ 70 ソート・オペレーション 77 ノンクラスタード・インデックスを使う 範囲クエリ 72, 73 並列クラスタード・インデックス・ パーティション・スキャン 176 並列ノンクラスタード・インデックス・ ハッシュベース・スキャン 180 並列パーティション・スキャン 174 並列ハッシュベース・テーブル・スキャン 178 ポイント・クエリ 69 コストの見積もり or 句 86 インデックス 4 再フォーマット 125 サブクエリの最適化 135 実体化 133 ジョイン 22 パフォーマンスの良いクエリ処理と悪い クエリ処理 5 固定長カラム インデックスと更新モード 100 コピー 抽象プラン 364 プラン 364, 366 プラン・グループ 366 コンシューマ・プロセス 214, 230 さ 再コンパイル 実行時調整の回避 205 サイズ tempdb データベース 280 412 最適化 「並列クエリ最適化」参照 in キーワード 84 OAM スキャン 177 order by を含むクエリ 79 SQL 抽出テーブル 7 カーソル 296 サブクエリの処理順序 136 並列クエリ 169–208 最適化における応答時間と合計作業量の比較 170 最適化の問題の原因 7 最適化の問題の症状 6 再フォーマット 125 ジョイン 125 並列最適化 210 再フォーマット方式 i_scan を使用して禁止する 380 t_scan を使用して禁止する 399 抽象プランでの指定 395 削除 index を使って指定したインデックス 41 tempdbs 265 抽象プラン・グループ 359 プラン 364, 370 削除オペレーション ジョインでの更新モード 94 ジョインと更新モード 94 作成 抽象プラン・グループ 358 サブクエリ any、最適化 126 exists、最適化 126 in、最適化 126 結果のキャッシュ 135, 200 限定述語、最適化 126 最適化 126, 200 式、最適化 131 実体化 131 実体化された 398 ネスト 385 ネストとビュー 382 ネストの例 396 付着 136 フラット化 126 フラット化された 398 プランでの識別 395 並列最適化 200 Adaptive Server Enterprise 索引 参照整合性 更新 94 更新オペレーション 92 し 式サブクエリ 最適化 131 識別子 リスト 373 システム・テーブル tempdbs 262 システム・プロシージャ、変更 51 実行カーソル メモリ使用 296 実行時調整 194, 202–205 影響 203 回避 205 識別 204 定義 153 実体化されたサブクエリ 131, 398 集合関数 最適化 89, 90 サブクエリ 132 正規化の解除とテンポラリ・テーブル 281 並列最適化 201 集合指向プログラミング ロー指向プログラミングとの比較 292 重複するロー ワークテーブルからの削除 87 順序 ジョイン 189–192 ジョインでのテーブル 37, 104 ジョイン or 句の最適化 136 union 演算子の最適化 136 インデックス密度 102, 126 オプティマイザが扱うテーブル数 39 オプティマイザによるインデックスの構築 22 更新 92, 93, 94 更新モード 94 最適化 101 処理 22 多数のテーブル 103, 104 データ型の互換性 30 テーブルの順序 37 テンポラリ・テーブル 281 ネストループ 107 並列最適化 189–192, 197–199 並列でのテーブル順 189–192, 197–199 ジョイン演算子 g_join 375 m_g_join 383 nl_g_join 387 ネストループ・ジョイン 387 マージ・ジョイン 383 ジョイン順 外部ジョインの制限 106 ジョイン推移閉包 定義 11 有効化 11 ジョインの内部テーブル 108 昇順 79, 82 処理能力 157 す 推移閉包 ジョイン 11 推移閉包、探索引数 (SARG) 10 数値式 xxii スキャン、テーブル コスト 63 スキャン・プロパティ 指定 392 ストアド・プロシージャ カーソル 300 最適化 21 テンポラリ・テーブル 289 分割 20, 21 ストアド・プロシージャ、tempdbs に対する処理 267 せ 正規化 テンポラリ・テーブル 281 正規化の解除 テンポラリ・テーブル 281 制限 並列クエリ処理 148, 152 並列ソート 148 ワーカー・プロセス 148, 152 整数データ SQL xxii パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 413 索引 クエリの最適化 14 セグメント tempdb 282 ターゲット 216, 230 並列ソート 216 並列ソートのパフォーマンス 227 セッションのバインドと tempdbs 261 セッション・テンポラリ・テーブル 257 接続 カーソル 309 設定 アプリケーション用の tempdbs 274 オープン・データベース数、tempdbs 271 設定サーバ 並列クエリ処理 149 設定用コマンド 248 そ 相関名 テーブル用 399 ビュー 404 挿入オペレーション ロギング 285 総密度 19 ソート順 降順 79, 82 昇順 79, 82 ソート操作 (order by) ソート・プラン 229 パフォーマンスの問題 278 ソート・オペレーション (order by) 「並列ソート」も参照 インデックスなし 77 カバーリング・インデックス 83 ノンクラスタード・インデックス 83 ソート・バッファ set sort_resources 230 ガイドライン 221 使用できる最大ページ数の計算 223 設定 221–222 並列ソートの動作条件 211 ソート・バッファの数 222 速度 ( サーバ ) select into 285 インデックスの遅延削除 97 置き換え更新 91 414 遅いクエリ 6 高コストの直接更新 93 更新 91 ソート・オペレーション 遅延更新 93 直接更新 91 低コストの直接更新 92 ソフト・バインドと tempdbs 215 261 た ターゲット・セグメント 216, 230 大容量 I/O インデックス・リーフ・ページ 42 非同期プリフェッチ 248 タスク CPU リソース 157 探索引数 インデックス 15 インデックスを使用できる探索引数 演算子 15 構文 15 推移閉包 10 データ型の一致 24 統計 17 同等な句 9 並列クエリ最適化 174 例 16 探索引数と同等な句 9 断片化、データ 非同期プリフェッチへの作用 245 ページ・チェーン 245 15 ち 遅延更新 93 中間選択性 20 抽出テーブル SQL 抽出テーブル 320 抽象プランの抽出テーブル 抽象プラン sp_help_qplan による表示 関連情報 363 検索 362 コピー 364 パターン一致 362 320 363 Adaptive Server Enterprise 索引 比較 365 抽象プランの検索 362 抽象プランの修正 366 抽象プランの抽出テーブル 320 定義 374 抽象プランの比較 365 抽象プラン・グループ インポート 371 エクスポート 370 管理のためのプロシージャ 357–371 関連情報 359 削除 359 作成 358 使用の概要 315 追加 358 プランの関連付け 315 プランの取得 315 抽象プラン・グループのインポート 371 チューニング 高度な手法 35–55 範囲クエリ 40 非同期プリフェッチ 247 並列クエリ 160 並列クエリ処理 157–163 並列ソート 220–228 直接更新 91 置き換え 91 高コスト 93 ジョイン 94 低コスト 92 つ 追加 抽象プラン・グループ て 低コストの直接更新 92 定数 xxii ディスク・デバイス I/O 速度 159 並列クエリ 155, 158 並列ソート 226, 228 データ型 クエリ内での一致 24 358 データ修正 更新モード 91 データベース・デバイス 並列クエリ 159 データ・キャッシュ tempdb の専用キャッシュへのバインド 284 サブクエリ・キャッシュ 135 ソート・バッファ 223 テーブル・スキャン時のフラッシュ 63 並列ソート 223, 226 データ・ページ プリフェッチする 43 テーブル 正規テーブル、tempdb 内 279 テーブル・スキャン OAM スキャン・コスト 177 キャッシュのフラッシュ 63 強制的に実行 40 コストの評価 63 指定 398 非同期プリフェッチ 241 手順 遅延更新 93 直接更新 91 分布表上のキー値 18 テスト インデックスの強制 40 デッドロック 降順スキャン 83 テーブル・スキャン 55 同時実行性の最適化スレッショルドの設定 55 デバイス RAID 159 デバッグのためのツール set forceplan on 37 デフォルト設定 インデックスの統計値 22 検討されるテーブル数 39 テンポラリ・データベースのグローバル・リスト 259 テンポラリ・テーブル インデックス 288 永続的 279 最適化 286 正規化 281 正規化の解除 281 ネスト・プロシージャ 288 パフォーマンスの考慮 278 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 415 索引 と の 等価ジョイン サブクエリの変換 131 統計値 between 選択性 20 サブクエリ・キャッシュの使用率 等選択性 20 同時実行性の最適化 小さいテーブル 55 同時実行性の最適化スレッショルド デッドロック 55 等選択性 dbcc traceon(302) の出力 22 統計値 20 動的インデックス 88 or クエリの最適化 85 特殊な OR 方式 85, 88 独立性レベル カーソル 304 トランザクション ロギング 285 トランザクション・ログ 更新オペレーション 91 トリガ 更新オペレーション 92 更新モード 98 ノンクラスタード・インデックス create index の動作条件 218 カバード・クエリとソート 83 ソート 83 ハッシュベース・スキャン 178–180 範囲クエリのコスト 72, 73 非同期プリフェッチ 241 ポイント・クエリのコスト 69 な 名前 index 句 41 インデックスのプリフェッチ カラム、探索引数内 15 43 ね ネスト テンポラリ・テーブル 288 ネストループ・ジョイン 107 指定 387 ネットワーク カーソルのアクティビティ 302 416 135 は パーティションベース・ スキャン 173–174, 174–176, 184 非同期プリフェッチ 251 ハードウェア 並列クエリ処理のガイドライン 159 ハード・バインドと tempdbs 261 バイナリ式 xxii バインド tempdb 284 バインドと tempdbs 256 ハッシュベース・スキャン I/O 172 set scan_parallel_degree の制限 152 インデックス 184 テーブル・スキャン 177–178 ノンクラスタード・インデックス 178–180, 184 ヒープ・テーブル 184 非同期プリフェッチ 250 ワーカー・プロセス 172 バッチ処理 テンポラリ・テーブル 287 バッファ 使用不可 44 ソート 221–222 バッファ・プール I/O サイズの指定 391 パフォーマンス order by 79–80 tempdb 277–288 遅いクエリの診断 206 オプティマイザが扱うテーブル数 39 実行時調整 203 データオンリーロック・テーブルに対するクエリの コスト見積もり 64 Adaptive Server Enterprise 索引 パラメータ、プロシージャ 最適化 21 ハロウィーン問題 カーソル 298 範囲 分割ソート 214 範囲クエリ 大容量 I/O 42 範囲セル密度 19 範囲選択性 20 ひ 非同期プリフェッチ 237, 248 dbcc 241, 252 MRU 置換方式 250 管理 253 大容量 I/O 248 断片化 245 逐次スキャン 241 チューニング目標 247 ノンクラスタード・インデックス 241 パーティションベース・スキャン 251 ハッシュベース・スキャン 250 パフォーマンス・モニタリング 254 プール制限値 244 並列クエリ処理 250 ページ・チェーンの断片化 245 ページ・チェーンのねじれ 245, 253 予備セット 238 リカバリ 251 リカバリ中 240 非同期ログ・サービスの使用 48 非同期ログ・サービスの使用、ALS 48 非マッチング・インデックス・スキャン 不等演算子 16 ビュー サブクエリのネスト 382 相関名 404 テーブルのロケーションの指定 380 表記規則 マニュアルで使用 xx ふ プール、ワーカー・プロセス 139 サイズ 153 プール・サイズ 指定 391 フェールオーバ シナリオと tempdbs 269 複写 更新オペレーション 92 複数データベースのトランザクションと tempdbs 273 複数のテンポラリ・データベース「tempdbs」参照 複数のマッチング・インデックス・スキャン 85, 88 複製 更新パフォーマンスの影響 94 浮動小数点データ xxii 部分プラン create plan での指定 315 hints 演算子 378 プライベート・テンポラリ・テーブル 257 フラット化されたサブクエリ 126, 398 プラン 検索 362 コピー 364, 366 削除 364, 370 修正 366 比較 365 変更 366 プランの取得 セッションレベル 346 プラン・グループ エクスポート 370 関連情報 359 コピー 366 削除 359 作成 358 使用の概要 315 すべてのプランの削除 370 追加 358 テーブルへのコピー 370 プランの関連付け 315 プランの取得 315 レポート 359 プラン・グループのエクスポート 370 プリフェッチ sp_cachestrategy 47 クエリ 42 データ・ページ 43 パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 417 索引 非同期 237–254 無効化 45 有効化 45 プレフィクス・サブセット order by 83 定義 18 例 18 プロキシ・データベースのサポートと tempdbs プロシージャ・テンポラリ・テーブル 257 削除 258 プロデューサ・プロセス 214, 230 分割 RAID デバイス 159 キャッシュ・ヒット率 162 最適化のプロシージャ 20, 21 設定のガイドライン 162 並列最適化 171 分割されたテーブル create index 217, 218, 228 データ分配の不整合 174 並列最適化 172, 185 ワークテーブル 183 分割されたテーブルの不整合 クエリ・プランへの影響 174 定義 174 分散マップ 213, 230 へ 並列クエリ ワークテーブル 201 並列クエリ最適化 169–208 exists 句 201 order by 句 201 select into クエリ 202 union 演算子 201 オーバヘッド 170, 171 サブクエリ 200 システム・テーブル 170 集約を伴うクエリ 201 ジョイン順 189–192, 197–199 使用条件 170 シングルテーブル・スキャン 195–196 逐次最適化との比較 170 定義 169 トラブルシューティング 206 418 269 分割の考慮 171, 172 並列度 185–194 目標の速度 170 リソース制限 208 例 194–205 並列クエリ処理 138–167, 169–208 CPU 使用率 157, 159, 162 I/O 158 クエリの種類 138 実行段階 141 ジョイン 146 設定 149 ディスク・デバイス 158 ハードウェアのガイドライン 159 非同期プリフェッチ 250 マージ方式 142 リソース 157 ワーカー・プロセスの制限 149 ワーカー・プロセスの設定 151 並列クエリと tempdbs 273 並列クラスタード・インデックス・パーティション・ スキャン 174–176 概要 184 使用コスト 176 定義 174 並列クラスタード・インデックス・パーティション・ スキャン (parallel clustered index partition scan) 使用条件 176 並列ソート 209–234 number of sort buffers パラメータ 211 select into/bulk copy/pllsort オプション 210 sort_resources オプション 229 tempdb 227 with consumers 句 218 影響されるコマンド 209 概要 212 監視 229–232 クラスタード・インデックスの動作条件 217 結果のマージ 215 コーディネーティング・プロセス 215 サブインデックス 214 実行の条件 210 十分な数のソート・バッファの設定 222 ソート・バッファ 221–222, 230 ターゲット・セグメント 216 チューニング用のツール 229 データのサンプリング 213, 230 Adaptive Server Enterprise 索引 動的な範囲による分割 214 ノンクラスタード・インデックスの動作条件 218 範囲ソート 214 必要なリソース 210, 215 プロデューサ・プロセス 214 分散マップ 213, 230 並列度 218, 230 マージの実行 214 リカバリ 228 例 230–232 ロギング 228 ワーカー・プロセスの設定 151 ワークテーブル 219 並列ソートのためのサンプリング 213, 230 並列度 148, 185–194 クエリレベル 153 サーバレベル 149 最適化 186 実行時調整 194, 202–205 指定 388 ジョイン 189, 191 上限値 186 セッションレベル 152 定義 185 並列ソート 218 並列ノンクラスタード・インデックス・ ハッシュベース・スキャン 178–180 概要 184 使用コスト 180 並列パーティション・スキャン 173–174 概要 184 使用コスト 174 使用条件 174 定義 173 例 195 並列ハッシュベース・テーブル・スキャン 177–178 概要 184 使用コスト 178 使用条件 178 定義 177 ページ、データ プリフェッチ 43 ページ・チェーンのねじれ クラスタード・インデックス 253 定義 245 ノンクラスタード・インデックス 253 ヒープ・テーブル 253 非同期プリフェッチ 245, 253 変換 in (value_list) から or 句への変換 84 サブクエリの等価ジョインへの変換 131 データ型 30 変更されたシステム・プロシージャ 51 変数 オプティマイザ 21 ほ 飽和 CPU 158 I/O 158 ま マージの実行、並列ソート 減少 222 マージ・ジョイン 抽象プラン 384 214, 221 み 密度 インデックス、ジョイン 総密度 19 範囲セル 19 102, 126 め メッセージ インデックスの削除 41 メモリ カーソル 294 メンテナンス作業 forceplan の確認 37 強制されたインデックス 41 も 文字式 xxii パフォーマンス&チューニング・ガイド:オプティマイザと抽象プラン 419 索引 ゆ ろ ユーザ ID sp_import_qpgroup による変更 371 ユーザ作成の tempdbs 256 ユーザ作成の tempdbs をデータ・キャッシュに バインドする 267 ユーザ・ログ・キャッシュ、ALS 内 49 ユニーク・インデックス 更新モード 99 ロー ID (RID: row ID) 更新オペレーション 91 ロールバックとリカバリ、tempdbs ロギング tempdb 内での最小化 285 並列ソート 228 ログ・トランケーションと tempdbs ロック tempdb 285 ワークテーブル 285 論理式 xxii よ 予備セット 238 dbcc 241 逐次スキャン 241 ノンクラスタード・インデックス リカバリ中 240 読み込み専用カーソル 297 インデックス 297 ロック 303 り リカバリ 非同期プリフェッチ 240 非同期プリフェッチの設定 並列ソート 228 リソース制限 205 領域の割り付け tempdb 283 れ レポート キャッシュ方式 47 プラン・グループ 359 レンジベース・スキャン I/O 172 ワーカー・プロセス 172 420 251 264 263 わ 241 ワーカー・プロセス 139 オーバヘッド 171 クラスタード・インデックス 217 コーディネーティング・プロセス 215 コンシューマ・プロセス 214 実行時調整 194, 202–205 指定 388 ジョイン 189 設定 151 ノンクラスタード・インデックス 218 プール 139 プール・サイズ 153 プロデューサ・プロセス 214 並列ソート 218 並列ソートの動作条件 216 リソース制限 208 ワークテーブル・ソート 219 ワーカー・プロセスのファミリ 139 ワークテーブル or 句 87 tempdb 280 空き領域の動作条件 227 再フォーマット 125 分割 183 並列クエリ 183, 201 並列ソート 201, 219, 221 ロック 285 ワーク・テーブル store 演算子 394 ワーク・テーブルのスキャン 空の scan 演算子 403 Adaptive Server Enterprise