Tìm hiểu về Phân tích hiệu năng SQL Server với Wait Statistics - Phần 2

Ở bài viết này Stanford sẽ giới thiệu đến bạn một số kỹ thuật để phân tích hiệu năng trong SQL Server với wait statistics. Bạn có thể sử dụng để phân tích hiệu năng quản trị SQL Server của bạn.

Có thể nói hiệu năng SQL Server được phản ánh bởi trạng thái của thread khi chúng đang thực hiện request. Nếu bạn chưa biết có những trạng thái nào trong quá trình xử lý công việc của SQL Server có thể xem bài viết tại đây. Chúng sẽ là một trong ba trạng thái runnable, running và suspended. Runnable là trạng thái xếp hàng chờ đến lượt dùng CPU, running là đang được xử lý trên CPU (processor) và suspended tức là đang chờ tài nguyên nào đó. Theo lý mà nói những yêu cầu (request) đang chờ tài nguyên là đối tượng ảnh hưởng lớn đến hiệu năng SQL Server vì chúng phí thời gian vào việc chờ đợi.

Phân tích hiệu năng SQL Server với wait statistics là việc xác định những tài nguyên gây chờ (wait type) cùng với thời gian chờ (wait time) đủ lớn. Từ đó truy tìm lý do và hướng xử lý. Có nhiều cách xác định wait type của một request, trong bài viết này chúng ta chỉ tập trung vào hai DMV chính. Một cái là nơi SQL Server lưu thông những threads đang nằm trong hàng đợi waiter list (có trạng thái suspended) và cái khác là tổng thời gian chờ tài nguyên trên SQL Server instance.

Phân tích hiệu năng SQL Server với DMV sys.dm_os_waiting_tasks

Đây chính là nơi lưu giữ những threads đang nằm trong runnable queue và waiter list, hay nói cách khác, DMV này cung cấp thông tin cho bạn biết SQL Server đang chờ cái gì? Chờ tài nguyên hay là chờ CPU? Những thông tin này sẽ cho bạn có cái nhìn tổng quan SQL Server đang bị gì.

SELECT *
FROM sys.dm_os_waiting_tasks
WHERE session_id > 50

Hình 1: sys.dm_os_waiting_tasks

Câu truy vấn trên loại những session_id nhỏ hơn 50 (là những system processes). Kết quả trả về của sys.dm_os_waiting_tasks trên máy của mình như trong hình 1. Cột wait_type thể hiện loại tài nguyên mà các threads đang chờ, session_id 123 đang chờ lock LCK_M_U (và cột resource_description cung cấp thông tin cụ thể lock trên object nào). Session 79 đang dùng cơ chế OLE DB để thực thiện request, session 156 đang chờ client nhận data. Chúng ta sẽ tìm hiểu một số loại wait types phổ biến ở phần sau, trước hết hãy tìm hiểu ý nghĩa các cột từ DMV này.

  • waiting_task_address địa chỉ trên bộ nhớ của tasks đang đợi tài nguyên.
  • session_id chính là id của session liên quan tới task, thread này.
  • exec_context_id thường là 0, đối với những câu truy vấn song song (sử dụng cùng lúc nhiều threads cho 1 request) sẽ có giá trị khác 0.
  • wait_duration_ms thời gian task đã chờ wait type hiện tại, tính bằng đơn vị milliseconds.
  • wait type loại tài nguyên thread đang chờ.
  • resource_address địa chỉ trên memory của tài nguyên chờ, không phải wait type nào cũng có thông tin này.
  • blocking_task_address, blocking_session_id, blocking_exec_context_id nếu thread đang đợi tài nguyên này bị block bởi một thread khác, ba thông tin này sẽ có giá trị tương ứng. Nếu không phải là tình huống blocking thì ba giá trị này sẽ NULL.
  • resource_description một số loại wait type sẽ cung cấp thêm thông tin về tài nguyên đang đợi, vì những thông tin này là quan trọng để xác định cụ thể tài nguyên nào. Ví dụ nếu thread đang chờ một lock, cột này sẽ cho ta biết lock trên row hay page, table và ID để xác định tài nguyên đó.

