Skip to content

Commit 3034c7d

Browse files
authored
Merge pull request BrentOzarULTD#350 from BrentOzarULTD/BlitzCache_Erik_Issue339
Blitzcache erik issue339
2 parents 9c966a8 + bd0001a commit 3034c7d

File tree

1 file changed

+77
-46
lines changed

1 file changed

+77
-46
lines changed

sp_BlitzCache.sql

Lines changed: 77 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1375,7 +1375,32 @@ BEGIN
13751375
EXEC sp_executesql @sql, N'@Top INT, @min_duration INT', @Top, @DurationFilter_i;
13761376
END
13771377

1378-
1378+
/* Update ##bou_BlitzCacheProcs to get Stored Proc info
1379+
* This should get totals for all statements in a Stored Proc
1380+
*/
1381+
;WITH agg AS (
1382+
SELECT
1383+
b.SqlHandle,
1384+
SUM(b.MinReturnedRows) AS MinReturnedRows,
1385+
SUM(b.MaxReturnedRows) AS MaxReturnedRows,
1386+
SUM(b.AverageReturnedRows) AS AverageReturnedRows,
1387+
SUM(b.TotalReturnedRows) AS TotalReturnedRows,
1388+
SUM(b.LastReturnedRows) AS LastReturnedRows
1389+
FROM ##bou_BlitzCacheProcs b
1390+
WHERE b.QueryHash IS NOT NULL
1391+
GROUP BY b.SqlHandle
1392+
)
1393+
UPDATE b
1394+
SET
1395+
b.MinReturnedRows = b2.MinReturnedRows,
1396+
b.MaxReturnedRows = b2.MaxReturnedRows,
1397+
b.AverageReturnedRows = b2.AverageReturnedRows,
1398+
b.TotalReturnedRows = b2.TotalReturnedRows,
1399+
b.LastReturnedRows = b2.LastReturnedRows
1400+
FROM ##bou_BlitzCacheProcs b
1401+
JOIN agg b2
1402+
ON b2.SqlHandle = b.SqlHandle
1403+
WHERE b.QueryHash IS NULL
13791404

