テラバイトクラスのDBシステムを扱っていると、データ量が増えるたびに、特定のSQLが極端に遅くなることがあります。
その時に、遅くなったSQLの実行プランを確認すると、インデックススキャン(Index seek)のコストが跳ね上がり、SQL全体のコストの100%近くを、インデックススキャンが占めるように変化しています。
インデックススキャンのコストは、SQL全体で20%未満になっているのが、妥当な値です。
極端に遅くなっている、もしくは、コストが高くなっているSQLは、SQLServerのチューニングアドバイザーにかけると、インデックスと統計情報が抽出されるので、それを適用する事で解決できます。
※SQLが遅くなっているサーバーで、チューニングアドバイザーを実行せず、別のサーバーでチューングアドバイザーにそのSQLをかけると、必要なインデックスと統計情報が抽出されない事があるので、そこは注意が必要です。
テラバイトクラスのDBシステムを1年以上運用していて、今回初めて、必要なインデックスと統計情報を追加しても、IISからのDB処理だけ処理性能が改善しない、という現象に遭遇しました。
Management Studioからだと、遅くなっているSQLの実行プランは改善され、実行時間も1秒程度なのに対し、WEBサイトからそのSQLを実行すると、5分たっても結果が返って来ませんでした。
【環境】
WEBサーバー:Windows Server 2008 R2 SP1
DBサーバー:Windows Server 2008 R2 SP1、SQLServer 2008 R2 SP2 CU3
WEBサイトは.Net4.0で構築
色々試した結果、WEBサイトから実行した場合のみ遅い現象が発生したら、ストアドのリコンパイルが有効だという事が分かりました。ユーザー定義関数を利用している場合は、関数のリコンパイルも必要です。
ストアドに実行プランをキャッシュする、こちらのアーキテクチャにバグがあって、IIS側からアクセスされた場合に、古い実行プランを使い続けていたのが原因でした。
http://msdn.microsoft.com/ja-jp/library/ms181055(v=sql.105).aspx
http://msdn.microsoft.com/ja-jp/library/ms191007(v=sql.105).aspx
そういえば、SQLServerはIISのキャッシュを、別扱いするという技術資料を、以前どこかで読んだ気がします。
毎日のように、インデックスと統計情報を追加しているシステムなので、再発防止として、インデックスと統計情報を追加する頻度の高いテーブル、ストアド、ユーザー定義関数は全て、日次で夜間に、sp_recompile を実行するようにしました。
http://msdn.microsoft.com/ja-jp/library/ms181647.aspx
【関連記事】
チューニングアドバイザーによる、インデックスと統計情報の抽出と追加
テーブルの統計情報を、週次で更新
ストアドとファンクションを、日次のジョブで毎朝リコンパイル
IISと関連サービスを、日次で毎朝再起動。
IISと関連サービスからのDB処理が、極端に遅くなるストアド、ファンクションは、使用するインデックスをヒント文で固定する
SQLServerで、IISからのDB処理だけが遅い場合は、ストアドをリコンパイルする
SQLServer 2005 インデックス チューニング ライフサイクル
6ヶ月以上使われていないインデックスを抽出するSQL
最近のコメント