私のフォローアップ Sharepointサイトのトラブルシューティングに関する以前の質問 のフォローアップとして、CXPACKETの待機について何かできるかどうか疑問に思っていました。
MAXDOPを1に設定してすべての並列処理をオフにすることは簡単な解決策であることは知っています。悪い考えのように聞こえます。しかし、別のアイデアは、並列処理が始まる前にコストのしきい値を増やすことです。実行プランのコストのデフォルトの5はかなり低いです。
したがって、実行プランのコストが最も高いクエリを見つけるクエリがすでにそこにあるかどうか疑問に思っていました(実行時間の最も長いクエリなどを見つけることができますが、実行プランのコストはどこかで取得できます)。また、そのようなクエリが並列で実行されているかどうかもわかります。
誰かがそのようなスクリプトを手元に持っていますか、またはこれを見つけるために、関連するDMV、DMF、または他のシステムカタログビューの方向に私を向けることができますか?
CXPACKET
が原因になることはありません。それはすべての責任ですが、それは常に何か他の症状です。行為でこれらのクエリをキャッチし、「何か他のもの」が何かを理解する必要があります。これはクエリごとに異なる可能性があり、並列処理を完全にオフにすることは-あなたが示唆したように-ほとんどの場合、不必要なやり過ぎです。しかし、多くの場合、これは最も少ない作業量です。そのため、これは非常に一般的な「修正」です。
高いCXPACKET待機の原因であると思われるクエリのactualプランを取得できる場合は、それを SQL Sentry Plan Explorer にロードします。通常、これには理由があります。スレッドスキューの原因となった並列処理を示します。これをオフになっている推定値と簡単に関連付けることができます(少なくとも特定のしきい値でオフになっている推定値を持つ演算を強調表示します)。通常、根本的な問題は、本当に悪い/古い(または利用できない)統計です。
残念ながら、sys.dm_exec_cached_plansにあるのは推定プランです。 actualプランはキャッシュされるものではないため、実際に使用されたときにプランが並列化されたかどうかはわかりません。場合によっては、同じクエリのシリアルプランとパラレルプランの両方が表示されることが予想されます。これは、SQL Serverが、実行時にmightが並列になるような並列プランの状況を処理する方法ではありません。 ( ここにたくさんの情報があります )
実行中のクエリの実際の実行プランを見たい場合。
SELECT plan_handle FROM sys.dm_exec_requests WHERE session_id = [YourSPID]
まず、このクエリに結果を入力します。
SELECT query_plan FROM sys.dm_exec_query_plan (Enter the result here.)
Sqlがそのクエリに使用した実際の実行プランが表示されます。その実行プランを使用して、待機しているスレッドを確認できます。
ハイパースレッディングをオフにすると、CXpacketの待機時間が大幅に短縮されることもわかりました。
お役に立てば幸いです。
上記のアーロンの答えは正しいです。
追加したいのは、 SQL Performance Dashboard Reports と組み込みの Data Collector をまだ使用していない場合は、開始する必要があります。
次のクエリを使用して、必要に応じて変更することもできます。
DECLARE @MinExecutions int;
SET @MinExecutions = 5
SELECT EQS.total_worker_time AS TotalWorkerTime
,EQS.total_logical_reads + EQS.total_logical_writes AS TotalLogicalIO
,EQS.execution_count As ExeCnt
,EQS.last_execution_time AS LastUsage
,EQS.total_worker_time / EQS.execution_count as AvgCPUTimeMiS
,(EQS.total_logical_reads + EQS.total_logical_writes) / EQS.execution_count
AS AvgLogicalIO
,DB.name AS DatabaseName
,SUBSTRING(EST.text
,1 + EQS.statement_start_offset / 2
,(CASE WHEN EQS.statement_end_offset = -1
THEN LEN(convert(nvarchar(max), EST.text)) * 2
ELSE EQS.statement_end_offset END
- EQS.statement_start_offset) / 2
) AS SqlStatement
-- Optional with Query plan; remove comment to show, but then the query takes !!much longer!!
--,EQP.[query_plan] AS [QueryPlan]
FROM sys.dm_exec_query_stats AS EQS
CROSS APPLY sys.dm_exec_sql_text(EQS.sql_handle) AS EST
CROSS APPLY sys.dm_exec_query_plan(EQS.plan_handle) AS EQP
LEFT JOIN sys.databases AS DB
ON EST.dbid = DB.database_id
WHERE EQS.execution_count > @MinExecutions
AND EQS.last_execution_time > DATEDIFF(MONTH, -1, GETDATE())
ORDER BY AvgLogicalIo DESC
,AvgCPUTimeMiS DESC
以前の経験では 並列処理のコストしきい値 はCXPACKETの削減に役立ちませんでした。
統計が正しくないためにCXPACKET
待機が高くなり、偏った並列処理が発生する可能性があります。
以下は、CXPacketと "other waits "(その下の図をご覧ください)。
[〜#〜] sql [〜#〜]
DECLARE @RawResult TABLE ([database_id] INT,[session_id] INT,exec_context_id INT, [blocking_session_id] INT,task_state VARCHAR(20),
[cpu_time] BIGINT,[wait_duration_ms] BIGINT, [wait_type] VARCHAR(100),[resource_description] nvarchar(3072),
[sql_handle] varbinary(64),[plan_handle] varbinary(64)
)
INSERT INTO @RawResult
SELECT
[R].[database_id],
[S].[session_id],
[W].exec_context_id,
[W].blocking_session_id,
[T].task_state,
[R].[cpu_time],
[W].[wait_duration_ms],
[W].[wait_type],
[W].[resource_description],
[R].[sql_handle],
[R].[plan_handle]
FROM sys.dm_os_waiting_tasks [W]
INNER JOIN sys.dm_os_tasks [T] ON
[W].[waiting_task_address] = [T].[task_address]
INNER JOIN sys.dm_exec_sessions [S] ON
[W].[session_id] = [S].[session_id]
INNER JOIN sys.dm_exec_requests [R] ON
[S].[session_id] = [R].[session_id]
WHERE [S].[is_user_process] = 1
--AND S.session_id <> @@SPID--???
--ORDER BY [W].[session_id],[W].[exec_context_id];
SELECT
DB_NAME(C.database_id) AS database_name,
C.[database_id],
C.[session_id],
C.exec_context_id,
C.blocking_session_id,
C.task_state,
C.[cpu_time],
C.[wait_duration_ms],
C.[wait_type],
C.[sql_handle],
C.[plan_handle],
[H].text,
[P].[query_plan],
C.[resource_description]
FROM @RawResult C
OUTER APPLY sys.dm_exec_sql_text (C.[sql_handle]) [H]
OUTER APPLY sys.dm_exec_query_plan (C.[plan_handle]) [P]
WHERE C.[session_id] IN
(
SELECT A.[session_id]
FROM @RawResult A
INNER JOIN @RawResult B
ON A.[session_id] = B.[session_id]
AND A.wait_type='CXPACKET'
AND B.wait_type <> 'CXPACKET'
)
ORDER BY C.[session_id],C.[exec_context_id]
大きなスキャンも根本的な原因の一部である可能性があります。上記のクエリから実行プランを確認したところ、データベースでそのようなスキャンが1つ見つかりました。また、実行計画に欠落したインデックスの提案がありました。