创建索引如何帮助解决 NOLOCK 问题?

var*_*ble -1 sql-server nolock

链接: https: //www.brentozar.com/archive/2018/10/using-nolock-heres-how-youll-get-the-wrong-query-results/

\n

文章提到了使用NOLOCK的一些问题:

\n
    \n
  • 您可以看到行两次
  • \n
  • 您可以完全跳过行
  • \n
  • 可以看到从未提交的数据
  • \n
  • 您的查询可能会因错误而彻底失败,\xe2\x80\x9c 由于数据移动而无法使用 nolock 继续扫描\xe2\x80\x9d
  • \n
\n

然后修复被提到为:

\n
\n

在表上创建索引(在此特定示例中任何单字段索引都可以正常工作,为 SQL Server 提供要扫描的表的较窄副本\n)

\n
\n

创建索引如何帮助解决 NOLOCK 问题?

\n

Tib*_*szi 10

仅在表上创建任何非聚集索引并不能神奇地使所有 NOLOCK 问题消失。

不过,在这种特殊情况下,对于该特定查询,除 WebsiteUrl 列之外的任何列上的索引都会有所帮助。

为什么?

想一想 SQL Server 如何执行 COUNT(*)。“有多少行?”。您可以回答读取任何索引叶级别(过滤索引除外)并仅计算行数。即获取链表中的第一页,逐页统计每页上的行数。

例如,假设您在 Age 列上有一个非聚集索引。SQL Server找到链表中的第一页,按照链表计算表中的行数。该索引不受 UPDATE 语句的影响,因为 UPDATE 语句不会修改 Age 列。

但是,布伦特的评论中缺少的是 WebsiteUrl 上的索引不会有帮助。这是因为我们正在修改 UDPATE 中的该列,因此我们再次成为 SELECT 语句期间数据移动的受害者。为了证明这一点,我创建了以下索引:

CREATE INDEX x ON dbo.Users(WebsiteUrl)
Run Code Online (Sandbox Code Playgroud)

并运行 UPDATE 和 SELECT,以下是结果(其中的一些行):

在此输入图像描述

  • 请重新阅读我的回复,答案就在那里:该索引没有被更新修改,该索引中没有数据被修改,因此索引是稳定的。这只适用于非聚集索引。而且,正如我所提到的,这不是一个通用的“修复”,它只是碰巧“修复”了这种特殊情况(COUNT(*))。 (5认同)