Sample Header Ad - 728x90

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