TSQL:大量のSQLコンパイルとSQL再コンパイルを個別に引き起こすクエリを見つける


8

パフォーマンスモニターカウンターに表示されるSQLコンパイルの高さ(再コンパイルではない)の原因を調べたい。

これが私の見解です:SQlコンパイルが大量に表示される場合は、次の理由により、システム上のクエリがキャッシュされていません。

  • 多くのアドホッククエリ
  • SQlがキャッシュしないクエリの実行:

    UPDATE table1 SET col1 = '8000文字より長い文字列.....' WHERE key_column = some int

  • プランがタイムアウトして、キャッシュから削除されています。キャッシュのスペースが不足しているか、プランが十分に長く使用されていません。

プロファイラーでのキャッシュ挿入のキャプチャに近い唯一のことは、ストアドプロシージャ-> SP:CacheInsertsですが、ストアドプロシージャキャッシュの管理のみを行います。

だから私はアドホッククエリを取得するために以下を試しました:

SELECT [cp].[refcounts] -- when Refcounts becomes 0, plan is excluded from cache.
    , [cp].[usecounts] 
    , [cp].[objtype] 
    , st.[dbid] 
    , st.[objectid] 
    , st.[text] 
    , [qp].[query_plan] 
FROM sys.dm_exec_cached_plans cp     
CROSS APPLY sys.dm_exec_sql_text ( cp.plan_handle ) st     
CROSS APPLY sys.dm_exec_query_plan ( cp.plan_handle ) qp ;

コンパイルの原因となったクエリはobjtype = Adhocのクエリであると考えましたが、これも再コンパイルに関連している可能性があります。次に、プロファイラーを実行し、クエリをキャプチャして再コンパイルを行い、上記のリストから除外する必要があります。

私は正しい方向に進んでいますか?

あまり作業をせずにSQLコンパイルだけを実行するために使用できる単一のクエリはありますか?

上記の知識を得るのに役立つリソース:

http://social.msdn.microsoft.com/Forums/en/sqldatabaseengine/thread/954b4fba-3774-42e3-86e7-e5172abe0c83 http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=143946 http: //technet.microsoft.com/en-nz/library/cc966425(en-us).aspx
http://www.sqlservercentral.com/Forums/Topic914951-360-1.aspx

どんな助けでも本当に感謝しています。

回答:


7

簡単な方法でこれを見つけることはできないと思いますが、とにかくこれを通り抜けることは可能です。プロファイラーは、クエリのパフォーマンスの分析に使用できる多くのイベントクラスタイプを提供します。新しいプロファイラーセッションを開始し、次のイベントを確認します。

Performance: Performance statistics
Stored Procedures: RPC:Completed
TSQL: SQL:BatchCompleted
TSQL: SQL: BatchStarting

[すべての列を表示する]チェックボックスをオンにし、[パフォーマンス:パフォーマンス統計イベントのみ]の下の各列を選択します。残りのイベントはデフォルト設定のままにしておくことができます。

次に、列フィルターを選択し、知っている場合はDatabaseNameやLoginName / ApplicationName / HostNameなどでフィルターします。目的は、プロファイラーに表示される行数を制限し、ユーザーのニーズのみに集中することです。

次に、[実行]を押してしばらく実行します(必要に応じて2〜3分)。主に以下を見て、表示された結果を分析します:パフォーマンス統計イベント。

パフォーマンス統計が頻繁に発生する場合は、クエリのプランが初めてキャッシュされ、コンパイル、再コンパイル、またはPlanCacheから削除されたことを意味します。クエリのプランキャッシュにクエリプランがない場合の私の知識から-2行のPerformanceStatisticsイベントが表示され、その後にSQL:BatchStarting、次にSQL:BatchCompletedが表示されます。これは、クエリプランが最初にコンパイルおよびキャッシュされ、次にクエリが開始および完了したことを意味します。

パフォーマンス統計イベントの下の次の列を見てください。

SPID - ID of the session on which the event occurred. You can use it to identify the       
       row on SQL:BatchCompleted event which will display the SQL Query text and other  
       usefull information (Read/Writes, StartTime/EndTime)
Duration - Total time, in microseconds, spent during compilation.
EventSubClass - 0 = New batch SQL text that is not currently present in the cache.
                1 = Queries within a stored procedure have been compiled.
                2 = Queries within an ad hoc SQL statement have been compiled.
                3 = A cached query has been destroyed and the historical performance         
                    data associated with the plan is about to be destroyed.
                4 = A cached stored procedure has been removed from the cache and the  
                    historical performance data associated with it is about to be 
                    destroyed.

                5 = A cached trigger has been removed from the cache and the historical  
                    performance data associated with it is about to be destroyed.

EventSubClass番号を考慮すると、クエリプランで何が起こったかを確認し、特定の対策を講じることができます。さらに、HostName、WindowsUser、またはプロファイラートレースからの他の情報に挿入されている場合は、ストアドプロシージャTSQLイベントクラスに他の列を追加できます。また、トレースをSQLテーブルに保存して、分析をより簡単に、よりカスタマイズできるようにすることもできます。以下は、パフォーマンス統計イベントクラスの詳細を説明するリンクです。


4

さて、まず、キャッシュに圧力がかかっていないか確認しましょう。

select bpool_visible from sys.dm_os_sys_info
go

