CXPACKET待機の処理-並列処理のコストしきい値の設定


12

Sharepointサイトのトラブルシューティングに関する以前の質問のフォローアップとして、CXPACKETの待機について何かできるかどうか疑問に思いました。

ひざまずく解決策は、MAXDOPを1に設定することですべての並列処理をオフにすることであることを知っています。これは悪い考えのように聞こえます。しかし、別のアイデアは、並列処理が開始される前にコストのしきい値を増やすことです。実行計画のコストのデフォルトの5はかなり低いです。

だから私は、実行計画コストが最も高いクエリを見つけるクエリがすでに書かれているのだろうかと思っていました(実行期間などが最も長いクエリを見つけることができることを知っていますが、実行プランのコストはどこかで取得可能です、また、そのようなクエリが並行して実行されたかどうかも教えてくれます。

誰かがそのようなスクリプトを手元に持っていますか、またはこれを見つけるために関連するDMV、DMFまたは他のシステムカタログビューの方向に私を向けることができますか?

回答:


11

CXPACKET決して原因ではありません。それはすべて非難を取得しますが、それは常に何か他のものの症状です。行為でこれらのクエリをキャッチし、「何か他のもの」が何であるかを把握する必要があります。クエリごとに異なる場合があり、並列処理を完全にオフにすることは-あなたが提案したように-ほとんどの場合、不必要なやり過ぎです。しかし、これは作業量が最も少ないことが多いため、このような一般的な「修正」です。

高いCXPACKET待機の原因と思われるクエリの実際のプランを取得できる場合は、それをSQL Sentry Plan Explorerにロードします。通常、これには理由があります。どの並列操作がスレッドスキューを引き起こしたかを示し、それをオフになっている推定値と容易に相関させることができます(少なくとも特定のしきい値だけオフになっている推定値を持つ操作を強調表示します)。通常、根本的な問題は本当に悪い/古い(または利用できない)統計です。

残念ながら、sys.dm_exec_cached_plansにあるのは推定プランです。実際のプランはキャッシュされたものではないため、プランが実際に使用されたときに並行していたかどうかはわかりません。場合によっては、同じクエリに対してシリアルプランとパラレルプランの両方が表示されることが期待されます。これは、SQL Serverが実行時に並列する可能性のある並列プランの状況を処理する方法ではありません。(それについての多くの情報がここにあります。)


4

実行中のクエリの実際の実行計画を表示する場合。

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の待ち時間が大幅に短縮されることもわかりました。

お役に立てば幸いです。


3

アーロンによる上記の答えは正しいです。

追加したいのですが、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

0

私の以前の経験では、並列処理のコストしきい値はCXPACKETの削減に役立ちませんでした。

CXPACKET不正確な統計が原因でスキュー並列処理が行われるため、高待機が発生する可能性があります。

  1. CXPACKET待機の詳細:スキュー並列処理
  2. Microsoft Connectアイテム
  3. 並列処理のためにクエリが待機していますか?-ティム・フォード

以下は、CXPacketと「その他の待機」の両方を含むセッションを見つけるために使用したSQLです(下の図をご覧ください)。

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]

ここに画像の説明を入力してください

大規模なスキャンも根本原因の一部になります。上記のクエリから実行プランをチェックしたところ、データベースでそのようなスキャンが見つかりました。また、実行計画にインデックスの提案がありませんでした。

ここに画像の説明を入力してください


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.