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 94c6d2f

Browse files
Add missing index details to BQS
Your mom.
1 parent 2689799 commit 94c6d2f

File tree

2 files changed

+272
-3
lines changed

2 files changed

+272
-3
lines changed

‎sp_BlitzCache.sql‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3333,7 +3333,7 @@ OPTION(RECOMPILE);
33333333
/*Begin Missing Index*/
33343334

33353335
IF EXISTS
3336-
(SELECT 1 FROM ##bou_BlitzCacheProcs AS bbcp WHERE bbcp.missing_index_count > 0 )
3336+
(SELECT 1 FROM ##bou_BlitzCacheProcs AS bbcp WHERE bbcp.missing_index_count > 0 ANDbbcp.SPID=@@SPID)
33373337
BEGIN
33383338

33393339
WITH XMLNAMESPACES ( 'http://schemas.microsoft.com/sqlserver/2004/07/showplan' AS p )
@@ -3442,6 +3442,8 @@ IF EXISTS
34423442
FROM ##bou_BlitzCacheProcs AS bbcp
34433443
JOIN missing AS m
34443444
ON m.SqlHandle = bbcp.SqlHandle
3445+
AND SPID = @@SPID
3446+
OPTION(RECOMPILE);
34453447

34463448

34473449
END

‎sp_BlitzQueryStore.sql‎

Lines changed: 269 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,7 @@ CREATE TABLE #working_warnings
614614
is_paul_white_electric BIT,
615615
implicit_conversion_info XML,
616616
cached_execution_parameters XML,
617+
missing_indexes XML,
617618
warnings NVARCHAR(4000)
618619
INDEX ww_ix_ids CLUSTERED (plan_id, query_id, query_hash, sql_handle)
619620
);
@@ -817,8 +818,120 @@ CREATE TABLE #conversion_info
817818
INDEX cif_ix_ids CLUSTERED (sql_handle, query_hash)
818819
);
819820

821+
/* These tables support the Missing Index details clickable*/
820822

821823

824+
DROP TABLE IF EXISTS #missing_index_xml
825+
826+
CREATE TABLE #missing_index_xml
827+
(
828+
query_hash BINARY(8),
829+
sql_handle VARBINARY(64),
830+
impact FLOAT,
831+
index_xml XML
832+
);
833+
834+
DROP TABLE IF EXISTS #missing_index_schema
835+
836+
CREATE TABLE #missing_index_schema
837+
(
838+
query_hash BINARY(8),
839+
sql_handle VARBINARY(64),
840+
impact FLOAT,
841+
database_name NVARCHAR(128),
842+
schema_name NVARCHAR(128),
843+
table_name NVARCHAR(128),
844+
index_xml XML
845+
);
846+
847+
848+
DROP TABLE IF EXISTS #missing_index_usage
849+
850+
CREATE TABLE #missing_index_usage
851+
(
852+
query_hash BINARY(8),
853+
sql_handle VARBINARY(64),
854+
impact FLOAT,
855+
database_name NVARCHAR(128),
856+
schema_name NVARCHAR(128),
857+
table_name NVARCHAR(128),
858+
usage NVARCHAR(128),
859+
index_xml XML
860+
);
861+
862+
DROP TABLE IF EXISTS #missing_index_detail
863+
864+
CREATE TABLE #missing_index_detail
865+
(
866+
query_hash BINARY(8),
867+
sql_handle VARBINARY(64),
868+
impact FLOAT,
869+
database_name NVARCHAR(128),
870+
schema_name NVARCHAR(128),
871+
table_name NVARCHAR(128),
872+
usage NVARCHAR(128),
873+
column_name NVARCHAR(128)
874+
);
875+
876+
877+
DROP TABLE IF EXISTS #missing_index_pretty
878+
879+
CREATE TABLE #missing_index_pretty
880+
(
881+
query_hash BINARY(8),
882+
sql_handle VARBINARY(64),
883+
impact FLOAT,
884+
database_name NVARCHAR(128),
885+
schema_name NVARCHAR(128),
886+
table_name NVARCHAR(128),
887+
equality NVARCHAR(4000),
888+
inequality NVARCHAR(4000),
889+
[include] NVARCHAR(4000),
890+
details AS N'/* '
891+
+ CHAR(10)
892+
+ N'The Query Processor estimates that implementing the following index could improve the query cost by '
893+
+ CONVERT(NVARCHAR(30), impact)
894+
+ '%.'
895+
+ CHAR(10)
896+
+ N'*/'
897+
+ CHAR(10) + CHAR(13)
898+
+ N'/* '
899+
+ CHAR(10)
900+
+ N'USE '
901+
+ database_name
902+
+ CHAR(10)
903+
+ N'GO'
904+
+ CHAR(10) + CHAR(13)
905+
+ N'CREATE NONCLUSTERED INDEX ix_'
906+
+ ISNULL(REPLACE(REPLACE(REPLACE(equality,'[', ''), ']', ''), ', ', '_'), '')
907+
+ ISNULL(REPLACE(REPLACE(REPLACE(inequality,'[', ''), ']', ''), ', ', '_'), '')
908+
+ CASE WHEN [include] IS NOT NULL THEN + N'Includes' ELSE N'' END
909+
+ CHAR(10)
910+
+ N' ON '
911+
+ schema_name
912+
+ N'.'
913+
+ table_name
914+
+ N' (' +
915+
+ CASE WHEN equality IS NOT NULL
916+
THEN equality
917+
+ CASE WHEN inequality IS NOT NULL
918+
THEN N', ' + inequality
919+
ELSE N''
920+
END
921+
ELSE inequality
922+
END
923+
+ N')'
924+
+ CHAR(10)
925+
+ CASE WHEN include IS NOT NULL
926+
THEN N'INCLUDE (' + include + N')'
927+
ELSE N''
928+
END
929+
+ CHAR(10)
930+
+ N'GO'
931+
+ CHAR(10)
932+
+ N'*/'
933+
);
934+
822935
/*Sets up WHERE clause that gets used quite a bit*/
823936