Như đã đề cập ở trên, khi SQL Server đang gặp vấn đề hiệu năng, bất kể là có một câu truy vấn nào đó chạy chậm hay cả hệ thống bỗng dưng chậm chạp, bạn đều có thể tìm thấy thông tin gì đó từ DMV này. Nếu lý do chậm là do các requests phức tạp đòi hỏi nhiều xử lý sẽ thể hiện ở thông số %Processor Time. Còn nếu requests chậm phản hồi là do đang kẹt trong việc đợi tài nguyên nào đó thì sẽ nằm trong waiter list và bạn sẽ thấy rõ nó đang chờ resource gì và đã chờ bao lâu rồi từ DMV này. Quả là tuyệt vời, mọi thứ đều trưng bày ra hết chỉ đợi bạn khám phá.

Chúng ta có thể sử dụng kết hợp với những DMVs khác để lấy thêm thông tin như nội dung statement đang chờ, thông số reads (I/O) và cpu time, client…của thread đang chờ tài nguyên. Đây đều là những thông tin cần thiết khi phân tích hiệu năng SQL Server. Dưới đây là câu truy vấn mình thường dùng cho việc này.

SELECT [spid] = er.session_Id, ecid, [blockedBy] = er.blocking_session_id
    , "database[Login]" = REPLACE(DB_NAME(sp.dbid) + ' [' + RTRIM(LTRIM(loginame)) + ']','[]','[--]')
    , "CMD[status]" = RTRIM(sp.cmd) + ' [' +er.status + ']', [wait] = er.wait_type,wt.wait_type,sp.waitresource
    , [current stmt] = SUBSTRING (qt.text, er.statement_start_offset/2,
                                                (CASE WHEN er.statement_end_offset = -1 THEN DATALENGTH(qt.text) 
                                                    ELSE er.statement_end_offset END - er.statement_start_offset)/2)
    ,sp.lastwaittype,wt.resource_description , wait_duration_ms
    ,[current batch] = qt.text, logical_reads, cpu, program = program_name, hostname
FROM sys.dm_exec_requests er
    INNER JOIN sys.sysprocesses sp ON er.session_id = sp.spid
    INNER JOIN sys.dm_os_waiting_tasks wt ON sp.spid = wt.session_id AND sp.ecid = wt.exec_context_id
    CROSS APPLY sys.dm_exec_sql_text(er.sql_handle)as qt
WHERE er.session_Id > 0              -- Ignore system spids 50.
AND er.session_Id NOT IN (@@SPID)     -- Ignore this current statement.
ORDER BY [spid]
GO

Phân tích hiệu năng với DMV sys.dm_os_wait_stats

DMV này lưu trữ danh sách các wait type mà phiên bản SQL Server đang có. Cùng với nó là giá trị cộng dồn của các thông tin về wait statistics như thời gian chờ tài nguyên bao nhiêu, thời gian chờ CPU bao lâu cho từng wait type, kể từ khi SQL Server restart hoặc lần cuối chạy command DBCC SQLPERF('sys.dm_os_wait_stats', CLEAR). Câu lệnh này sẽ xóa hết thông tin wait statistics hiện có và tính lại từ đầu. Thông tin cộng dồn gồm có số lần xảy ra sự kiện chờ tài nguyên, tổng thời gian chờ theo từng wait type như bạn thấy ở câu truy vấn dưới.

SELECT *
FROM sys.dm_os_wait_stats
ORDER BY waiting_tasks_count DESC;

Hình 2: sys.dm_os_wait_stats

  • wait_type loại wait, thường biểu thị cho tài nguyên mà các threads đã chờ.
  • wait_time_ms tổng thời gian cộng dồn các threads đã chờ trên loại wait type này. Giá trị này đã tính luôn signal_wait_time_ms. Có thể hình dung các lần chờ trong DMV sys.dm_os_waiting_tasks được cộng dồn vào cột này, theo từng wait type.
  • singal_wait_time_ms tổng thời gian cộng dồn của các threads chờ trên runnable queue.
  • waiting_tasks_count tổng cộng dồn số lần xảy ra sự kiện chờ trên wait type
  • max_wait_time_ms lần chờ lâu nhất của các threads.

Các bạn có thể tính ra resource wait bằng cách lấy total wait trừ cho signal wait. Nhắc lại signal wait là thời gian chờ CPU, nếu lượng signal wait này mà đủ lớn chứng tỏ SQL Server instance của bạn đang gặp vấn đề CPU pressure.

