Skip to content

Commit fad7335

Browse files
committed
Adds implicit conversion info to sp_BlitzCache
1 parent 4c9cc1a commit fad7335

File tree

1 file changed

+180
-1
lines changed

1 file changed

+180
-1
lines changed

sp_BlitzCache.sql

Lines changed: 180 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,8 @@ CREATE TABLE ##bou_BlitzCacheProcs (
210210
estimated_rows FLOAT,
211211
is_bad_estimate BIT,
212212
is_paul_white_electric BIT,
213+
implicit_conversion_info XML,
214+
cached_execution_parameters XML,
213215
SetOptions VARCHAR(MAX),
214216
Warnings VARCHAR(MAX)
215217
);
@@ -891,6 +893,8 @@ BEGIN
891893
estimated_rows FLOAT,
892894
is_bad_estimate BIT,
893895
is_paul_white_electric BIT,
896+
implicit_conversion_info XML,
897+
cached_execution_parameters XML,
894898
SetOptions VARCHAR(MAX),
895899
Warnings VARCHAR(MAX)
896900
);
@@ -1017,6 +1021,9 @@ IF OBJECT_ID ('tempdb..#checkversion') IS NOT NULL
10171021
IF OBJECT_ID ('tempdb..#configuration') IS NOT NULL
10181022
DROP TABLE #configuration;
10191023

1024+
IF OBJECT_ID ('tempdb..#stored_proc_info') IS NOT NULL
1025+
DROP TABLE #stored_proc_info;
1026+
10201027
CREATE TABLE #only_query_hashes (
10211028
query_hash BINARY(8)
10221029
);
@@ -1056,6 +1063,19 @@ CREATE TABLE #configuration (
10561063
value DECIMAL(38,0)
10571064
);
10581065