その数に8を掛けて、K単位のメモリを取得します。0〜4Gの75%+ 4G〜64Gの10%+これ以上5%が、計画のキャッシュ圧力制限です。この制限の75%に達すると、SQL Serverは計画をキャッシュからパージし始めます。このパージは、新しいクエリプランがキャッシュに追加されたときに発生するため、この作業を行うためにスレッドが一時停止します。プランがパージされる原因となる2番目の原因は、プランの数がハッシュバケットの数の4倍を超える場合です(ハッシュテーブルはplan_handleをプランにマップします)。32ビットシステムでは10,000、64ビットシステムでは40,000です。

select type, sum(pages_allocated_count) as pages_used from sys.dm_os_memory_objects 
where type in ('MEMOBJ_CACHESTOREOBJCP', 'MEMOBJ_CACHESTORESQLCP', 'MEMOBJ_CACHESTOREXPROC')
group by type
go

何をパージするかは、使用量ではなく、プランのコストで決定されます。最も安価なプランが最初にパージされます(実行するのではなく、生成するコスト)。これは、列を追加して、のクエリに追加するoriginal_costcurrent_cost確認できますsys.dm_exec_cached_plans。アドホックプランは0から始まり、使用されるたびに1ずつ増加します。キャッシュプレッシャーが発生すると、SQL Serverは各コストから半分を差し引き、0に達したものを削除します。

アドホックSQLがたくさんある場合は、次のことを試してください。

exec sp_reconfigure 'optimize for ad hoc workloads', 1
go
reconfigure
go

このモードでは、SQL Serverは、約300バイトのサイズのスタブ(通常のクエリプランは最低でも24k)をキャッシュします。これには、ハッシュとSQLテキストへのポインターが含まれており、最初に特定のSQLステートメントが表示されます。それが再度実行される場合、その後、完全なプランをキャッシュします。これは必ずしもそれ自体でコンパイルを削減するわけではありませんが、プランキャッシュのメモリ負荷を軽減します。

注:これは2008年に機能し、2005年には機能しません。

別のトリックは

alter database ... set parameterization forced
go

これにより、SQL Serverは定数をパラメーターとして扱います。これは、通常、同様のSQLステートメントのプランをキャッシュする自動パラメーター化機能に役立ちます。アドホックSQLでは、サーバーのメモリが非常に不足している場合を除き、クエリプランをキャッシュする必要がありますが、これはパラメーター化できない限り、完全に一致したテキストに依存します。この場合、準備されたクエリのように動作します。


ありがとう!この「パラメータ化を強制する」オプションは知っていましたが、使用するのが怖いです。これを使用する際に目にすることができる唯一の欠点は、キャッシュがいっぱいになることです。私は正しいですか?
Manjot

3

このボックスでSQL Serverジョブを頻繁に実行していますか?2005年、エージェントジョブクエリはキャッシュされず、キャッシュの膨張とSQLコンパイルも発生する可能性があることに注意してください。

再利用数の少ないプランの数を見てください。それらはあなたの犯人です。

以下のプランのキャッシュに関するいくつかの関連メモ。

http://www.sqlskills.com/BLOGS/KIMBERLY/post/Plan-cache-adhoc-workloads-and-clearing-the-single-use-plan-cache-bloat.aspx

http://www.sqlskills.com/BLOGS/KIMBERLY/post/Clearing-the-cache-are-there-other-options.aspx


0

この影響は「クエリプランの汚染」と呼ばれ、多くの同様のSQLクエリが個別の、しかし同等の実行プランを生成します。

アドホッククエリでは、個々の解析によってオーバーヘッドが発生しますが、プランは保存されないため、通常はクエリプランの汚染は発生しません。これは、パラメーターが1つしかないクエリ(MS SQL Serverの場合)とは異なり、これらはパラメーター化されたクエリのように扱われます。

クエリプランの汚染には、いくつかの典型的なケースがあります。

  • ハードコードされたリテラルパラメーターが1つだけのSQLクエリ( 'select id、name from person where person where id = 1234'など)
  • 特に、MSSQLでの 'sp_prepexec'またはsp_executesql 'などのクエリプランをデータベースに強制的に保存するコマンド/ストアドプロシージャで使用する場合(Oracleでの' execute immediate 'は同様に機能すると思います)
  • 「select * from SoccerMatches sm where sm.Date>?」などの「ハードコードされた」リテラル値に大きな変動がある部分的にパラメーター化されたクエリ およびsm.Date <?およびHomeClubId = 5678およびGuestClubId = 1234 '。これらはパラメーターのためにクエリプランを保存しますが、変更されたすべてのHomeClubまたはGuestClubに対して新しいクエリプランを作成します(特に、ローカルで異なる日付のためにクエリが失敗した場合、日付/時刻値は多くのDB APIにパラメーターを導入する絶好の機会なので、フォーマット)。
  • クエリプランの汚染のもう1つの原因は、文字列/(n)varchar値と組み合わせた、ドライバーが不十分なADO.NETなどのフレームワークです。一部の実装/ドライバーは、パラメーターサイズを実際の文字列長に設定し、クエリ内の異なる文字列パラメーター長ごとに個別のクエリプランを作成します。ベストプラクティスは、最大フィールドサイズ(例:varchar(4000))、または正しい長さのドライバーを使用することです
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.