SQL Server NOLOCK и объединяет

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

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

Ответ 1

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

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

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

Ответ 2

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