1066+
CREATE TABLE #stored_proc_info
1067+
(
1068+
SPID INT,
1069+
QueryHash BINARY(8),
1070+
variable_name NVARCHAR(128),
1071+
variable_datatype NVARCHAR(128),
1072+
compile_time_value NVARCHAR(128),
1073+
proc_name NVARCHAR(300),
1074+
column_name NVARCHAR(128),
1075+
converted_to NVARCHAR(128)
1076+
);
1077+
1078+
10591079
RAISERROR(N'Checking plan cache age', 0, 1) WITH NOWAIT;
10601080
WITH x AS (
10611081
SELECT SUM(CASE WHEN DATEDIFF(HOUR, deqs.creation_time, SYSDATETIME()) <= 24 THEN 1 ELSE 0 END) AS [plans_24],
@@ -1102,7 +1122,6 @@ WHERE cp.usecounts = 1
11021122
OPTION (RECOMPILE) ;
11031123

11041124

1105-
11061125
SET @OnlySqlHandles = LTRIM(RTRIM(@OnlySqlHandles)) ;
11071126
SET @OnlyQueryHashes = LTRIM(RTRIM(@OnlyQueryHashes)) ;
11081127
SET @IgnoreQueryHashes = LTRIM(RTRIM(@IgnoreQueryHashes)) ;
@@ -2826,6 +2845,164 @@ ON ipwe.SqlHandle = b.SqlHandle
28262845
WHERE b.SPID = @@SPID
28272846
OPTION (RECOMPILE);
28282847

2848+
IF EXISTS ( SELECT 1
2849+
FROM ##bou_BlitzCacheProcs AS bbcp
2850+
WHERE bbcp.implicit_conversions = 1
2851+
OR bbcp.QueryType LIKE 'Procedure or Function:%' )
2852+
BEGIN
2853+
2854+
RAISERROR(N'Getting information about implicit conversions and stored proc parameters', 0, 1) WITH NOWAIT;
2855+
2856+
WITH XMLNAMESPACES ( 'http://schemas.microsoft.com/sqlserver/2004/07/showplan' AS p )
2857+
, variables_types
2858+
AS ( SELECT qp.QueryHash,
2859+
qp.SqlHandle,
2860+
SUBSTRING(b.QueryType, CHARINDEX('[', b.QueryType), LEN(b.QueryType) - CHARINDEX('[', b.QueryType)) AS proc_name,
2861+
q.n.value('@Column', 'NVARCHAR(128)') AS variable_name,
2862+
q.n.value('@ParameterDataType', 'NVARCHAR(128)') AS variable_datatype,
2863+
q.n.value('@ParameterCompiledValue', 'NVARCHAR(1000)') AS compile_time_value
2864+
FROM #query_plan AS qp
2865+
JOIN ##bou_BlitzCacheProcs AS b
2866+
ON b.QueryHash = qp.QueryHash
2867+
CROSS APPLY qp.query_plan.nodes('//p:QueryPlan/p:ParameterList/p:ColumnReference') AS q(n)
2868+
WHERE qp.QueryHash IS NOT NULL
2869+
AND b.implicit_conversions = 1 ),
2870+
convert_implicit
2871+
AS ( SELECT qp.QueryHash,
2872+
qp.SqlHandle,
2873+
qq.c.value('@Expression', 'NVARCHAR(128)') AS expression,
2874+
SUBSTRING(
2875+
qq.c.value('@Expression', 'NVARCHAR(128)'), --Original Expression
2876+
CHARINDEX('@', qq.c.value('@Expression', 'NVARCHAR(128)')), --Charindex of @+1
2877+
CHARINDEX(']',
2878+
qq.c.value('@Expression', 'NVARCHAR(128)'), --Charindex of end bracket
2879+
CHARINDEX('@', qq.c.value('@Expression', 'NVARCHAR(128)')) + 1 --Starting at the Charindex of the @ +1
2880+
) - CHARINDEX('@', qq.c.value('@Expression', 'NVARCHAR(128)'))) AS variable_name,
2881+
SUBSTRING(
2882+
qq.c.value('@Expression', 'NVARCHAR(128)'), -- Original Expression
2883+
CHARINDEX('].[', qq.c.value('@Expression', 'NVARCHAR(128)')) + 3, --Charindex of ].[ + 3
2884+
CHARINDEX(']',
2885+
qq.c.value('@Expression', 'NVARCHAR(128)'), -- Charindex of end bracket
2886+
CHARINDEX('].[', qq.c.value('@Expression', 'NVARCHAR(128)')) + 3 --Starting at the Charindex of ].[ + 3
2887+
) - CHARINDEX('].[', qq.c.value('@Expression', 'NVARCHAR(128)')) - 3) AS column_name,
2888+
SUBSTRING(
2889+
qq.c.value('@Expression', 'NVARCHAR(128)'), -- Original Expression
2890+
CHARINDEX('(', qq.c.value('@Expression', 'NVARCHAR(128)')) + 1, --Charindex of ( + 1
2891+
CHARINDEX(',',
2892+
qq.c.value('@Expression', 'NVARCHAR(128)'), -- Charindex of comma
2893+
CHARINDEX('(', qq.c.value('@Expression', 'NVARCHAR(128)')) + 1 --Starting at the Charindex of ( + 1
2894+
) - CHARINDEX('(', qq.c.value('@Expression', 'NVARCHAR(128)')) - 1) AS converted_to
2895+
FROM #query_plan AS qp
2896+
JOIN ##bou_BlitzCacheProcs AS b
2897+
ON b.QueryHash = qp.QueryHash
2898+
CROSS APPLY qp.query_plan.nodes('//p:QueryPlan/p:Warnings/p:PlanAffectingConvert') AS qq(c)
2899+
WHERE qq.c.exist('@ConvertIssue[.="Seek Plan"]') = 1
2900+
AND qp.QueryHash IS NOT NULL
2901+
AND b.implicit_conversions = 1 )
2902+
INSERT #stored_proc_info ( SPID, QueryHash, variable_name, variable_datatype, compile_time_value, proc_name, column_name, converted_to )
2903+
SELECT @@SPID,
2904+
vt.QueryHash,
2905+
vt.variable_name,
2906+
vt.variable_datatype,
2907+
vt.compile_time_value,
2908+
vt.proc_name,
2909+
ci.column_name,
2910+
ci.converted_to
2911+
FROM variables_types AS vt
2912+
JOIN convert_implicit AS ci
2913+
ON ci.variable_name = vt.variable_name
2914+
AND ci.QueryHash = vt.QueryHash
2915+
OPTION(RECOMPILE);
2916+
2917+
WITH precheck AS (
2918+
SELECT spi.SPID,
2919+
spi.QueryHash,
2920+
spi.proc_name,
2921+
CONVERT(XML,
2922+
'<?ClickMe -- '
2923+
+ CHAR(10)
2924+
+ 'The stored procedure '
2925+
+ spi.proc_name
2926+
+ ' had the following implicit conversions: '
2927+
+ CHAR(10)
2928+
+ STUFF((
2929+
SELECT DISTINCT
2930+
CHAR(10)
2931+
+ 'The variable '
2932+
+ spi2.variable_name
2933+
+ ' has a data type of '
2934+
+ spi2.variable_datatype
2935+
+ ' which caused implicit conversion on the column '
2936+
+ spi2.column_name
2937+
FROM #stored_proc_info AS spi2
2938+
WHERE spi.QueryHash = spi2.QueryHash
2939+
FOR XML PATH(N''), TYPE).value(N'.[1]', N'NVARCHAR(MAX)'), 1, 1, N'')
2940+
+ CHAR(10)
2941+
+ ' -- ?>'
2942+
) AS implicit_conversion_info,
2943+
CONVERT(XML,
2944+
'<?ClickMe -- '
2945+
+ CHAR(10)
2946+
+ 'This statement '
2947+
+ ' had the following implicit conversions: '
2948+
+ CHAR(10)
2949+
+ STUFF((
2950+
SELECT DISTINCT
2951+
CHAR(10)
2952+
+ 'The variable '
2953+
+ spi2.variable_name
2954+
+ ' has a data type of '
2955+
+ spi2.variable_datatype
2956+
+ ' which caused implicit conversion on the column '
2957+
+ spi2.column_name
2958+
FROM #stored_proc_info AS spi2
2959+
WHERE spi.QueryHash = spi2.QueryHash
2960+
FOR XML PATH(N''), TYPE).value(N'.[1]', N'NVARCHAR(MAX)'), 1, 1, N'')
2961+
+ CHAR(10)
2962+
+ ' -- ?>'
2963+
) AS implicit_conversion_info_statement,
2964+
CONVERT(XML,
2965+
'<?ClickMe -- '
2966+
+ CHAR(10)
2967+
+ 'EXEC '
2968+
+ spi.proc_name
2969+
+ ' '
2970+
+ STUFF((
2971+
SELECT DISTINCT ', '
2972+
+ spi2.variable_name
2973+
+ ' = '
2974+
+ CASE WHEN spi2.compile_time_value = 'NULL'
2975+
THEN spi2.compile_time_value
2976+
ELSE QUOTENAME(spi2.compile_time_value, '''')
2977+
END
2978+
FROM #stored_proc_info AS spi2
2979+
WHERE spi.QueryHash = spi2.QueryHash
2980+
FOR XML PATH(N''), TYPE).value(N'.[1]', N'NVARCHAR(MAX)'), 1, 1, N'')
2981+
+ CHAR(10)
2982+
+ ' -- ?>'
2983+
) AS cached_execution_parameters
2984+
FROM #stored_proc_info AS spi
2985+
GROUP BY spi.SPID, spi.QueryHash, spi.proc_name
2986+
)
2987+
UPDATE b
2988+
SET b.implicit_conversion_info = CASE WHEN b.QueryType = 'Statement' THEN implicit_conversion_info_statement ELSE pk.implicit_conversion_info END,
2989+
b.cached_execution_parameters = pk.cached_execution_parameters
2990+
FROM ##bou_BlitzCacheProcs AS b
2991+
JOIN precheck pk
2992+
ON pk.QueryHash = b.QueryHash
2993+
AND pk.SPID = b.SPID
2994+
AND b.implicit_conversions = 1
2995+
OPTION(RECOMPILE);
2996+
2997+
END --End implicit conversion information gathering
2998+
2999+
UPDATE b
3000+
SET b.implicit_conversion_info = CASE WHEN b.implicit_conversion_info IS NULL THEN '<?NoNeedToClickMe -- N/A --?>' ELSE b.implicit_conversion_info END,
3001+
b.cached_execution_parameters = CASE WHEN b.cached_execution_parameters IS NULL THEN '<?NoNeedToClickMe -- N/A --?>' ELSE b.cached_execution_parameters END
3002+
FROM ##bou_BlitzCacheProcs AS b
3003+
WHERE SPID = @@SPID
3004+
OPTION(RECOMPILE)
3005+
28293006
IF @SkipAnalysis = 1
28303007
BEGIN
28313008
RAISERROR(N'Skipping analysis, going to results', 0, 1) WITH NOWAIT;
@@ -3396,6 +3573,8 @@ BEGIN
33963573
QueryText AS [Query Text],
33973574
QueryType AS [Query Type],
33983575
Warnings AS [Warnings],
3576+
implicit_conversion_info AS [Implicit Conversion Info],
3577+
cached_execution_parameters AS [Cached Execution Parameters],
33993578
ExecutionCount AS [# Executions],
34003579
ExecutionsPerMinute AS [Executions / Minute],
34013580
PercentExecutions AS [Execution Weight],

0 commit comments

Comments
 (0)