在打开 READ_COMMITTED_SNAPSHOT 的 SQL 服务器数据库上使用 WITH (NOLOCK) 是否可以提高性能?

Do I get any performance gain by using WITH (NOLOCK) on SQL Server database where READ_COMMITTED_SNAPSHOT is switched on?

我在 Microsoft SQL Server 2014 上有一个数据库,其中 READ_COMMITTED_SNAPSHOT 属性 已打开。我知道这意味着读取不会被写入阻塞,因为读取不会发出共享锁并且这是干净的读取。

我的问题是:在这种情况下,在 select 语句中使用 WITH (NOLOCK) 是否可以提高性能?就我而言,我不介意这会是脏读。

我试图找到此信息,但只找到了使用 WITH (NOLOCK) 和打开 READ_COMMITTED_SNAPSHOT 之间的比较。但是我已经戴上了。

理论上应该有改进,因为虽然查询在任何一种情况下都不会阻塞,但在 READ_COMMITTED_SNAPSHOT 情况下,仍然需要与锁关联的簿记,以便数据库知道何时需要 create/retain/cleanup 快照 rows/pages.

然而,与所有性能问题一样,您应该尝试一下,看看实践中是否存在差异,如果存在,它对您的用例是否重要。

谢谢大家的建议。

我们进行了一些测试,使用 WITH (NOLOCK) 似乎在性能上仍然存在差异,即使 READ_COMMITTED_SNAPSHOT 已打开。

测试用例是:大量更新事务中的某些 table(更新 3M 记录),同时从另一个连接中读取相同的 table。在此读取语句中使用或不使用 WITH (NOLOCK) 会产生巨大的性能差异(使用 WITH (NOLOCK) 更快)。

但在 Azure DB 中要小心!我们有 NOLOCK(从 on-premise 天开始),发现在某些情况下他们发送了 Azure DB berzerk:即查询(使用 NOLOCK)以前 运行 很好,在 Azure DB 上,运行 非常缓慢 直到 我们删除了 NOLOCK。这与所有建议和所有文档、所有理论等都背道而驰。但是 Azure DB 是一个奇怪的野兽,理论仍然经常在实践中不成立。