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

위의 Aaron의 대답은 맞습니다.

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대기가 기울어 져 Parallellism의 결과로 잘못된 통계로 인해 발생할 수 있습니다.

  1. CXPACKET Waits : Skewed Parallelism에 대한 추가 정보
  2. Microsoft 연결 항목
  3. 병렬 처리로 인해 내 쿼리가 대기하지 않습니까? -팀 포드

다음은 CXPacket 과 " other waits " 가 모두있는 세션을 찾는 데 사용한 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.