SQL Server NOLOCK и присоединяется

153

Справочная информация: у меня есть запрос, критичный к производительности, который я хотел бы выполнить, и меня не волнует грязное чтение.

Мой вопрос Если я использую соединения, нужно ли указывать подсказку 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)подсказку для объединения, чтобы убедиться, что я не блокирую объединенную таблицу?

DanP
источник

Ответы:

166

Я не буду рассматривать READ UNCOMMITTEDспор, только ваш оригинальный вопрос.

Да, вам нужно WITH(NOLOCK)на каждом столе объединения. Нет, ваши запросы не совпадают.

Попробуйте это упражнение. Начните транзакцию и вставьте строку в table1 и table2. Не совершайте и не отменяйте транзакцию. В этот момент ваш первый запрос будет успешно возвращен и будет содержать незавершенные строки; Ваш второй запрос не вернется, потому что на table2 нет WITH(NOLOCK)подсказки.

codeConcussion
источник
18

Я был почти уверен, что вам нужно указать 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)подсказки запроса.

Jagmag
источник
@ In Sane: Интересно ... спасибо за это ... Я предполагаю, что я не причинил вреда, включив его в JOINS, даже если это не совсем необходимо? Документация по NOLOCK довольно скудна, как вы уже упоминали; У меня были проблемы с поиском чего-либо убедительного.
ДанП
2
@ InSane: Откуда вы взяли эту информацию? Кажется, идет вразрез с принятым ответом.
Джей Салливан
1
@notfed - см. ссылку на technet technet.microsoft.com/en-us/library/ms187373(v=sql.105).aspx - вы можете изменить версию базы данных сверху, чтобы сравнить одну и ту же статью для разных версий БД
Jagmag
2
Текст 2005 года говорит о ВЗГЛЯДАХ. Так что если вы делаете «из myview с (nolock)», то это говорит о том, что nolock распространяется на все таблицы и представления, участвующие в myview (у вас может быть 10 объединений). Не уверен, что именно означает текст 2008 года, поскольку он добавляет «доступ к плану запросов» в дополнение к представлениям.
Thierry_S
9

Ни. Вы устанавливаете уровень изоляции, READ UNCOMMITTEDкоторый всегда лучше, чем давать индивидуальные подсказки блокировки. Или, что еще лучше, если вам важны такие детали, как согласованность , используйте изоляцию моментальных снимков .

Ремус Русану
источник
@Remus: я не уверен, что могу использовать READ UNCOMMITTED в моем случае, потому что я получаю доступ к соединению через NHibernate для выполнения специального необработанного вызова ADO.NET; это может быть указано в запросе inline или будет подчиняться уровню транзакции, присутствующему в транзакции NHibernate?
ДанП
Заверните вызов using (TransactionScope scope=new TransactionScope(..., TransactionOptions) {...}и установите IsolationLevelпараметры: msdn.microsoft.com/en-us/library/…
Remus Rusanu
@Remus: К сожалению, управление транзакциями осуществляется на гораздо более высоком уровне, чем этот, так что это тоже не вариант.
ДанП
Понимаю. Затем, чтобы ответить на ваш вопрос: NOLOCK - это табличная подсказка, и как таковая она применяется к набору строк, к которому добавляется (таблица, представление, TVF и т. Д.). Если у вас есть несколько наборов строк, соединенных в запросе, каждый из них должен иметь свою собственную подсказку NOLOCK.
Ремус Русану
2
Но вы рассматривали изоляцию снимка? ALTER DATABASE ... SET READ_COMMITTED_SNAPSHOT ON;, Результаты впечатляют, так как все обычные операции чтения с фиксацией превращаются в операции чтения снимков, без блокировки, но согласованные. Стоимость увеличенной tempdbнагрузки: msdn.microsoft.com/en-us/library/ms175492.aspx
Ремус Русану