SELECT wait_type, waiting_tasks_count,
(wait_time_ms - signal_wait_time_ms) AS 'Resource_Wait_Time_ms',
signal_wait_time_ms ,wait_time_ms AS 'Total_Wait_Time_ms',
COALESCE(wait_time_ms / NULLIF(waiting_tasks_count,0), 0) AS 'Average_Wait_Time_ms'
FROM sys.dm_os_wait_stats
ORDER BY waiting_tasks_count DESC;
Với dữ liệu lịch sử như DMV này chúng ta sẽ sử dụng như thế nào để cải thiện hiệu năng SQL Server? Nó không trả lời cho câu hỏi tại một thời điểm cụ thể tuần trước xảy đã ra những wait type nào và bao lâu? Dữ liệu này giúp chúng ta xác định được nhóm wait types và tài nguyên nào làm SQL Server chờ đợi nhiều nhất. Tôi thường sử dụng câu truy vấn của Paul Randal ở bài viết này để kiểm tra top những wait type nhiều nhất trong instance như sau:

-- Last updated October 1, 2021
WITH [Waits] AS
    (SELECT
        [wait_type],
        [wait_time_ms] / 1000.0 AS [WaitS],
        ([wait_time_ms] - [signal_wait_time_ms]) / 1000.0 AS [ResourceS],
        [signal_wait_time_ms] / 1000.0 AS [SignalS],
        [waiting_tasks_count] AS [WaitCount],
        100.0 * [wait_time_ms] / SUM ([wait_time_ms]) OVER() AS [Percentage],
        ROW_NUMBER() OVER(ORDER BY [wait_time_ms] DESC) AS [RowNum]
    FROM sys.dm_os_wait_stats
    WHERE [wait_type] NOT IN (
        -- These wait types are almost 100% never a problem and so they are
        -- filtered out to avoid them skewing the results. Click on the URL
        -- for more information.
        N'BROKER_EVENTHANDLER', -- https://www.sqlskills.com/help/waits/BROKER_EVENTHANDLER
        N'BROKER_RECEIVE_WAITFOR', -- https://www.sqlskills.com/help/waits/BROKER_RECEIVE_WAITFOR
        N'BROKER_TASK_STOP', -- https://www.sqlskills.com/help/waits/BROKER_TASK_STOP
        N'BROKER_TO_FLUSH', -- https://www.sqlskills.com/help/waits/BROKER_TO_FLUSH
        N'BROKER_TRANSMITTER', -- https://www.sqlskills.com/help/waits/BROKER_TRANSMITTER
        N'CHECKPOINT_QUEUE', -- https://www.sqlskills.com/help/waits/CHECKPOINT_QUEUE
        N'CHKPT', -- https://www.sqlskills.com/help/waits/CHKPT
        N'CLR_AUTO_EVENT', -- https://www.sqlskills.com/help/waits/CLR_AUTO_EVENT
        N'CLR_MANUAL_EVENT', -- https://www.sqlskills.com/help/waits/CLR_MANUAL_EVENT
        N'CLR_SEMAPHORE', -- https://www.sqlskills.com/help/waits/CLR_SEMAPHORE
  
        -- Maybe comment this out if you have parallelism issues
        N'CXCONSUMER', -- https://www.sqlskills.com/help/waits/CXCONSUMER
  
        -- Maybe comment these four out if you have mirroring issues
        N'DBMIRROR_DBM_EVENT', -- https://www.sqlskills.com/help/waits/DBMIRROR_DBM_EVENT
        N'DBMIRROR_EVENTS_QUEUE', -- https://www.sqlskills.com/help/waits/DBMIRROR_EVENTS_QUEUE
        N'DBMIRROR_WORKER_QUEUE', -- https://www.sqlskills.com/help/waits/DBMIRROR_WORKER_QUEUE
        N'DBMIRRORING_CMD', -- https://www.sqlskills.com/help/waits/DBMIRRORING_CMD
        N'DIRTY_PAGE_POLL', -- https://www.sqlskills.com/help/waits/DIRTY_PAGE_POLL
        N'DISPATCHER_QUEUE_SEMAPHORE', -- https://www.sqlskills.com/help/waits/DISPATCHER_QUEUE_SEMAPHORE
        N'EXECSYNC', -- https://www.sqlskills.com/help/waits/EXECSYNC
        N'FSAGENT', -- https://www.sqlskills.com/help/waits/FSAGENT
        N'FT_IFTS_SCHEDULER_IDLE_WAIT', -- https://www.sqlskills.com/help/waits/FT_IFTS_SCHEDULER_IDLE_WAIT
        N'FT_IFTSHC_MUTEX', -- https://www.sqlskills.com/help/waits/FT_IFTSHC_MUTEX
   
       -- Maybe comment these six out if you have AG issues
        N'HADR_CLUSAPI_CALL', -- https://www.sqlskills.com/help/waits/HADR_CLUSAPI_CALL
        N'HADR_FILESTREAM_IOMGR_IOCOMPLETION', -- https://www.sqlskills.com/help/waits/HADR_FILESTREAM_IOMGR_IOCOMPLETION
        N'HADR_LOGCAPTURE_WAIT', -- https://www.sqlskills.com/help/waits/HADR_LOGCAPTURE_WAIT
        N'HADR_NOTIFICATION_DEQUEUE', -- https://www.sqlskills.com/help/waits/HADR_NOTIFICATION_DEQUEUE
        N'HADR_TIMER_TASK', -- https://www.sqlskills.com/help/waits/HADR_TIMER_TASK
        N'HADR_WORK_QUEUE', -- https://www.sqlskills.com/help/waits/HADR_WORK_QUEUE
  
        N'KSOURCE_WAKEUP', -- https://www.sqlskills.com/help/waits/KSOURCE_WAKEUP
        N'LAZYWRITER_SLEEP', -- https://www.sqlskills.com/help/waits/LAZYWRITER_SLEEP
        N'LOGMGR_QUEUE', -- https://www.sqlskills.com/help/waits/LOGMGR_QUEUE
        N'MEMORY_ALLOCATION_EXT', -- https://www.sqlskills.com/help/waits/MEMORY_ALLOCATION_EXT
        N'ONDEMAND_TASK_QUEUE', -- https://www.sqlskills.com/help/waits/ONDEMAND_TASK_QUEUE
        N'PARALLEL_REDO_DRAIN_WORKER', -- https://www.sqlskills.com/help/waits/PARALLEL_REDO_DRAIN_WORKER
        N'PARALLEL_REDO_LOG_CACHE', -- https://www.sqlskills.com/help/waits/PARALLEL_REDO_LOG_CACHE
        N'PARALLEL_REDO_TRAN_LIST', -- https://www.sqlskills.com/help/waits/PARALLEL_REDO_TRAN_LIST
        N'PARALLEL_REDO_WORKER_SYNC', -- https://www.sqlskills.com/help/waits/PARALLEL_REDO_WORKER_SYNC
        N'PARALLEL_REDO_WORKER_WAIT_WORK', -- https://www.sqlskills.com/help/waits/PARALLEL_REDO_WORKER_WAIT_WORK
        N'PREEMPTIVE_OS_FLUSHFILEBUFFERS', -- https://www.sqlskills.com/help/waits/PREEMPTIVE_OS_FLUSHFILEBUFFERS
        N'PREEMPTIVE_XE_GETTARGETSTATE', -- https://www.sqlskills.com/help/waits/PREEMPTIVE_XE_GETTARGETSTATE
        N'PVS_PREALLOCATE', -- https://www.sqlskills.com/help/waits/PVS_PREALLOCATE
        N'PWAIT_ALL_COMPONENTS_INITIALIZED', -- https://www.sqlskills.com/help/waits/PWAIT_ALL_COMPONENTS_INITIALIZED
        N'PWAIT_DIRECTLOGCONSUMER_GETNEXT', -- https://www.sqlskills.com/help/waits/PWAIT_DIRECTLOGCONSUMER_GETNEXT
        N'PWAIT_EXTENSIBILITY_CLEANUP_TASK', -- https://www.sqlskills.com/help/waits/PWAIT_EXTENSIBILITY_CLEANUP_TASK
        N'QDS_PERSIST_TASK_MAIN_LOOP_SLEEP', -- https://www.sqlskills.com/help/waits/QDS_PERSIST_TASK_MAIN_LOOP_SLEEP
        N'QDS_ASYNC_QUEUE', -- https://www.sqlskills.com/help/waits/QDS_ASYNC_QUEUE
        N'QDS_CLEANUP_STALE_QUERIES_TASK_MAIN_LOOP_SLEEP',
        N'QDS_SHUTDOWN_QUEUE', -- https://www.sqlskills.com/help/waits/QDS_SHUTDOWN_QUEUE
        N'REDO_THREAD_PENDING_WORK', -- https://www.sqlskills.com/help/waits/REDO_THREAD_PENDING_WORK
        N'REQUEST_FOR_DEADLOCK_SEARCH', -- https://www.sqlskills.com/help/waits/REQUEST_FOR_DEADLOCK_SEARCH
        N'RESOURCE_QUEUE', -- https://www.sqlskills.com/help/waits/RESOURCE_QUEUE
        N'SERVER_IDLE_CHECK', -- https://www.sqlskills.com/help/waits/SERVER_IDLE_CHECK
        N'SLEEP_BPOOL_FLUSH', -- https://www.sqlskills.com/help/waits/SLEEP_BPOOL_FLUSH
        N'SLEEP_DBSTARTUP', -- https://www.sqlskills.com/help/waits/SLEEP_DBSTARTUP
        N'SLEEP_DCOMSTARTUP', -- https://www.sqlskills.com/help/waits/SLEEP_DCOMSTARTUP
        N'SLEEP_MASTERDBREADY', -- https://www.sqlskills.com/help/waits/SLEEP_MASTERDBREADY
        N'SLEEP_MASTERMDREADY', -- https://www.sqlskills.com/help/waits/SLEEP_MASTERMDREADY
        N'SLEEP_MASTERUPGRADED', -- https://www.sqlskills.com/help/waits/SLEEP_MASTERUPGRADED
        N'SLEEP_MSDBSTARTUP', -- https://www.sqlskills.com/help/waits/SLEEP_MSDBSTARTUP
        N'SLEEP_SYSTEMTASK', -- https://www.sqlskills.com/help/waits/SLEEP_SYSTEMTASK
        N'SLEEP_TASK', -- https://www.sqlskills.com/help/waits/SLEEP_TASK
        N'SLEEP_TEMPDBSTARTUP', -- https://www.sqlskills.com/help/waits/SLEEP_TEMPDBSTARTUP
        N'SNI_HTTP_ACCEPT', -- https://www.sqlskills.com/help/waits/SNI_HTTP_ACCEPT
        N'SOS_WORK_DISPATCHER', -- https://www.sqlskills.com/help/waits/SOS_WORK_DISPATCHER
        N'SP_SERVER_DIAGNOSTICS_SLEEP', -- https://www.sqlskills.com/help/waits/SP_SERVER_DIAGNOSTICS_SLEEP
        N'SQLTRACE_BUFFER_FLUSH', -- https://www.sqlskills.com/help/waits/SQLTRACE_BUFFER_FLUSH
        N'SQLTRACE_INCREMENTAL_FLUSH_SLEEP', -- https://www.sqlskills.com/help/waits/SQLTRACE_INCREMENTAL_FLUSH_SLEEP
        N'SQLTRACE_WAIT_ENTRIES', -- https://www.sqlskills.com/help/waits/SQLTRACE_WAIT_ENTRIES
        N'VDI_CLIENT_OTHER', -- https://www.sqlskills.com/help/waits/VDI_CLIENT_OTHER
        N'WAIT_FOR_RESULTS', -- https://www.sqlskills.com/help/waits/WAIT_FOR_RESULTS
        N'WAITFOR', -- https://www.sqlskills.com/help/waits/WAITFOR
        N'WAITFOR_TASKSHUTDOWN', -- https://www.sqlskills.com/help/waits/WAITFOR_TASKSHUTDOWN
        N'WAIT_XTP_RECOVERY', -- https://www.sqlskills.com/help/waits/WAIT_XTP_RECOVERY
        N'WAIT_XTP_HOST_WAIT', -- https://www.sqlskills.com/help/waits/WAIT_XTP_HOST_WAIT
        N'WAIT_XTP_OFFLINE_CKPT_NEW_LOG', -- https://www.sqlskills.com/help/waits/WAIT_XTP_OFFLINE_CKPT_NEW_LOG
        N'WAIT_XTP_CKPT_CLOSE', -- https://www.sqlskills.com/help/waits/WAIT_XTP_CKPT_CLOSE
        N'XE_DISPATCHER_JOIN', -- https://www.sqlskills.com/help/waits/XE_DISPATCHER_JOIN
        N'XE_DISPATCHER_WAIT', -- https://www.sqlskills.com/help/waits/XE_DISPATCHER_WAIT
        N'XE_TIMER_EVENT' -- https://www.sqlskills.com/help/waits/XE_TIMER_EVENT
        )
    AND [waiting_tasks_count] > 0
    )
