如果我在 Stack Overflow2010 数据库中有以下查询
UPDATE dbo.Posts
SET Title =
CASE
WHEN CreationDate <= '2008-01-01T00:00:00'
THEN 'A'
ELSE 'B'
END
FROM dbo.Posts
简要的STATISTICS IO
输出如下
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)
执行计划如下
如果我创建一个表来存储我想要在比较中使用的值:
CREATE TABLE dbo.Canary
(
TheDate DATETIME
)
INSERT INTO dbo.Canary VALUES ('2008-01-01T00:00:00')
然后如果我将查询更改如下:
UPDATE dbo.Posts
SET Title =
CASE
WHEN CreationDate <= Canary.TheDate
THEN 'A'
ELSE 'B'
END
FROM dbo.Posts
CROSS JOIN dbo.Canary
STATISTICS IO 输出是
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)
执行计划如下
我们可以看到逻辑读取的数量大幅增加,从 445k 增加到 16m。我花了一些时间才在执行计划中找到这个问题的根源,但我使用实际 I/O 统计信息/实际逻辑读取属性对其进行了跟踪,并可以看到额外的读取是在聚集索引更新运算符上,我还可以看到此运算符现在在所有执行中都有一个实际行数值,而第一个查询的计划没有。
这里发生了什么?聚集索引更新中发生了什么,导致读取次数增加?
如果要使用这种“配置表中的值”模式,我知道查询应该使用一个变量,但是,这是一个来自供应商应用程序的查询,所以我想反馈查询以这种方式编写后发生的情况。