Prior to executing the plan (because I'm debugging a poorly functioning plan) I have this block of variable assignments:
DECLARE @Days INT = 180
DECLARE @DateRangeFrom DateTime = DATEADD(d, -@Days, getDate())
DECLARE @DateRangeTo DateTime = getDate()
DECLARE @FacilityID INT = 1010
DECLARE @Answer0 INT = 1879
DECLARE @Answer1 INT = 1949
DECLARE @Answer1SetID INT = 1607
DECLARE @Answer2 INT = 1907
DECLARE @Answer2SetID INT = 1593
My first problem is with the lookup I'm performing on the IRItemAnswer_Info table (Node ID 19). It's spilling to Tempdb which already starts the query off on the wrong foot.
It's referencing the IRItemAnswerInfo_DGItemID_AnswerSourceID
index, which is the correct index, as I'm matching on DGItemID
and AnswerSourceID
, and getting back IncidentID
. The index is created as
CREATE NONCLUSTERED INDEX IRItemAnswerInfo_DGItemID_AnswerSourceID
ON dbo.IRItemAnswer_Info (DGItemID, AnswerSourceID)
INCLUDE([IncidentID], [AnswerBoolean])
However, the Estimated Rows for the query is 53,459 and the Actual Rows is 969,812.
I just finished forcing new statistics via UPDATE STATISTICS IRItemAnswer_Info IRItemAnswerInfo_DGItemID_AnswerSourceID WITH FULLSCAN
and it made no difference.
DBCC SHOW_STATISTICS ('IRItemAnswer_Info', 'DGItemID')
for DGItemID=1949
has EQ_ROWS
as 1,063,536
and
DBCC SHOW_STATISTICS ('IRItemAnswer_Info', 'AnswerSourceID')
for AnswerSourceID=1607
has EQ_ROWS
as 970,079
The database is running Compatibility level 140 (SQL Server 2017). We would run 2019, but there are issues we need to correct in the stored procedures before we can do that.
What should be the next thing I look at?
I chose the worst performing output, which is the most common values. IRItemAnswer_Info
is a table containing user-defined answers to associate to an event, where DGItemID=1949
is one of the most common questions (almost every event has one), and where AnswerSourceID=1607
is the most common answer. Given that there is a strong correlation between them, how should I reorder the query?
As it is a point of a little bit of confusion, there are two INNER JOIN
s to the same table, IRItemAnswer_Info
. One is the answer I'm looking for (as identified by the question iria.DGItemID=1879
and its output iria.AnswerSourceID
links to irai.AltLabel
), and the second one is a limiting factor. I only want records where the question iiai1.DGItemID=1949
has as its answer iiai1.AnswerSourceID=1607
.
I have explicitly removed the plan from the cache (using DBCC FREEPROCCACHE
) and re-run it, with no change in the result - the Hash Match is still spilling.