4
4
5
5
6
6
ALTER PROCEDURE dbo .sp_BenchmarkTSQL (
7
- @tsqlStatement NVARCHAR (MAX )= N ' '
7
+ @tsqlStatement NVARCHAR (MAX )
8
8
, @numberOfExecution INT = 10
9
9
, @saveResults BIT = 0
10
10
, @clearCache BIT = 0
11
11
, @calcMedian BIT = 0
12
12
, @printStepInfo BIT = 1
13
+ , @durationAccuracy VARCHAR (10 ) = ' ns'
13
14
)
14
15
/*
15
16
.SYNOPSIS
@@ -44,11 +45,13 @@ ALTER PROCEDURE dbo.sp_BenchmarkTSQL(
44
45
EXEC sp_BenchmarkTSQL @tsqlStatement = 'SELECT * FROM sys.databases';
45
46
46
47
.EXAMPLE
47
- EXEC sp_BenchmarkTSQL @tsqlStatement = 'SELECT TOP(10000 ) * FROM sys.objects AS o1 CROSS JOIN sys.objects AS o2;'
48
+ EXEC sp_BenchmarkTSQL @tsqlStatement = 'SELECT TOP(100000 ) * FROM sys.objects AS o1 CROSS JOIN sys.objects AS o2 CROSS JOIN sys.objects AS o3 ;'
48
49
, @numberOfExecution = 100
50
+ , @saveResults = 1
49
51
, @calcMedian = 1
50
52
, @clearCache = 1
51
- , @printStepInfo = 0;
53
+ , @printStepInfo = 0
54
+ , @durationAccuracy = 'ms';
52
55
53
56
.NOTE
54
57
Author: Aleksei Nagorskii
@@ -60,8 +63,8 @@ ALTER PROCEDURE dbo.sp_BenchmarkTSQL(
60
63
Version: 1.1
61
64
62
65
Author: Konstantin Taranov
63
- Modified date: 2017-12-16
64
- Version: 1.2
66
+ Modified date: 2017-12-23
67
+ Version: 2.0
65
68
*/
66
69
AS
67
70
BEGIN TRY
@@ -71,7 +74,23 @@ BEGIN TRY
71
74
IF @tsqlStatement IS NULL
72
75
THROW 55001 , ' @tsqlStatement is NULL, please specify TSQL statement.' , 1 ;
73
76
IF @tsqlStatement = N ' '
74
- THROW 55001 , ' @tsqlStatement is empty, please specify TSQL statement.' , 1 ;
77
+ THROW 55002 , ' @tsqlStatement is empty, please specify TSQL statement.' , 1 ;
78
+
79
+ IF @durationAccuracy NOT IN (
80
+ ' ns' -- nanosecond
81
+ , ' mcs' -- microsecond
82
+ , ' ms' -- millisecond
83
+ , ' ss' -- second
84
+ , ' s' -- second
85
+ , ' mi' -- minute
86
+ , ' n' -- minute
87
+ , ' hh' -- hour
88
+ , ' wk' -- week
89
+ , ' ww' -- week
90
+ , ' dd' -- day
91
+ , ' d' -- day
92
+ )
93
+ THROW 55003 , ' @durationAccuracy can be only in this values: ns, mcs, ms, ss, s, mi, n, hh. See DATEDIFF https://docs.microsoft.com/en-us/sql/t-sql/functions/datediff-transact-sql' , 1 ;
75
94
76
95
IF EXISTS (
77
96
SELECT 1
@@ -90,114 +109,208 @@ BEGIN TRY
90
109
FROM sys .dm_exec_describe_first_result_set (@tsqlStatement, NULL , 0 )
91
110
WHERE column_ordinal = 0 ;
92
111
93
- THROW 55002 , @err_msg, 1 ;
112
+ THROW 55004 , @err_msg, 1 ;
94
113
END
95
114
96
115
DECLARE @crlf VARCHAR (10 ) = CHAR (10 );
97
- DECLARE @cts DATETIME = CURRENT_TIMESTAMP ;
116
+ DECLARE @cts DATETIME2 ( 7 ) = CURRENT_TIMESTAMP ;
98
117
DECLARE @r INT = 0 ;
99
- DECLARE @handle VARBINARY (64 );
100
- DECLARE @min INT ;
101
- DECLARE @avg INT ;
102
- DECLARE @max INT ;
118
+ DECLARE @min BIGINT ;
119
+ DECLARE @avg BIGINT ;
120
+ DECLARE @max BIGINT ;
103
121
DECLARE @median REAL ;
104
122
DECLARE @plan_handle VARBINARY (64 );
105
- DECLARE @rts DATETIME ;
123
+ DECLARE @rts DATETIME2 (7 );
124
+ DECLARE @finishTime DATETIME2 (7 );
125
+ DECLARE @duration INT ;
126
+
106
127
DECLARE @t TABLE (
107
- StartTimeStamp DATETIME2 ,
108
- RunTimeStamp DATETIME2 ,
109
- FinishTimeStamp DATETIME2 ,
110
- TsqlStatement NVARCHAR (MAX ),
111
- ClearCache BIT
128
+ StartTimeStamp DATETIME2 (7 )
129
+ , RunTimeStamp DATETIME2 (7 )
130
+ , FinishTimeStamp DATETIME2 (7 )
131
+ , Duration BIGINT
132
+ , TsqlStatement NVARCHAR (MAX )
133
+ , ClearCache BIT
134
+ , PrintStepInfo BIT
135
+ , DurationAccuracy VARCHAR (10 )
112
136
);
113
137
114
- PRINT (' Benchmark started at ' + CONVERT (VARCHAR (23 ), CURRENT_TIMESTAMP , 121 ));
138
+ PRINT (' Benchmark started at ' + CONVERT (VARCHAR (27 ), CAST ( CURRENT_TIMESTAMP AS DATETIME2 ( 7 )) , 121 ));
115
139
116
140
WHILE @r < @numberOfExecution
117
141
BEGIN
118
142
SET @r = @r + 1 ;
119
- SET @rts = CURRENT_TIMESTAMP ;
143
+ SET @rts = CAST ( CURRENT_TIMESTAMP AS DATETIME2 ( 7 )) ;
120
144
121
145
IF @clearCache = 1
122
146
BEGIN
123
- SELECT @handle = plan_handle
147
+ SELECT @plan_handle = plan_handle
124
148
FROM sys .dm_exec_cached_plans
125
149
CROSS APPLY sys .dm_exec_sql_text (plan_handle)
126
- WHERE [text] LIKE @tsqlStatement;
150
+ WHERE [text] LIKE @tsqlStatement;-- LIKE instead = (equal) because = ignoring trailing spaces
127
151
128
- IF @handle IS NOT NULL DBCC FREEPROCCACHE (@handle );
152
+ IF @plan_handle IS NOT NULL DBCC FREEPROCCACHE (@plan_handle );
129
153
END ;
130
154
131
155
EXECUTE sp_executesql @tsqlStatement;
132
156
133
- IF @printStepInfo = 1
134
- PRINT (
135
- ' Run ' + CASE WHEN @r < 10 THEN ' ' + CAST (@r AS VARCHAR (30 ))
136
- WHEN @r < 100 THEN ' ' + CAST (@r AS VARCHAR (30 ))
137
- ELSE CAST (@r AS VARCHAR (30 ))
138
- END +
139
- ' , start: ' + CONVERT (VARCHAR (23 ), @rts, 121 ) +
140
- ' , finish: ' + CONVERT (VARCHAR (23 ), CURRENT_TIMESTAMP , 121 ) +
141
- ' , duration: ' + CAST (DATEDIFF (ms, @rts, CURRENT_TIMESTAMP ) AS VARCHAR (MAX )) + ' ms.'
142
- );
157
+ SET @finishTime = CAST (CURRENT_TIMESTAMP AS DATETIME2 (7 ));
158
+ SET @duration = CASE WHEN @durationAccuracy = ' ns' THEN CAST (DATEDIFF (ns, @rts, @finishTime) AS INT )
159
+ WHEN @durationAccuracy = ' mcs' THEN CAST (DATEDIFF (mcs, @rts, @finishTime) AS INT )
160
+ WHEN @durationAccuracy = ' ms' THEN CAST (DATEDIFF (ms, @rts, @finishTime) AS INT )
161
+ WHEN @durationAccuracy = ' ss' THEN CAST (DATEDIFF (ss, @rts, @finishTime) AS INT )
162
+ WHEN @durationAccuracy = ' s' THEN CAST (DATEDIFF (s, @rts, @finishTime) AS INT )
163
+ WHEN @durationAccuracy = ' mi' THEN CAST (DATEDIFF (mi, @rts, @finishTime) AS INT )
164
+ WHEN @durationAccuracy = ' n' THEN CAST (DATEDIFF (n, @rts, @finishTime) AS INT )
165
+ WHEN @durationAccuracy = ' hh' THEN CAST (DATEDIFF (hh, @rts, @finishTime) AS INT )
166
+ WHEN @durationAccuracy = ' wk' THEN CAST (DATEDIFF (wk, @rts, @finishTime) AS INT )
167
+ WHEN @durationAccuracy = ' ww' THEN CAST (DATEDIFF (ww, @rts, @finishTime) AS INT )
168
+ WHEN @durationAccuracy = ' dd' THEN CAST (DATEDIFF (dd, @rts, @finishTime) AS INT )
169
+ WHEN @durationAccuracy = ' d' THEN CAST (DATEDIFF (d, @rts, @finishTime) AS INT )
170
+ ELSE 0
171
+ END ;
143
172
144
173
INSERT @t (
145
174
StartTimeStamp
146
175
, RunTimeStamp
147
176
, FinishTimeStamp
177
+ , Duration
148
178
, TsqlStatement
149
179
, ClearCache
180
+ , PrintStepInfo
181
+ , DurationAccuracy
150
182
)
151
183
VALUES (
152
184
@cts
153
185
, @rts
154
- , CURRENT_TIMESTAMP
186
+ , @finishTime
187
+ , @duration
155
188
, @tsqlStatement
156
189
, @clearCache
190
+ , @printStepInfo
191
+ , @durationAccuracy
157
192
);
193
+
194
+ IF @printStepInfo = 1
195
+ PRINT (
196
+ ' Run ' + CASE WHEN @r < 10 THEN ' ' + CAST (@r AS VARCHAR (30 ))
197
+ WHEN @r < 100 THEN ' ' + CAST (@r AS VARCHAR (30 ))
198
+ ELSE CAST (@r AS VARCHAR (30 ))
199
+ END +
200
+ ' , start: ' + CONVERT (VARCHAR (27 ), @rts, 121 ) +
201
+ ' , finish: ' + CONVERT (VARCHAR (27 ), CAST (CURRENT_TIMESTAMP AS DATETIME2 (7 )), 121 ) +
202
+ ' , duration: ' + CAST (@duration AS VARCHAR (100 )) + @durationAccuracy + ' .'
203
+ );
204
+
158
205
END ;
159
206
160
- SELECT @min = MIN (DATEDIFF (ms, RunTimeStamp, FinishTimeStamp) )
161
- , @avg = AVG (DATEDIFF (ms, RunTimeStamp, FinishTimeStamp) )
162
- , @max = MAX (DATEDIFF (ms, RunTimeStamp, FinishTimeStamp) )
207
+ SELECT @min = MIN (Duration )
208
+ , @avg = AVG (Duration )
209
+ , @max = MAX (Duration )
163
210
FROM @t;
164
211
165
212
IF @calcMedian = 1
166
213
BEGIN
167
214
SELECT @median = (
168
- (SELECT MAX (TMIN) FROM
169
- (SELECT TOP 50 PERCENT DATEDIFF (ms, RunTimeStamp, FinishTimeStamp) AS TMIN FROM @t ORDER BY TMIN) AS BottomHalf)
170
- +
171
- (SELECT MIN (TMAX) FROM
172
- (SELECT TOP 50 PERCENT DATEDIFF (ms, RunTimeStamp, FinishTimeStamp) AS TMAX FROM @t ORDER BY TMAX DESC ) AS TopHalf)
173
- ) / 2 .0 ;
215
+ (SELECT MAX (TMIN) FROM
216
+ (SELECT TOP (50 ) PERCENT
217
+ CASE WHEN @durationAccuracy = ' ns' THEN CAST (DATEDIFF (ns, RunTimeStamp, FinishTimeStamp) AS INT )
218
+ WHEN @durationAccuracy = ' mcs' THEN CAST (DATEDIFF (mcs, RunTimeStamp, FinishTimeStamp) AS INT )
219
+ WHEN @durationAccuracy = ' ms' THEN CAST (DATEDIFF (ms, RunTimeStamp, FinishTimeStamp) AS INT )
220
+ WHEN @durationAccuracy = ' ss' THEN CAST (DATEDIFF (ss, RunTimeStamp, FinishTimeStamp) AS INT )
221
+ WHEN @durationAccuracy = ' s' THEN CAST (DATEDIFF (s, RunTimeStamp, FinishTimeStamp) AS INT )
222
+ WHEN @durationAccuracy = ' mi' THEN CAST (DATEDIFF (mi, RunTimeStamp, FinishTimeStamp) AS INT )
223
+ WHEN @durationAccuracy = ' n' THEN CAST (DATEDIFF (n, RunTimeStamp, FinishTimeStamp) AS INT )
224
+ WHEN @durationAccuracy = ' hh' THEN CAST (DATEDIFF (hh, RunTimeStamp, FinishTimeStamp) AS INT )
225
+ WHEN @durationAccuracy = ' wk' THEN CAST (DATEDIFF (wk, RunTimeStamp, FinishTimeStamp) AS INT )
226
+ WHEN @durationAccuracy = ' ww' THEN CAST (DATEDIFF (ww, RunTimeStamp, FinishTimeStamp) AS INT )
227
+ WHEN @durationAccuracy = ' dd' THEN CAST (DATEDIFF (dd, RunTimeStamp, FinishTimeStamp) AS INT )
228
+ WHEN @durationAccuracy = ' d' THEN CAST (DATEDIFF (d, RunTimeStamp, FinishTimeStamp) AS INT )
229
+ ELSE 0
230
+ END AS TMIN
231
+ FROM @t
232
+ ORDER BY TMIN
233
+ ) AS BottomHalf
234
+ )
235
+ +
236
+ (SELECT MIN (TMAX) FROM
237
+ (SELECT TOP 50 PERCENT
238
+ CASE WHEN @durationAccuracy = ' ns' THEN CAST (DATEDIFF (ns, RunTimeStamp, FinishTimeStamp) AS INT )
239
+ WHEN @durationAccuracy = ' mcs' THEN CAST (DATEDIFF (mcs, RunTimeStamp, FinishTimeStamp) AS INT )
240
+ WHEN @durationAccuracy = ' ms' THEN CAST (DATEDIFF (ms, RunTimeStamp, FinishTimeStamp) AS INT )
241
+ WHEN @durationAccuracy = ' ss' THEN CAST (DATEDIFF (ss, RunTimeStamp, FinishTimeStamp) AS INT )
242
+ WHEN @durationAccuracy = ' s' THEN CAST (DATEDIFF (s, RunTimeStamp, FinishTimeStamp) AS INT )
243
+ WHEN @durationAccuracy = ' mi' THEN CAST (DATEDIFF (mi, RunTimeStamp, FinishTimeStamp) AS INT )
244
+ WHEN @durationAccuracy = ' n' THEN CAST (DATEDIFF (n, RunTimeStamp, FinishTimeStamp) AS INT )
245
+ WHEN @durationAccuracy = ' hh' THEN CAST (DATEDIFF (hh, RunTimeStamp, FinishTimeStamp) AS INT )
246
+ WHEN @durationAccuracy = ' wk' THEN CAST (DATEDIFF (wk, RunTimeStamp, FinishTimeStamp) AS INT )
247
+ WHEN @durationAccuracy = ' ww' THEN CAST (DATEDIFF (ww, RunTimeStamp, FinishTimeStamp) AS INT )
248
+ WHEN @durationAccuracy = ' dd' THEN CAST (DATEDIFF (dd, RunTimeStamp, FinishTimeStamp) AS INT )
249
+ WHEN @durationAccuracy = ' d' THEN CAST (DATEDIFF (d, RunTimeStamp, FinishTimeStamp) AS INT )
250
+ ELSE 0
251
+ END AS TMAX
252
+ FROM @t
253
+ ORDER BY TMAX DESC
254
+ ) AS TopHalf
255
+ )
256
+ ) / 2 .0 ;
174
257
END ;
175
258
176
259
PRINT (
177
- ' Min: ' + CAST (@min AS VARCHAR (30 )) +
178
- ' ms , Max: ' + CAST (@max AS VARCHAR (30 )) +
179
- ' ms , Average: ' + CAST (@avg AS VARCHAR (30 )) +
180
- CASE WHEN @calcMedian = 1 THEN ' ms , Median: ' + CAST (@median AS VARCHAR (30 )) ELSE ' ' END +
181
- ' ms.' + @crlf +
260
+ ' Min: ' + CAST (@min AS VARCHAR (30 ))+ @durationAccuracy +
261
+ ' , Max: ' + CAST (@max AS VARCHAR (30 ))+ @durationAccuracy +
262
+ ' , Average: ' + CAST (@avg AS VARCHAR (30 ))+ @durationAccuracy +
263
+ CASE WHEN @calcMedian = 1 THEN ' , Median: ' + CAST (@median AS VARCHAR (30 ))+ @durationAccuracy ELSE ' ' END +
264
+ @crlf +
182
265
' Benchmark finished at ' + CONVERT (VARCHAR (23 ), CURRENT_TIMESTAMP , 121 ) + ' .'
183
266
);
184
267
185
-
186
268
IF @saveResults = 1
187
- IF OBJECT_ID (' .[dbo].[BenchmarkTSQL]' , ' U' ) IS NULL
188
- SELECT * INTO dbo .BenchmarkTSQL FROM @t
269
+ IF OBJECT_ID (' dbo.BenchmarkTSQL' , ' U' ) IS NULL
270
+ BEGIN
271
+ CREATE TABLE dbo .BenchmarkTSQL(
272
+ BenchmarkTSQLID INT IDENTITY
273
+ , StartTimeStamp DATETIME2 (7 )
274
+ , RunTimeStamp DATETIME2 (7 )
275
+ , FinishTimeStamp DATETIME2 (7 )
276
+ , Duration BIGINT
277
+ , TsqlStatement NVARCHAR (MAX )
278
+ , ClearCache BIT
279
+ , PrintStepInfo BIT
280
+ , DurationAccuracy VARCHAR (10 )
281
+ );
282
+ INSERT INTO dbo .BenchmarkTSQL (
283
+ StartTimeStamp
284
+ , RunTimeStamp
285
+ , FinishTimeStamp
286
+ , Duration
287
+ , TsqlStatement
288
+ , ClearCache
289
+ , PrintStepInfo
290
+ , DurationAccuracy
291
+ )
292
+ SELECT StartTimeStamp
293
+ , RunTimeStamp
294
+ , FinishTimeStamp
295
+ , Duration
296
+ , TsqlStatement
297
+ , ClearCache
298
+ , PrintStepInfo
299
+ , DurationAccuracy
300
+ FROM @t;
301
+ END
189
302
ELSE
190
303
INSERT INTO dbo .BenchmarkTSQL SELECT * FROM @t;
191
304
192
305
SET NOCOUNT ON ;
193
306
END TRY
194
307
195
308
BEGIN CATCH
196
- PRINT ' Error: ' + CONVERT (varchar (50 ), ERROR_NUMBER ()) +
309
+ PRINT ' Error: ' + CONVERT (varchar (50 ), ERROR_NUMBER ()) +
197
310
' , Severity: ' + CONVERT (varchar (5 ), ERROR_SEVERITY ()) +
198
- ' , State: ' + CONVERT (varchar (5 ), ERROR_STATE ()) +
199
- ' , Procedure: ' + ISNULL (ERROR_PROCEDURE (), ' -' ) +
200
- ' , Line: ' + CONVERT (varchar (5 ), ERROR_LINE ()) +
311
+ ' , State: ' + CONVERT (varchar (5 ), ERROR_STATE ()) +
312
+ ' , Procedure: ' + ISNULL (ERROR_PROCEDURE (), ' -' ) +
313
+ ' , Line: ' + CONVERT (varchar (5 ), ERROR_LINE ()) +
201
314
' , User name: ' + CONVERT (sysname , CURRENT_USER );
202
315
PRINT ERROR_MESSAGE ();
203
316
END CATCH ;
0 commit comments