Question :
I have a rather strange situation. There is a table ProductStock
which has 2 triggers: one for afterInsert and one for afterDelete
both do an insert with the changed value in STOCKDEBUGTRIGGERED
afterDelete:
INSERT INTO STOCKDEBUGTRIGGERED
(ProductID,Amount,StockOld,StockNew)
select deleted.ProductID, count(deleted.ProductStockID),
(select count(productstock.ProductStockID) from PRODUCTSTOCK where productstock.ProductID = deleted.productid) + count(deleted.ProductStockID)
, (select count(productstock.ProductStockID) from PRODUCTSTOCK where productstock.ProductID = deleted.productid)
from deleted
group by deleted.ProductID
afterInsert
INSERT INTO STOCKDEBUGTRIGGERED
(ProductID,Amount,StockOld,StockNew)
select inserted.ProductID, count(inserted.ProductStockID),
(select count(productstock.ProductStockID) from PRODUCTSTOCK where productstock.ProductID = inserted.productid) - count(inserted.ProductStockID)
, (select count(productstock.ProductStockID) from PRODUCTSTOCK where productstock.ProductID = inserted.productid)
from inserted
group by inserted.ProductID
But this is the query which troubles me:
SELECT TOP 250
STOCKDEBUGTRIGGERED.ProductID,
productcode,
'http://urltomyimages.com/' + ProductPictureName as img,
Amount,
STOCKDEBUGTRIGGERED.StockOld,
STOCKDEBUGTRIGGERED.StockNew,
ChangeDate,
(select top 1 STOCKDEBUG.StockDebugWho from STOCKDEBUG
where STOCKDEBUG.ProductID = STOCKDEBUGTRIGGERED.ProductID
and STOCKDEBUG.StockOld = STOCKDEBUGTRIGGERED.StockOld
and STOCKDEBUG.StockNew = STOCKDEBUGTRIGGERED.StockNew
) as who
FROM STOCKDEBUGTRIGGERED
inner join products on STOCKDEBUGTRIGGERED.productid = products.productid
order by ChangeDate desc
Please do not advice temporal tables, because this does work and is running on sql 2008. It only has a high load because this gets executed by a monitoring tool every 5 minutes.
Here are the client statistics:
What troubles me is the 44% sort with the yellow exclamation mark:
So is there a thing I missed? I made a view for the query and threw in three WITH(NOLOCK)
statements. But that did not make it run faster. No index suggestion.
edit have read https://stackoverflow.com/questions/29001721/is-it-possible-to-allocate-memory-to-a-query-in-ms-sql-server because I wanted to see if there was a way to allocate 5mb memory for this query to skip the use of the tempdb. And have read https://www.mssqltips.com/sqlservertip/4132/correct-sql-server-tempdb-spills-in-query-plans-caused-by-outdated-statistics/ but that is not the case for me I think because I limit it to 250 rows.
edit2 if I remove the subquery:
SELECT TOP 250
STOCKDEBUGTRIGGERED.ProductID,
productcode,
'http://ourimages.com/' + ProductPictureName as img,
Amount,
STOCKDEBUGTRIGGERED.StockOld,
STOCKDEBUGTRIGGERED.StockNew,
ChangeDate
FROM STOCKDEBUGTRIGGERED
inner join products on STOCKDEBUGTRIGGERED.productid = products.productid
order by ChangeDate desc
the sort increases to 89% and there is still a 15mb memory load because of the tempdb
edit3
as reply on @T.H. his answer:
execution time is now less than 1% or 2% of original!
Why did neither the perf advisor from azure or the ssms suggest these indexes?
edit4 To prove that @T.H. is right. You can see exactly when I created his two suggested indexes. It had a spike every x time because of that query up to 20% dtu. All spikes are gone and it is nice 1% avg dtu.
Answer :
I believe the basic issue is that the query is doing multiple heavy table scans due to no index support.
Try adding the following indexes:
CREATE NONCLUSTERED INDEX TEST ON STOCKDEBUGTRIGGERED (ChangeDate)
CREATE NONCLUSTERED INDEX TEST ON STOCKDEBUG(ProductID, StockOld, StockNew)
There may be further tweaks, so please post the stats and execution plan with these indexes added.