我有一个问题:
UPDATE TOP(100000) pv
SET pv.intUrlId = urls.intUrlId
FROM [schema1].[Urls] urls WITH(NOLOCK)
INNER JOIN [schema2].[PageViews] pv WITH(NOLOCK)
ON pv.urlId = urls.id
AND pv.intUrlId IS NULL
此查询中使用的每个列都是索引,urls.id是PRIMARY KEY。但查询仍然太慢。尝试提高性能我已经重建了pv_urlId_IDX索引,将pv.intUrlId列添加为“包含列”。我的推理如下:查询需要搜索pv_urlId_IDX索引来执行JOIN和下一个pv_intUrlId_IDX来确定NULL记录。如果我将pv.intUrlId的值添加到pv_urlId_IDX索引,则将“就地”执行第二条件的测试,并且将不执行搜索第二索引。不幸的是,我没有注意到任何性能提升。
我还阅读了SQL Server文档,并且每次都提到包含范围的非键列。所以我的问题是:索引中的关键列是否有意义,如果我们能够从这样的解决方案中获益,那么它是否正确。
答案 0 :(得分:1)
要记住的事项很少:
execution plan
了吗? 100000
行,请注意,当optimizer
Index Seek
更改为Table Scan
时,UPDATE
会更改{ x%表中的行。NULL
会因为您的更新而变慢(从urls.intUrlId
到{{1}})答案 1 :(得分:1)
如果没有实际执行计划和CREATE TABLE
语句,请参阅以下内容:
不需要删除Urls (id) INCLUDE (intUrlId)
。它可能是此Urls
语句的最佳索引(在UPDATE
上)。它是否对聚集索引进行了大大小小的改进取决于表的宽度,但它肯定不会更糟,优化器会选择它。
删除WITH (NOLOCK)
。网上有很多链接,很多关于StackOverflow本身的链接解释了为什么它一般都是不好的做法。
考虑(并测试)在PageViews (intUrlId, urlId)
上添加索引或在PageViews (urlId) WHERE intUrlId IS NULL
上添加部分索引。两者都将提高查找需要更新的行的效率。虽然索引更新语句所需的时间也会增加(还有一个要更新的索引),但它们有两种选择。
)
UPDATE
语句拆分为较小的块。您可以使用TOP (1000)
运行100个语句,而不是运行的100K更新和测试效率。要回答你的问题,不,PageViews (urlId) INCLUDES (intUrlId)
上的索引不会非常有用。因为它为表添加了一个索引(UPDATE
也必须更新),并且因为它的选择性低于上述两个建议索引中的任何索引。
答案 2 :(得分:0)
每列的索引都是问题
上禁用索引[schema2].[PageViews].[intUrlId]
执行更新 然后重建该索引
更新使用该索引检查null 我宁愿处理列扫描而不是维护索引 如果在多次更新后更新速度变慢,那么很可能问题是索引变得支离破碎。
尝试更大的顶部,甚至可能没有顶部。
删除(nolock)并让优化器决定
disable index on [schema2].[PageViews].[intUrlId]
UPDATE top (100000) pv
SET pv.intUrlId = urls.intUrlId
FROM [schema1].[Urls] urls WITH (NOLOCK)
INNER JOIN [schema2].[PageViews] pv
ON pv.urlId = urls.id
AND pv.intUrlId IS NULL
rebuild index