2015-06-19 59 views
2

最近我一直在做一些SQL Server過程優化,並且正在尋找測試模式(時間和結果明智)。我已經用此溶液來了迄今:SQL Server過程優化測試模式改進

SET NOCOUNT ON; 
---------------------------------------------------------------------------------------------------------------- 
-- Procedures data and performance testing pattern 
---------------------------------------------------------------------------------------------------------------- 
-- Prepare test queries (most likely will be taken from Logs.ProcedureTraceData (DATAUK/DATAUS servers) 
-- Procedures should insert records into Temporary table, so we can compare their results using EXCEPT 
-- If result set columns are fixed (i.e. no Dynamic SQL is used), we can create Temporary tables inside script 
-- and insert records in them to do comparison and just TRUNCATE them at the end of the loop. 
-- example here: http://stackoverflow.com/a/654418/3680098 
-- If there're any data discrepancies or record counts are different, it will be displayed in TraceLog table 
---------------------------------------------------------------------------------------------------------------- 
-- Create your own TraceLog table to keep records 
---------------------------------------------------------------------------------------------------------------- 
/* 
CREATE TABLE Temporary._EB_TraceLog 
(
    ID INT NOT NULL IDENTITY(1, 1) CONSTRAINT PK_Temporary_EB_TraceLog_ID PRIMARY KEY 
    , CurrentExecutionTime INT 
    , TempExecutionTime INT 
    , CurrentExecutionResultsCount INT 
    , TempExecutionResultsCount INT 
    , IsDifferent BIT CONSTRAINT DF_Temporary_EB_TraceLog_IsDifferent DEFAULT 0 NOT NULL 
    , TimeDiff AS CurrentExecutionTime - TempExecutionTime 
    , PercentageDiff AS CAST(((CAST(CurrentExecutionTime AS DECIMAL)/ CAST(TempExecutionTime AS DECIMAL)) * 100 - 100) AS DECIMAL(10, 2)) 
    , TextData NVARCHAR(MAX) 
); 

SELECT * 
FROM Temporary._EB_TraceLog; 

TRUNCATE TABLE Temporary._EB_TraceLog; 
*/ 

INSERT INTO Temporary._EB_TraceLog (TextData) 
SELECT TextData 
FROM Temporary._EB_GetData_Timeouts 
EXCEPT 
SELECT TextData 
FROM Temporary._EB_TraceLog; 

DECLARE @Counter INT; 

SELECT @Counter = MIN(ID) 
FROM Temporary._EB_TraceLog 
WHERE CurrentExecutionTime IS NULL 
    OR TempExecutionTime IS NULL 
    OR CurrentExecutionResultsCount IS NULL 
    OR TempExecutionResultsCount IS NULL; 

WHILE @Counter <= (SELECT MAX(ID) FROM Temporary._EB_TraceLog) 
BEGIN 
    DECLARE @SQLStringCurr NVARCHAR(MAX); 
    DECLARE @SQLStringTemp NVARCHAR(MAX); 
    DECLARE @StartTime DATETIME2; 
    SELECT @SQLStringCurr = REPLACE(TextData, 'dbo.GetData', 'Temporary._EB_GetData_Orig') 
     , @SQLStringTemp = REPLACE(TextData, 'dbo.GetData', 'Temporary._EB_GetData_Mod') 
    FROM Temporary._EB_TraceLog 
    WHERE ID = @Counter; 

    ---------------------------------------------------------------------------------------------------------------- 
    -- Drop temporary tables in script, so these numbers don't figure in SP execution time 
    ---------------------------------------------------------------------------------------------------------------- 
    IF OBJECT_ID(N'Temporary._EB_Test_Orig') IS NOT NULL 
     DROP TABLE Temporary._EB_Test_Orig; 

    IF OBJECT_ID(N'Temporary._EB_Test_Mod') IS NOT NULL 
     DROP TABLE Temporary._EB_Test_Mod; 

    ---------------------------------------------------------------------------------------------------------------- 
    -- Actual testing 
    ---------------------------------------------------------------------------------------------------------------- 
    -- Take time snapshot and execute original procedure, which inserts records into Temporary table 
    -- When done - measurements will be updated on TraceLog table 
    ---------------------------------------------------------------------------------------------------------------- 
    SELECT @StartTime = CURRENT_TIMESTAMP; 
    EXECUTE sp_executesql @SQLStringCurr; 

    UPDATE T 
    SET T.CurrentExecutionTime = DATEDIFF(MILLISECOND, @StartTime, CURRENT_TIMESTAMP) 
    FROM Temporary._EB_TraceLog AS T 
    WHERE T.ID = @Counter; 

    ---------------------------------------------------------------------------------------------------------------- 
    -- Take time snapshot and execute optimized procedure, which inserts records into Temporary table 
    -- When done - measurements will be updated on TraceLog table 
    ---------------------------------------------------------------------------------------------------------------- 
    SELECT @StartTime = CURRENT_TIMESTAMP; 
    EXECUTE sp_executesql @SQLStringTemp; 

    UPDATE T 
    SET T.TempExecutionTime = DATEDIFF(MILLISECOND, @StartTime, CURRENT_TIMESTAMP) 
    FROM Temporary._EB_TraceLog AS T 
    WHERE T.ID = @Counter; 

    ---------------------------------------------------------------------------------------------------------------- 
    -- Check if there are any data discrepancies 
    -- If there are any, set IsDifferent to 1, so we can find the root cause 
    ---------------------------------------------------------------------------------------------------------------- 
    IF EXISTS (SELECT * FROM Temporary._EB_Test_Mod EXCEPT SELECT * FROM Temporary._EB_Test_Orig) 
    OR EXISTS (SELECT * FROM Temporary._EB_Test_Orig EXCEPT SELECT * FROM Temporary._EB_Test_Mod) 
    BEGIN 
     UPDATE T 
     SET T.IsDifferent = 1 
     FROM Temporary._EB_TraceLog AS T 
     WHERE T.ID = @Counter; 
    END 

    ---------------------------------------------------------------------------------------------------------------- 
    -- Update record counts for each execution 
    -- We can check if there aren't any different record counts even tho results are same 
    -- EXCEPT clause removes duplicates when doing checks 
    ---------------------------------------------------------------------------------------------------------------- 
    UPDATE T 
    SET T.CurrentExecutionResultsCount = (SELECT COUNT(*) FROM Temporary._EB_Test_Orig) 
     , T.TempExecutionResultsCount = (SELECT COUNT(*) FROM Temporary._EB_Test_Mod) 
    FROM Temporary._EB_TraceLog AS T 
    WHERE T.ID = @Counter; 

    ---------------------------------------------------------------------------------------------------------------- 
    -- Print iteration number and proceed on next one 
    ---------------------------------------------------------------------------------------------------------------- 
    PRINT @Counter; 
    SET @Counter += 1; 
END 

SELECT * 
FROM Temporary._EB_TraceLog; 

這工作得很好,到目前爲止,但我想包括IO和在每個迭代時間統計。那可能嗎?

我知道我可以用做:

SET STATISTICS IO ON; 
SET STATISTICS TIME ON; 

但是,有沒有辦法抓住總結值並把它們放在我的追蹤日誌表?

最重要的是,這段代碼有沒有什麼不合理的地方?

感謝

+0

這使我的心是使用擴展事件的唯一的事情,但我不知道這是否是適合這個 –

+0

如果你想只執行那麼你可以通過聲明一個'variable'並在開始執行之前和完成一個語句之後使用'datediff'使用'datetime'差異來計算它。或者更詳細的信息,你可以使用這個'DMV'' sys.dm_exec_query_stats'。 –

+0

嗨@ArunGairola,我已經在做這個(關於'DATEDIFF()')。但看看'sys.dm_exec_query_stats'看起來很有希望。我如何將這個'DMV'的行連接到實際的程序執行? –

回答

1

您可以使用此查詢

SELECT total_elapsed_time 
FROM sys.dm_exec_query_stats 
WHERE sql_handle in (SELECT most_recent_sql_handle 
FROM sys.dm_exec_connections 
CROSS APPLY sys.dm_exec_sql_text(most_recent_sql_handle) 
WHERE session_id = (@@spid)) 
+1

這看起來非常符合我的要求,我會玩弄這個查詢來獲得所需的輸出,非常感謝您的幫助! –