Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 9ec3de9

Browse files
Merge pull request BrentOzarULTD#1131 from BrentOzarULTD/Issue_1129
Adds implicit conversion info to sp_BlitzCache
2 parents 1e3f0a9 + dbbf312 commit 9ec3de9

File tree

2 files changed

+375
-23
lines changed

2 files changed

+375
-23
lines changed

‎sp_BlitzCache.sql‎

Lines changed: 178 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,20 @@ CREATE TABLE #configuration (
10561063
value DECIMAL(38,0)
10571064
);
10581065

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

11041125

1105-
11061126
SET @OnlySqlHandles = LTRIM(RTRIM(@OnlySqlHandles)) ;
11071127
SET @OnlyQueryHashes = LTRIM(RTRIM(@OnlyQueryHashes)) ;
11081128
SET @IgnoreQueryHashes = LTRIM(RTRIM(@IgnoreQueryHashes)) ;
@@ -2826,6 +2846,161 @@ ON ipwe.SqlHandle = b.SqlHandle
28262846
WHERE b.SPID = @@SPID
28272847
OPTION (RECOMPILE);
28282848

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

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /