背景:我有一个性能关键的查询,我想运行,我不关心脏读。
我的问题是;如果我正在使用连接,我是否必须在那些上指定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)
提示以确保我没有锁定已连接的表?
答案 0 :(得分:142)
我不会解决READ UNCOMMITTED
论证,只讨论原始问题。
是的,您需要在每个联接表上WITH(NOLOCK)
。不,您的查询不一样。
尝试这个练习。开始一个事务并在table1和table2中插入一行。不要提交或回滚事务。此时,您的第一个查询将成功返回并包含未提交的行;您的第二个查询将不会返回,因为table2上没有WITH(NOLOCK)
提示。
答案 1 :(得分:16)
我非常确定您需要为查询中的每个NOLOCK
指定JOIN
。但我的经验仅限于SQL Server 2005。
当我查询MSDN以确认时,我找不到任何确定的内容。以下陈述似乎让我想到,对于2008年,你上面的两个陈述是相同的,尽管2005年并非如此:
[SQL Server 2008 R2]
所有锁定提示都会传播到查询计划访问的所有表和视图,包括视图中引用的表和视图。此外,SQL Server还会执行相应的锁一致性检查。
[SQL Server 2005]
在SQL Server 2005中,所有锁定提示都会传播到视图中引用的所有表和视图。此外,SQL Server还会执行相应的锁一致性检查。
此外,请注意 - 这适用于2005年和2008年:
如果查询计划未访问表,则忽略表提示。这可能是由于优化器根本不选择访问表,或者是因为访问了索引视图。在后一种情况下,可以使用
OPTION (EXPAND VIEWS)
查询提示来阻止访问索引视图。
答案 2 :(得分:9)
都不是。您将隔离级别设置为READ UNCOMMITTED
,这总是比提供单独的锁定提示更好。或者,更好的是,如果您关心consistency等详细信息,请使用snapshot isolation。