Clustered Index Update operator performing excessive Logical Reads after query change
10
votes
1
answer
485
views
If I have the following query in the Stack Overflow2010 database
UPDATE dbo.Posts
SET Title =
CASE
WHEN CreationDate <= '2008-01-01T00:00:00'
THEN 'A'
ELSE 'B'
END
FROM dbo.Posts
The abridged
STATISTICS IO
output is below
Table 'Posts'. Scan count 1, logical reads 445699, physical reads 375822, page server reads 0, read-ahead reads 445521, page server read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob page server reads 0, lob read-ahead reads 0, lob page server read-ahead reads 0.
(1878895 rows affected)
and the execution plan is here
If I create a table to store the value I want use in my comparison:
CREATE TABLE dbo.Canary
(
TheDate DATETIME
)
INSERT INTO dbo.Canary VALUES ('2008-01-01T00:00:00')
and then if I change the query as follows:
UPDATE dbo.Posts
SET Title =
CASE
WHEN CreationDate <= Canary.TheDate
THEN 'A'
ELSE 'B'
END
FROM dbo.Posts
CROSS JOIN dbo.Canary
The STATISTICS IO output is
Table 'Canary'. Scan count 1, logical reads 1, physical reads 1, page server reads 0, read-ahead reads 0, page server read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob page server reads 0, lob read-ahead reads 0, lob page server read-ahead reads 0.
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, page server reads 0, read-ahead reads 0, page server read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob page server reads 0, lob read-ahead reads 0, lob page server read-ahead reads 0.
Table 'Posts'. Scan count 1, logical reads 16787757, physical reads 3127, page server reads 0, read-ahead reads 784795, page server read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob page server reads 0, lob read-ahead reads 0, lob page server read-ahead reads 0.
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, page server reads 0, read-ahead reads 6291, page server read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob page server reads 0, lob read-ahead reads 0, lob page server read-ahead reads 0.
(1878895 rows affected)
and the execution plan is here
We can see that the number of logical reads has increased massively, from 445k to 16m. It took me some time to find in the execution plan where the source of this is but I tracked it down using the **Actual I/O statistics / Actual Logical Reads** property and can see the extra reads are on the clustered index update operator, I can also see this operator now has a value for **Actual Number of Rows for all executions** whereas the plan for the first query does not.
What is happening here? what is happening in the clustered index update that is causing the increase in reads?
I appreciate the query should use a variable if this "value in a config table" pattern is to be used, however, this is a query from a vendor app so I want to feedback what is happening as a result of the query being written the way it has.
Asked by SE1986
(2192 rep)
Mar 17, 2025, 02:47 PM
Last activity: Mar 18, 2025, 08:21 AM
Last activity: Mar 18, 2025, 08:21 AM