175

背景:我想运行一个性能关键的查询,我不关心脏读。

我的问题是;如果我正在使用连接,我是否也必须在这些连接上指定 NOLOCK 提示?

例如; 是:

SELECT * FROM table1 a WITH (NOLOCK)
INNER JOIN table2 b WITH (NOLOCK) ON a.ID = b.ID

相当于:

SELECT * FROM table1 a WITH (NOLOCK)
INNER JOIN table2 b ON a.ID = b.ID

或者我是否需要(NOLOCK)在连接上指定提示以确保我没有锁定连接表?

4

3 回答 3

189

我不会解决这个READ UNCOMMITTED论点,只是你原来的问题。

是的,您需要WITH(NOLOCK)对每个表进行联接。不,您的查询不一样。

试试这个练习。开始一个事务并在 table1 和 table2 中插入一行。不要提交或回滚事务。此时您的第一个查询将成功返回并包含未提交的行;您的第二个查询不会返回,因为 table2 没有WITH(NOLOCK)提示。

于 2010-09-24T15:09:41.223 回答
19

我很确定您需要在查询中NOLOCK为每个指定。JOIN但我的经验仅限于 SQL Server 2005。

当我查找 MSDN 只是为了确认时,我找不到任何确定的东西。下面的陈述似乎让我觉得,对于 2008 年,您上面的两个陈述是等效的,但对于 2005 年情况并非如此:

[SQL Server 2008 R2]

所有锁定提示都传播到查询计划访问的所有表和视图,包括视图中引用的表和视图。此外,SQL Server 执行相应的锁一致性检查。

[SQL 服务器 2005]

在 SQL Server 2005 中,所有锁定提示都传播到视图中引用的所有表和视图。此外,SQL Server 执行相应的锁一致性检查。

此外,请注意 - 这适用于 2005 年和 2008 年:

如果查询计划未访问表,则忽略表提示。这可能是由于优化器选择根本不访问该表,或者是因为访问的是索引视图。在后一种情况下,可以通过使用OPTION (EXPAND VIEWS)查询提示来防止访问索引视图。

于 2010-09-24T02:04:39.963 回答
11

两者都不。您将隔离级别设置READ UNCOMMITTED为总是比给出单独的锁定提示更好。或者,更好的是,如果您关心一致性等细节,请使用快照隔离

于 2010-09-24T02:25:04.407 回答