Berurusan dengan menunggu CXPACKET - menetapkan ambang biaya untuk paralelisme

12

Sebagai tindak lanjut dari pertanyaan saya sebelumnya tentang pemecahan masalah perf situs Sharepoint , saya bertanya-tanya apakah saya bisa melakukan sesuatu tentang menunggu CXPACKET.

Saya tahu solusi spontan adalah mematikan semua paralelisme dengan mengatur MAXDOP ke 1 - terdengar seperti ide yang buruk. Tetapi ide lain adalah untuk meningkatkan ambang biaya sebelum paralelisme dimulai. Default 5 untuk biaya rencana eksekusi cukup rendah.

Jadi saya bertanya-tanya apakah ada permintaan di luar sana yang sudah ditulis yang akan menemukan saya pertanyaan dengan biaya rencana eksekusi tertinggi (saya tahu Anda dapat menemukan pertanyaan-pertanyaan dengan durasi eksekusi tertinggi dan seterusnya - tetapi apakah biaya pelaksanaannya dapat diambil di suatu tempat, juga?) dan itu juga akan memberi tahu saya jika permintaan seperti itu telah dieksekusi secara paralel.

Apakah ada yang punya skrip seperti itu, atau dapat mengarahkan saya ke arah DMV, DMF, atau pandangan katalog sistem lain yang relevan untuk mengetahui hal ini?

marc_s
sumber

Jawaban:

11

CXPACKETtidak pernah menjadi penyebab; semua disalahkan, tetapi selalu merupakan gejala dari sesuatu yang lain. Anda perlu menangkap pertanyaan ini dalam tindakan dan mencari tahu apa "sesuatu yang lain" itu. Mungkin berbeda dari kueri ke kueri, dan mematikan paralelisme sama sekali - seperti yang Anda sarankan - berlebihan dalam banyak kasus. Tetapi seringkali ini adalah jumlah pekerjaan yang paling sedikit, itulah sebabnya mengapa ini merupakan "perbaikan" yang lazim.

Jika Anda bisa mendapatkan paket aktual untuk kueri yang tampaknya bertanggung jawab atas menunggu CXPACKET tinggi, muat ke dalam SQL Sentry Plan Explorer . Biasanya ada alasan di balik ini; kami menunjukkan operasi paralel mana yang mengarah pada kemiringan utas, dan Anda dapat dengan mudah menghubungkannya dengan taksiran yang mati (kami menyoroti operasi dengan taksiran yang dimatikan oleh setidaknya ambang tertentu). Biasanya masalah yang mendasarinya adalah statistik yang benar-benar buruk / kedaluwarsa (atau tidak tersedia).

Sayangnya apa yang akan Anda temukan di sys.dm_exec_cached_plans adalah paket yang diperkirakan . Mereka tidak akan memberi tahu Anda apakah rencana berjalan paralel ketika sebenarnya digunakan, karena rencana sebenarnya bukan apa yang di-cache. Dalam beberapa kasus, Anda berharap melihat paket serial dan paralel untuk permintaan yang sama; ini bukan bagaimana SQL Server menangani situasi untuk paket paralel yang mungkin paralel saat runtime. ( Banyak informasi tentang itu di sini .)

Aaron Bertrand
sumber
4

Jika Anda ingin melihat rencana eksekusi sebenarnya dari kueri yang sedang berjalan.

SELECT plan_handle FROM sys.dm_exec_requests WHERE session_id = [YourSPID]

Pertama, masukkan hasilnya ke dalam kueri ini.

SELECT query_plan FROM sys.dm_exec_query_plan (Enter the result here.)

Itu akan menunjukkan kepada Anda rencana eksekusi aktual yang digunakan sql untuk permintaan itu. Anda bisa menggunakan rencana eksekusi itu untuk melihat utas mana yang Anda tunggu.

Saya juga menemukan bahwa mematikan hyper threading secara drastis mengurangi waktu tunggu CXpacket saya.

Semoga itu bisa membantu.

Zane
sumber
3

Jawaban di atas oleh Aaron benar.

Saya hanya ingin menambahkan itu, jika Anda belum menggunakan Laporan Dashboard Kinerja SQL dan Pengumpul Data bawaan , Anda harus mulai.

Anda juga dapat mengambil kueri berikut, dan memodifikasinya sesuai keinginan Anda:

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
tacotuesday
sumber
0

Dalam pengalaman saya sebelumnya, Ambang Biaya Untuk Paralelisme tidak membantu mengurangi CXPACKET.

CXPACKETMenunggu tinggi dapat terjadi karena statistik yang salah yang menghasilkan Skalled Parallellism.

  1. Lebih lanjut tentang CXPACKET Menunggu: Paralelisme miring
  2. Microsoft Connect Item
  3. Pertanyaan Saya (Tidak) Menunggu Karena Paralelisme? - Tim Ford

Berikut ini adalah SQL yang saya gunakan untuk menemukan sesi yang memiliki CXPacket dan " menunggu lain " di dalamnya (silakan lihat dagram di bawah).

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]

masukkan deskripsi gambar di sini

Pemindaian Besar juga bisa menjadi bagian dari akar permasalahan. Ketika saya memeriksa rencana eksekusi dari kueri di atas, saya menemukan satu pemindaian di database saya. Ada juga saran indeks yang hilang dalam rencana eksekusi.

masukkan deskripsi gambar di sini


LCJ
sumber