http://blogs.wankuma.com/esten/archive/2007/12/03/111565.aspx
の続き(汗)
あいかわらず、苦しみぬいているSQLServerでのSQL処理チューニング。一度書いたSQL文を使い回すぜオー!と意気込んで、ただいまソースおよび生成SQLを鋭意チェック中。そんな中でのちょいメモw
まずは、ここをチェック。
http://www.microsoft.com/japan/technet/prodtechnol/sql/2005/recomp.mspx
つまりだ、
SQL Server では、2 つのアドホック クエリのテキストが完全に一致する必要があります。テキストの一致では、大文字と小文字、およびスペースの有無が区別されます。
ってな事なんで、プログラムで生成するSQL文処理をしていると、この辺りは杞憂。キャッシュはがんがん入るから有利になれるはず(^^; もちろん、その上で、プログラム上でパラメータ化できるところはとことんパラメータ化。んでもって、ProFilerで流れてくるSQL文をチェックして、使いまわし出来ているのかドキドキに見守るw、CacheHitイベントの発生がドドドーっと来ると、パラメータ化が出来てて、SQLServer自身も「使いまわしてあげてもよろしくってよ」と微笑んでくれているんだと解釈できるんだよね? そうだよね? そうだといってよ、DBサーバー(おい)
この際、パラメータ化できるところはパラメータ化なんていってても、何が何でもパラメータ化して楽しておけるわーってわけではないらしく、記事抜粋。
----------------------
以下に、SQLServer2005で自動パラメータ化されないステートメントの種類を記載します。
?IN句を含むクエリは自動パラメータ化されません。以下に例を示します。
WHEREProductIDIN(707,799,905)
?BULKINSERTステートメント。
?変数が含まれているSET句を含むUPDATEステートメント。以下に例を示します。
UPDATE Sales.Customer
SET CustomerType=N'S'
WHERE CustomerType=@a
?UNIONを含むSELECTステートメント。
?INTO句を含むSELECTステートメント。
?FORBROWSE句を含むSELECTまたはUPDATEステートメント。
?OPTION句を使用して指定されたクエリヒントを含むステートメント。
?DISTINCTを含むSELECTリストを持つSELECTステートメント。
?TOP句を含むステートメント。
?WAITFORステートメント。
?FROM句を含むDELETEまたはUPDATE。
?FROM句に以下のいずれかが含まれている場合。
?複数のテーブル
?TABLESAMPLE句
?テーブル値関数またはテーブル値変数
?フルテキストテーブル
?OPENROWSET
?XMLUNNEST
?OPENXML
?OPENQUERY
?IROWSET
?OPENDATASOURCE
?テーブルヒントまたはインデックスヒント
?SELECTクエリにサブクエリが含まれている場合。
?SELECTステートメントにGROUPBY、HAVING、またはCOMPUTEBYが含まれている場合。
?WHERE句内でORで結合されている式。
?「expr<>non-null-constant」という形式の比較述語。
?フルテキスト述語。
?INSERT、UPDATE、またはDELETE内の対象となるテーブルがテーブル値関数の場合。
?EXECstringで送信されたステートメント。
?TF447で自動パラメータ化されるパラメータを使用せずに、sp_executesql、sp_prepare、およびsp_prepexecで送信されたステートメント。
?クエリ通知が要求される場合。
?クエリに共通テーブル式の一覧が含まれる場合。
?クエリにFORUPDATE句が含まれる場合。
?UPDATEにORDERBY句が含まれる場合。
?クエリにGROUPING句が含まれる場合。
?INSERTINTOTDEFAULTVALUESという形式のINSERTステートメント。
?INSERT...EXECステートメント。
?クエリに2つの定数の比較が含まれている場合。以下に例を示します。
WHERE 20 > 5
----------------------
とにかく、今回のサーバーさん、たくさんたくさんキャッシュを見て、情報ゲッチュー♪しているのをProfilerで確認。使えば使うほど、少しずつですがパフォーマンスはあがるはずです。
後は、クエリ最適化において作成される実行プランときっても切り離せない、統計情報をおさらいw
ってことでここ。
http://www.microsoft.com/japan/technet/prodtechnol/sql/2005/qrystats.mspx
http://www.mssqltips.com/tip.asp?tip=1193
http://sqlserver-qa.net/blogs/perftune/archive/2007/07/23/usage-and-good-practices-with-update-statistics-feature-in-sql-2005.aspx
まーようするに、統計情報は作っとけとw 自動でちまちまと入れといて、使いまわしきくようにしとかんとあかんでー、という世界らしい。
でも、統計情報の過信は禁物、こっちも読んどけ、と
http://support.microsoft.com/kb/195565/ja
で出てくるキーワード、rowmodctr
こいつについては
http://technet.microsoft.com/ja-jp/library/ms190283.aspx
で、閑話休題、こんなSQLをこっそりと作ってみる
1: select
2: sys.objects.name as [TBL_Name],
3: sys.indexes.name as [IDX_Name],
4: sys.sysindexes.indid as [IDX_SEQ],
5: sys.sysindexes.keycnt as [KeyCount],
6: sys.sysindexes.rows as [RowCount],
7: sys.sysindexes.rowmodctr as [RowModCTR],
8: sys.sysindexes.reserved as [PageSize],
9: CASE sys.sysindexes.reserved
10: WHEN 0 THEN '0'
11: ELSE sys.sysindexes.used * 100 / sys.sysindexes.reserved
12: END as [Usage%],
13: sys.dm_db_index_usage_stats.user_seeks as [SeekCount],
14: sys.dm_db_index_usage_stats.user_updates as [UpdateCount]
15: from sys.sysindexes
16: inner join sys.indexes on sys.indexes.object_id = sys.sysindexes.id
17: inner join sys.objects on sys.objects.object_id = sys.sysindexes.id
18: and sys.objects.type ='U'
19: INNER JOIN sys.dm_db_index_usage_stats ON
20: sys.dm_db_index_usage_stats.object_id = sys.sysindexes.id
21: order by [TBL_Name],[IDX_Name],[IDX_SEQ]
今あるインデックスはどれだけ作られてて、どれくらい使われてて、どれくらい更新されてるのか?
走らせてみた結果、使い回しは頑張っているらしい。サーバーなりにw
結論:
個々のSQL文のチューニング、つまったら次は全体処理のチューニング、それでもダメなら……遠くを見つめて長ーく溜息。