Đây là cách tôi sử dụng câu trả lời cho câu hỏi của tôi.
Tôi là một fan hâm mộ lớn của sp_whoisactive. Nếu bạn không có điều đó, hãy ngừng đọc; tải về tại đây .
Vì vậy, tôi đã thiết lập nó để thu thập ảnh chụp nhanh cứ sau 10 phút, như thế này:
DROP TABLE dbo.HESPOmonitoring_output
DECLARE @s VARCHAR(MAX)
EXEC sp_WhoIsActive
@output_column_list = '[login_name][dd%][session_id][program%][sql_com%][sql_text][block%][reads][writes][physical_reads][query_plan][used_memory][tempdb%][wait%][start_time][collection_time][host%][additional%]', @get_outer_command=1, @get_additional_info=1,
@return_schema = 1, @get_plans=1,
@schema = @s OUTPUT
SET @s = REPLACE(@s, '<table_name>', 'dbo.HESPOmonitoring_output')
EXEC(@s)
ALTER TABLE dbo.HESPOmonitoring_output ADD HESPOmonitoring_outputID BIGINT IDENTITY(1,1) NOT NULL
go
SET NOCOUNT ON
DECLARE @Started DATETIME=DATEADD(DAY, 3, GETDATE())
WHILE 1 > 0 BEGIN
EXEC sp_WhoIsActive
@output_column_list = '[login_name][dd%][session_id][program%][sql_com%][sql_text][block%][reads][writes][physical_reads][query_plan][used_memory][tempdb%][wait%][start_time][collection_time][host%][additional%]', @get_outer_command=1, @get_additional_info=1,
@get_plans=1,
@destination_table = 'dbo.HESPOmonitoring_output'
WAITFOR DELAY '00:10:00'
IF GETDATE() > @Started BREAK
END
Tôi đã để nó chạy một lúc (tối đa 3 ngày). Sau đó, tôi chuyển đổi dữ liệu được thu thập như thế này:
/* this query turns HESPOmonitoring_output in a table with one row per SQL statement */
Begin TRY
DROP TABLE #hespo
END TRY
BEGIN CATCH
END CATCH
;WITH XMLNAMESPACES
(DEFAULT 'http://schemas.microsoft.com/sqlserver/2004/07/showplan')
SELECT top 10000 H.Start_Time, H.session_id, MAX(H.program_name) AS program_name, MAX(CAST(H.sql_command AS VARCHAR(max))) AS sql_command
, MAX(CAST(H.sql_text AS VARCHAR(max))) AS sql_text
, MAX(H.reads) AS reads
, MAX(H.physical_reads) AS physical_reads
, MAX(H.writes) AS writes
, MAX(H.collection_time) AS collection_time
, MAX(DATEDIFF(second, start_time, collection_time)) AS RunTime
, MAX(HESPOmonitoring_outputID) AS MaxHESPOmonitoring_outputID
, MAX(H.blocking_session_id) AS MaxBlocking_session_id
, Min(H.blocking_session_id) AS MinBlocking_session_id
, count_big(*) as RowCnt
, MAX(TRY_CAST(n.value('(@StatementSubTreeCost)[1]', 'VARCHAR(128)') AS DECIMAL(18,3))) AS StatementSubTreeCost
INTO #hespo
FROM dbo.HESPOmonitoring_output H
CROSS APPLY query_plan.nodes('/ShowPlanXML/BatchSequence/Batch/Statements/StmtSimple') AS qn(n)
GROUP BY H.Start_Time, H.session_id
Và cuối cùng tôi nhận được một danh sách hiển thị cho tôi nơi Chi phí ước tính nhỏ so với thời gian chạy, mà không có công việc nào bị chặn cả
SELECT top 10000
H.StatementSubTreeCost/NULLIF(H.RunTime, 0) AS Ratio, H.StatementSubTreeCost, H.RunTime, *
FROM #hespo H
WHERE H.MinBlocking_session_id IS NULL
AND H.RunTime>0
AND H.StatementSubTreeCost IS NOT NULL
ORDER BY 1
Đó là một danh sách rất thú vị , nhưng nó đi kèm với một chút tiếng ồn. Để bắt đầu, tôi đã chọn bỏ qua các công việc nhỏ nhanh chóng chỉ chạy dưới 10 phút, nhưng giới hạn đó phụ thuộc vào tình huống của bạn.
Bây giờ việc tìm việc chạy với một kế hoạch tồi tệ sẽ dễ dàng hơn rất nhiều.
Cảm ơn bạn rất nhiều vì đã giúp đỡ của bạn.