13801405
/* Compute the total CPU, etc across our active set of the plan cache.
13811406
* Yes, there's a flaw - this doesn't include anything outside of our @Top
@@ -1520,6 +1545,7 @@ OPTION (RECOMPILE) ;
15201545
WITH XMLNAMESPACES('http://schemas.microsoft.com/sqlserver/2004/07/showplan' AS p)
15211546
SELECT QueryHash ,
15221547
SqlHandle ,
1548+
PlanHandle,
15231549
q.n.query('.') AS statement
15241550
INTO #statements
15251551
FROM ##bou_BlitzCacheProcs p
@@ -1559,50 +1585,55 @@ WHERE ##bou_BlitzCacheProcs.QueryHash = x.QueryHash
15591585
OPTION (RECOMPILE) ;
15601586

15611587
-- statement level checks
1588+
WITH XMLNAMESPACES('http://schemas.microsoft.com/sqlserver/2004/07/showplan' AS p)
1589+
UPDATE ##bou_BlitzCacheProcs
1590+
SET QueryPlanCost = CASE WHEN QueryType LIKE '%Stored Procedure%' THEN
1591+
statement.value('sum(/p:StmtSimple/@StatementSubTreeCost)', 'float')
1592+
ELSE
1593+
statement.value('sum(/p:StmtSimple[xs:hexBinary(substring(@QueryPlanHash, 3)) = xs:hexBinary(sql:column("QueryPlanHash"))]/@StatementSubTreeCost)', 'float')
1594+
END ,
1595+
compile_timeout = CASE WHEN statement.exist('/p:StmtSimple/@StatementOptmEarlyAbortReason[.="TimeOut"]') = 1 THEN 1 END ,
1596+
compile_memory_limit_exceeded = CASE WHEN statement.exist('/p:StmtSimple/@StatementOptmEarlyAbortReason[.="MemoryLimitExceeded"]') = 1 THEN 1 END ,
1597+
unmatched_index_count = statement.value('count(//p:UnmatchedIndexes/Parameterization/Object)', 'int') ,
1598+
is_trivial = CASE WHEN statement.exist('/p:StmtSimple[@StatementOptmLevel[.="TRIVIAL"]]/p:QueryPlan/p:ParameterList') = 1 THEN 1 END ,
1599+
unparameterized_query = CASE WHEN statement.exist('//p:StmtSimple[@StatementOptmLevel[.="FULL"]]/p:QueryPlan/p:ParameterList') = 1 AND
1600+
statement.exist('//p:StmtSimple[@StatementOptmLevel[.="FULL"]]/p:QueryPlan/p:ParameterList/p:ColumnReference') = 0 THEN 1
1601+
WHEN statement.exist('//p:StmtSimple[@StatementOptmLevel[.="FULL"]]/p:QueryPlan/p:ParameterList') = 0 AND
1602+
statement.exist('//p:StmtSimple[@StatementOptmLevel[.="FULL"]]/*/p:RelOp/descendant::p:ScalarOperator/p:Identifier/p:ColumnReference[contains(@Column, "@")]') = 1 THEN 1
1603+
END
1604+
FROM #statements s
1605+
WHERE s.QueryHash = ##bou_BlitzCacheProcs.QueryHash
1606+
OPTION (RECOMPILE);
1607+
1608+
--Gather Stored Proc costs
15621609
;WITH XMLNAMESPACES('http://schemas.microsoft.com/sqlserver/2004/07/showplan' AS p)
1563-
, c1 AS (
1564-
SELECT
1565-
QueryPlanCost_check = CASE WHEN QueryType LIKE '%Stored Procedure%' THEN
1566-
statement.value('sum(/p:StmtSimple/@StatementSubTreeCost)', 'float')
1567-
ELSE
1568-
statement.value('sum(/p:StmtSimple[xs:hexBinary(substring(@QueryPlanHash, 3)) = xs:hexBinary(sql:column("QueryPlanHash"))]/@StatementSubTreeCost)', 'float')
1569-
END ,
1570-
compile_timeout_check = CASE WHEN statement.exist('/p:StmtSimple/@StatementOptmEarlyAbortReason[.="TimeOut"]') = 1 THEN 1 END ,
1571-
compile_memory_limit_exceeded_check = CASE WHEN statement.exist('/p:StmtSimple/@StatementOptmEarlyAbortReason[.="MemoryLimitExceeded"]') = 1 THEN 1 END ,
1572-
unmatched_index_count_check = statement.value('count(//p:UnmatchedIndexes/Parameterization/Object)', 'int') ,
1573-
is_trivial_check = CASE WHEN statement.exist('/p:StmtSimple[@StatementOptmLevel[.="TRIVIAL"]]/p:QueryPlan/p:ParameterList') = 1 THEN 1 END ,
1574-
unparameterized_query_check = CASE WHEN statement.exist('//p:StmtSimple[@StatementOptmLevel[.="FULL"]]/p:QueryPlan/p:ParameterList') = 1 AND
1575-
statement.exist('//p:StmtSimple[@StatementOptmLevel[.="FULL"]]/p:QueryPlan/p:ParameterList/p:ColumnReference') = 0 THEN 1
1576-
WHEN statement.exist('//p:StmtSimple[@StatementOptmLevel[.="FULL"]]/p:QueryPlan/p:ParameterList') = 0 AND
1577-
statement.exist('//p:StmtSimple[@StatementOptmLevel[.="FULL"]]/*/p:RelOp/descendant::p:ScalarOperator/p:Identifier/p:ColumnReference[contains(@Column, "@")]') = 1 THEN 1
1578-
END,
1579-
s.QueryHash
1580-
FROM #statements s
1581-
JOIN ##bou_BlitzCacheProcs b
1582-
ON b.QueryHash = s.QueryHash
1583-
), c2 AS (
1584-
SELECT
1585-
QueryHash,
1586-
QueryPlanCost = MAX([c1].[QueryPlanCost_check]) ,
1587-
compile_timeout = MAX([c1].[compile_timeout_check]) ,
1588-
compile_memory_limit_exceeded = MAX([c1].[compile_memory_limit_exceeded_check]) ,
1589-
unmatched_index_count = MAX([c1].[unmatched_index_count_check]) ,
1590-
is_trivial = MAX([c1].[is_trivial_check]) ,
1591-
unparameterized_query = MAX([c1].[unparameterized_query_check])
1592-
FROM c1
1593-
GROUP BY QueryHash
1610+
, QueryCost AS (
1611+
SELECT
1612+
statement.value('sum(/p:StmtSimple/@StatementSubTreeCost)', 'float') AS SubTreeCost,
1613+
s.PlanHandle,
1614+
s.SqlHandle
1615+
FROM #statements AS s
1616+
WHERE PlanHandle IS NOT NULL
15941617
)
1595-
UPDATE b
1596-
SET
1597-
b.QueryPlanCost = c2.QueryPlanCost,
1598-
b.compile_timeout = c2.compile_timeout,
1599-
b.compile_memory_limit_exceeded = c2.compile_memory_limit_exceeded,
1600-
b.unmatched_index_count = c2.unmatched_index_count,
1601-
b.is_trivial = c2.is_trivial,
1602-
b.unparameterized_query = c2.unparameterized_query
1603-
FROM [c2] AS c2
1604-
JOIN ##bou_BlitzCacheProcs AS b
1605-
ON c2.QueryHash = b.QueryHash
1618+
, QueryCostUpdate AS (
1619+
SELECT
1620+
SUM(qc.SubTreeCost) OVER (PARTITION BY SqlHandle, PlanHandle) PlanTotalQuery,
1621+
qc.PlanHandle,
1622+
qc.SqlHandle
1623+
FROM QueryCost qc
1624+
WHERE qc.SubTreeCost > 0
1625+
)
1626+
UPDATE b
1627+
SET b.QueryPlanCost =
1628+
CASE WHEN
1629+
b.QueryType LIKE '%Procedure%' THEN
1630+
(SELECT TOP 1 PlanTotalQuery FROM QueryCostUpdate qcu WHERE qcu.PlanHandle = b.PlanHandle ORDER BY PlanTotalQuery DESC)
1631+
ELSE
1632+
b.QueryPlanCost
1633+
END
1634+
FROM QueryCostUpdate qcu
1635+
JOIN ##bou_BlitzCacheProcs AS b
1636+
ON qcu.SqlHandle = b.SqlHandle
16061637
OPTION (RECOMPILE);
16071638

16081639
-- query level checks
@@ -1684,12 +1715,12 @@ WITH XMLNAMESPACES('http://schemas.microsoft.com/sqlserver/2004/07/showplan' AS
16841715
UPDATE ##bou_BlitzCacheProcs
16851716
SET NumberOfDistinctPlans = distinct_plan_count,
16861717
NumberOfPlans = number_of_plans,
1687-
QueryPlanCost = CASE WHEN QueryType LIKE '%Stored Procedure%' THEN
1688-
QueryPlan.value('sum(//p:StmtSimple/@StatementSubTreeCost)', 'float')
1718+
QueryPlanCost = CASE WHEN QueryType LIKE '%Procedure%' THEN
1719+
QueryPlanCost
16891720
ELSE
16901721
QueryPlan.value('sum(//p:StmtSimple[xs:hexBinary(substring(@QueryPlanHash, 3)) = xs:hexBinary(sql:column("QueryPlanHash"))]/@StatementSubTreeCost)', 'float')
16911722
END,
1692-
missing_index_count = QueryPlan.value('count(//p:MissingIndexGroup)', 'int') ,
1723+
missing_index_count = QueryPlan.value('count(//p:MissingIndexGroup)', 'int') ,
16931724
unmatched_index_count = QueryPlan.value('count(//p:UnmatchedIndexes/p:Parameterization/p:Object)', 'int') ,
16941725
plan_multiple_plans = CASE WHEN distinct_plan_count < number_of_plans THEN 1 END ,
16951726
is_trivial = CASE WHEN QueryPlan.exist('//p:StmtSimple[@StatementOptmLevel[.="TRIVIAL"]]/p:QueryPlan/p:ParameterList') = 1 THEN 1 END ,

0 commit comments

Comments
 (0)