824937
--Date stuff
@@ -3077,7 +3190,141 @@ SET b.implicit_conversion_info = CASE WHEN b.implicit_conversion_info IS NULL
30773190
FROM #working_warnings AS b
30783191
OPTION ( RECOMPILE );
30793192

3193+
/*Begin Missing Index*/
30803194

3195+
IF EXISTS
3196+
(SELECT 1 FROM #working_warnings AS ww WHERE ww.missing_index_count > 0 )
3197+
3198+
BEGIN
3199+
3200+
RAISERROR(N'Inserting to #missing_index_xml', 0, 1) WITH NOWAIT;
3201+
WITH XMLNAMESPACES ( 'http://schemas.microsoft.com/sqlserver/2004/07/showplan' AS p )
3202+
INSERT #missing_index_xml
3203+
SELECT qp.query_hash,
3204+
qp.sql_handle,
3205+
c.mg.value('@Impact', 'FLOAT') AS Impact,
3206+
c.mg.query('.') AS cmg
3207+
FROM #query_plan AS qp
3208+
CROSS APPLY qp.query_plan.nodes('//p:MissingIndexes/p:MissingIndexGroup') AS c(mg)
3209+
WHERE qp.query_hash IS NOT NULL
3210+
AND c.mg.value('@Impact', 'FLOAT') > 70.0
3211+
OPTION(RECOMPILE);
3212+
3213+
RAISERROR(N'Inserting to #missing_index_schema', 0, 1) WITH NOWAIT;
3214+
WITH XMLNAMESPACES ( 'http://schemas.microsoft.com/sqlserver/2004/07/showplan' AS p )
3215+
INSERT #missing_index_schema
3216+
SELECT mix.query_hash, mix.sql_handle, mix.impact,
3217+
c.mi.value('@Database', 'NVARCHAR(128)') ,
3218+
c.mi.value('@Schema', 'NVARCHAR(128)') ,
3219+
c.mi.value('@Table', 'NVARCHAR(128)') ,
3220+
c.mi.query('.')
3221+
FROM #missing_index_xml AS mix
3222+
CROSS APPLY mix.index_xml.nodes('//p:MissingIndex') AS c(mi)
3223+
OPTION(RECOMPILE);
3224+
3225+
RAISERROR(N'Inserting to #missing_index_usage', 0, 1) WITH NOWAIT;
3226+
WITH XMLNAMESPACES ( 'http://schemas.microsoft.com/sqlserver/2004/07/showplan' AS p )
3227+
INSERT #missing_index_usage
3228+
SELECT ms.query_hash, ms.sql_handle, ms.impact, ms.database_name, ms.schema_name, ms.table_name,
3229+
c.cg.value('@Usage', 'NVARCHAR(128)'),
3230+
c.cg.query('.')
3231+
FROM #missing_index_schema ms
3232+
CROSS APPLY ms.index_xml.nodes('//p:ColumnGroup') AS c(cg)
3233+
OPTION(RECOMPILE);
3234+
3235+
RAISERROR(N'Inserting to #missing_index_detail', 0, 1) WITH NOWAIT;
3236+
WITH XMLNAMESPACES ( 'http://schemas.microsoft.com/sqlserver/2004/07/showplan' AS p )
3237+
INSERT #missing_index_detail
3238+
SELECT miu.query_hash,
3239+
miu.sql_handle,
3240+
miu.impact,
3241+
miu.database_name,
3242+
miu.schema_name,
3243+
miu.table_name,
3244+
miu.usage,
3245+
c.c.value('@Name', 'NVARCHAR(128)')
3246+
FROM #missing_index_usage AS miu
3247+
CROSS APPLY miu.index_xml.nodes('//p:Column') AS c(c)
3248+
OPTION(RECOMPILE);
3249+
3250+
RAISERROR(N'Inserting to #missing_index_pretty', 0, 1) WITH NOWAIT;
3251+
INSERT #missing_index_pretty
3252+
SELECT m.query_hash, m.sql_handle, m.impact, m.database_name, m.schema_name, m.table_name
3253+
, STUFF(( SELECT DISTINCT N', ' + ISNULL(m2.column_name, '') AS column_name
3254+
FROM #missing_index_detail AS m2
3255+
WHERE m2.usage = 'EQUALITY'
3256+
AND m.query_hash = m2.query_hash
3257+
AND m.sql_handle = m2.sql_handle
3258+
AND m.impact = m2.impact
3259+
AND m.database_name = m2.database_name
3260+
AND m.schema_name = m2.schema_name
3261+
AND m.table_name = m2.table_name
3262+
FOR XML PATH(N''), TYPE ).value(N'.[1]', N'NVARCHAR(4000)'), 1, 2, N'') AS equality
3263+
, STUFF(( SELECT DISTINCT N', ' + ISNULL(m2.column_name, '') AS column_name
3264+
FROM #missing_index_detail AS m2
3265+
WHERE m2.usage = 'INEQUALITY'
3266+
AND m.query_hash = m2.query_hash
3267+
AND m.sql_handle = m2.sql_handle
3268+
AND m.impact = m2.impact
3269+
AND m.database_name = m2.database_name
3270+
AND m.schema_name = m2.schema_name
3271+
AND m.table_name = m2.table_name
3272+
FOR XML PATH(N''), TYPE ).value(N'.[1]', N'NVARCHAR(4000)'), 1, 2, N'') AS inequality
3273+
, STUFF(( SELECT DISTINCT N', ' + ISNULL(m2.column_name, '') AS column_name
3274+
FROM #missing_index_detail AS m2
3275+
WHERE m2.usage = 'INCLUDE'
3276+
AND m.query_hash = m2.query_hash
3277+
AND m.sql_handle = m2.sql_handle
3278+
AND m.impact = m2.impact
3279+
AND m.database_name = m2.database_name
3280+
AND m.schema_name = m2.schema_name
3281+
AND m.table_name = m2.table_name
3282+
FOR XML PATH(N''), TYPE ).value(N'.[1]', N'NVARCHAR(4000)'), 1, 2, N'') AS [include]
3283+
FROM #missing_index_detail AS m
3284+
GROUP BY m.query_hash, m.sql_handle, m.impact, m.database_name, m.schema_name, m.table_name
3285+
OPTION(RECOMPILE);
3286+
3287+
RAISERROR(N'Updating missing index information', 0, 1) WITH NOWAIT;
3288+
WITH missing AS (
3289+
SELECT mip.query_hash,
3290+
mip.sql_handle,
3291+
CONVERT(XML,
3292+
N'<?MissingIndexes -- '
3293+
+ CHAR(10) + CHAR(13)
3294+
+ STUFF(( SELECT CHAR(10) + CHAR(13) + ISNULL(mip2.details, '') AS details
3295+
FROM #missing_index_pretty AS mip2
3296+
WHERE mip.query_hash = mip2.query_hash
3297+
AND mip.sql_handle = mip2.sql_handle
3298+
GROUP BY mip2.details
3299+
ORDER BY MAX(mip2.impact) DESC
3300+
FOR XML PATH(N''), TYPE ).value(N'.[1]', N'NVARCHAR(4000)'), 1, 2, N'')
3301+
+ CHAR(10) + CHAR(13)
3302+
+ N' -- ?>'
3303+
) AS full_details
3304+
FROM #missing_index_pretty AS mip
3305+
GROUP BY mip.query_hash, mip.sql_handle, mip.impact
3306+
)
3307+
UPDATE ww
3308+
SET ww.missing_indexes = m.full_details
3309+
FROM #working_warnings AS ww
3310+
JOIN missing AS m
3311+
ON m.sql_handle = ww.sql_handle
3312+
OPTION(RECOMPILE);
3313+
3314+
3315+
END
3316+
3317+
RAISERROR(N'Filling in missing index blanks', 0, 1) WITH NOWAIT;
3318+
UPDATE ww
3319+
SET ww.missing_indexes =
3320+
CASE WHEN ww.missing_indexes IS NULL
3321+
THEN '<?NoNeedToClickMe -- N/A --?>'
3322+
ELSE ww.missing_indexes
3323+
END
3324+
FROM #working_warnings AS ww
3325+
OPTION(RECOMPILE);
3326+
3327+
/*End Missing Index*/
30813328

30823329
RAISERROR(N'General query dispositions: frequent executions, long running, etc.', 0, 1) WITH NOWAIT;
30833330

@@ -3292,7 +3539,7 @@ RAISERROR(N'Returning regular results', 0, 1) WITH NOWAIT;
32923539

32933540
WITH x AS (
32943541
SELECT wpt.database_name, ww.query_cost, wm.plan_id, wm.query_id, wpt.query_sql_text, wm.proc_or_function_name, wpt.query_plan_xml, ww.warnings, wpt.pattern,
3295-
wm.parameter_sniffing_symptoms, wpt.top_three_waits, ww.implicit_conversion_info, ww.cached_execution_parameters, wm.count_executions, wm.count_compiles, wm.total_cpu_time, wm.avg_cpu_time,
3542+
wm.parameter_sniffing_symptoms, wpt.top_three_waits, ww.missing_indexes, ww.implicit_conversion_info, ww.cached_execution_parameters, wm.count_executions, wm.count_compiles, wm.total_cpu_time, wm.avg_cpu_time,
32963543
wm.total_duration, wm.avg_duration, wm.total_logical_io_reads, wm.avg_logical_io_reads,
32973544
wm.total_physical_io_reads, wm.avg_physical_io_reads, wm.total_logical_io_writes, wm.avg_logical_io_writes, wm.total_rowcount, wm.avg_rowcount,
32983545
wm.total_query_max_used_memory, wm.avg_query_max_used_memory, wm.total_tempdb_space_used, wm.avg_tempdb_space_used,
@@ -3321,7 +3568,7 @@ RAISERROR(N'Returning results for failed queries', 0, 1) WITH NOWAIT;
33213568

33223569
WITH x AS (
33233570
SELECT wpt.database_name, ww.query_cost, wm.plan_id, wm.query_id, wpt.query_sql_text, wm.proc_or_function_name, wpt.query_plan_xml, ww.warnings, wpt.pattern,
3324-
wm.parameter_sniffing_symptoms, wpt.last_force_failure_reason_desc, wpt.top_three_waits, ww.implicit_conversion_info, ww.cached_execution_parameters,
3571+
wm.parameter_sniffing_symptoms, wpt.last_force_failure_reason_desc, wpt.top_three_waits, ww.missing_indexes, ww.implicit_conversion_info, ww.cached_execution_parameters,
33253572
wm.count_executions, wm.count_compiles, wm.total_cpu_time, wm.avg_cpu_time,
33263573
wm.total_duration, wm.avg_duration, wm.total_logical_io_reads, wm.avg_logical_io_reads,
33273574
wm.total_physical_io_reads, wm.avg_physical_io_reads, wm.total_logical_io_writes, wm.avg_logical_io_writes, wm.total_rowcount, wm.avg_rowcount,
@@ -4428,6 +4675,26 @@ SELECT '#variable_info' AS table_name, *
44284675
FROM #variable_info AS vi
44294676
OPTION ( RECOMPILE );
44304677

4678+
SELECT '#missing_index_xml' AS table_name, *
4679+
FROM #missing_index_xml
4680+
OPTION ( RECOMPILE );
4681+
4682+
SELECT '#missing_index_schema' AS table_name, *
4683+
FROM #missing_index_schema
4684+
OPTION ( RECOMPILE );
4685+
4686+
SELECT '#missing_index_usage' AS table_name, *
4687+
FROM #missing_index_usage
4688+
OPTION ( RECOMPILE );
4689+
4690+
SELECT '#missing_index_detail' AS table_name, *
4691+
FROM #missing_index_detail
4692+
OPTION ( RECOMPILE );
4693+
4694+
SELECT '#missing_index_pretty' AS table_name, *
4695+
FROM #missing_index_pretty
4696+
OPTION ( RECOMPILE );
4697+
44314698
END;
44324699

44334700
END TRY

0 commit comments

Comments
(0)

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