SELECT
    MAX ([W1].[wait_type]) AS [WaitType],
    CAST (MAX ([W1].[WaitS]) AS DECIMAL (16,2)) AS [Wait_S],
    CAST (MAX ([W1].[ResourceS]) AS DECIMAL (16,2)) AS [Resource_S],
    CAST (MAX ([W1].[SignalS]) AS DECIMAL (16,2)) AS [Signal_S],
    MAX ([W1].[WaitCount]) AS [WaitCount],
    CAST (MAX ([W1].[Percentage]) AS DECIMAL (5,2)) AS [Percentage],
    CAST ((MAX ([W1].[WaitS]) / MAX ([W1].[WaitCount])) AS DECIMAL (16,4)) AS [AvgWait_S],
    CAST ((MAX ([W1].[ResourceS]) / MAX ([W1].[WaitCount])) AS DECIMAL (16,4)) AS [AvgRes_S],
    CAST ((MAX ([W1].[SignalS]) / MAX ([W1].[WaitCount])) AS DECIMAL (16,4)) AS [AvgSig_S],
    CAST ('https://www.sqlskills.com/help/waits/' + MAX ([W1].[wait_type]) as XML) AS [Help/Info URL]
FROM [Waits] AS [W1]
INNER JOIN [Waits] AS [W2] ON [W2].[RowNum] <= [W1].[RowNum]
GROUP BY [W1].[RowNum]
HAVING SUM ([W2].[Percentage]) - MAX( [W1].[Percentage] ) < 95; -- percentage threshold
GO

