【问题标题】:Index scan on SQL update statementSQL 更新语句的索引扫描
【发布时间】:2015-01-26 22:57:59
【问题描述】:

我有以下 SQL 语句,我想让它更有效率。查看执行计划,我可以看到@newWebcastEvents 上有一个聚集索引扫描。有没有办法可以把它变成一个寻求?或者有什么其他方法可以让下面的工作更有效率吗?

declare @newWebcastEvents table (
    webcastEventId int not null primary key clustered (webcastEventId) with (ignore_dup_key=off)
)

insert into @newWebcastEvents
select wel.WebcastEventId
from WebcastChannelWebcastEventLink wel with (nolock)
where wel.WebcastChannelId = 1178

Update WebcastEvent
set WebcastEventTitle = LEFT(WebcastEventTitle, CHARINDEX('(CLONE)',WebcastEventTitle,0) - 2)
where
WebcastEvent.WebcastEventId in (select webcastEventId from @newWebcastEvents)

【问题讨论】:

  • 它只是一个临时表,而不仅仅是主键。该表很小,最多只有 15 行。我正在更新的表可能有数千行。
  • WebcastChannelWebcastEventLink 中大约有 5000 行,该表大约有 15 行被选入@newWebcastEvents

标签: sql performance tsql indexing


【解决方案1】:

@newWebcastEvents 表变量仅包含唯一的单列,并且您在此 where 子句中要求该表变量的 所有行

where
   WebcastEvent.WebcastEventId in (select webcastEventId from @newWebcastEvents)

因此,在此聚集索引上执行 seek 通常是毫无意义的 - SQL Server 查询优化器无论如何都需要该表变量的所有列、所有行...... . 所以它选择索引扫描。

无论如何,我认为这不是性能问题。

如果您需要从大表中选择非常少量的行(int 列和 15 行 --> 寻找绝对没有意义,在一次扫描中读取这 15 个 int 值并完成会快得多有了它...

更新:不确定它在性能方面是否有任何区别,但我个人通常更喜欢使用 joins 而不是子选择来“连接”两个表:

UPDATE we
SET we.WebcastEventTitle = LEFT(we.WebcastEventTitle, CHARINDEX('(CLONE)', we.WebcastEventTitle, 0) - 2)
FROM dbo.WebcastEvent we
INNER JOIN @newWebcastEvents nwe ON we.WebcastEventId = nwe.webcastEventId

【讨论】:

  • 哦,好的,干杯。这个查询不需要很长时间运行,我只是想提高我的知识。我被告知要尝试避免在我的查询中进行索引扫描,所以只是试图纠正这一点,但上述内容是有道理的。你会说这是做我想做的最有效的方法吗?
  • @user3284707:是的,我还建议尽量避免索引扫描 - 在真正的大表上,例如100'000 行或更多行 - 如果您只需要从这些表中提取少数行(占总数的 1-2%)。但是 15 个 int 值 - 那是 60 字节,比单个页面的 8K 少了很多 - 而且 SQL Server 总是基于页面加载......
  • 非常感谢,如果这被认为是最佳实践,我会考虑将我的更新更改为此。感谢您的帮助。
猜你喜欢
  • 2012-01-31
  • 2011-06-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-26
  • 2020-06-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多