Câu truy vấn này có loại ra những wait type không quan trọng và đặc biệt nó được chủ nhân cập nhật thường xuyên. Hình dưới là kết quả trên máy mình.


Hình 3. Top wait types trong SQL Server instance

Câu truy vấn chỉ lấy ra những wait type có thời gian chờ đủ lớn đóng góp vào danh sách các tài nguyên là điểm nghẽn có thể có trong SQL instance. Chỉ cần bạn tập trung giải quyết những wait type xuất hiện trên danh sách này thì hiệu năng đã cải thiện rất nhiều rồi.

Ví dụ LCK_M_U là wait type là loại khóa để cập nhật tài nguyên. Phân tích kết quả này giúp chúng ta xác định được phạm vi nghẽn cụ thể và dành nhiều thời gian cho nó hơn. Ví dụ nếu phần lớn wait types xuất hiện trong top này thuộc về disk I/O, ta sẽ dùng các tiêu chí liên quan đến disk I/O để đi kiểm tra và tìm nguyên nhân. Nếu top wait types thuộc về locks chúng ta lại giải quyết bài toán kiểu khác. Theo tôi đây là hướng tiếp cận tốt trong quá trình cải thiện hiệu năng SQL Server.

Như vậy qua bài viết này đã giúp các bạn học quản trị SQL Server nắm được một số kỹ thuật phân tích hiệu năng với DMV trong SQL Server. Để hiểu rõ hơn các bạn có thể thực hiện chạy các câu lệnh như trong bài viết trên SQL Server của mình quản lý. Chúc các bạn thành công !

Bên cạnh đó nếu bạn đang muốn được đào tạo bài bản từ cơ bản đến nâng cao có thể tham gia ngay khóa học sql cùng chuyên gia giàu kinh nghiệm Stanford tại đây: http://bit.ly/2SLPYFF và nhận ưu đãi hấp dẫn của Stanford trong thời gian này. Bạn có thể gọi theo hotline: 0963 723 236 - 0866 586 366 để được gọi lại tư vấn trực tiếp nhé.

=============================
☎ STANFORD – ĐÀO TẠO VÀ PHÁT TRIỂN CÔNG NGHỆ
Hotline: 0963 723 236 - 0866 586 366
Website: https://stanford.com.vn
Facebook: http://bit.ly/2FN0TYb
Youtube: http://bit.ly/2TkKT7I

Tags: wait statistics, phân tích hiệu năng