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)підказку на приєднання, щоб переконатися, що я не блокую приєднану таблицю?

Відповіді:


166

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

Так, вам потрібно WITH(NOLOCK) на кожній таблиці з'єднання. Ні, ваші запити не однакові.

Спробуйте цю вправу. Почніть транзакцію та вставте рядок у table1 та table2. Поки не здійснюйте та не повертайте транзакцію У цей момент ваш перший запит успішно повернеться і включить незапущені рядки; ваш другий запит не повернеться, оскільки table2 не має WITH(NOLOCK)натяку на нього.


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)підказку запиту.


@ In Sane: Цікаво ... спасибі за це ... Я припускаю, що я не приношу шкоди, включаючи його до приєднання, навіть якщо це не зовсім необхідно? Документація на NOLOCK є досить рідкою, як ви вже згадували; У мене були проблеми знайти щось переконливе для себе.
DanP

2
@InSane: Звідки ви взяли цю інформацію? Здається, це суперечить прийнятій відповіді.
Джей Салліван

1
@notfed - см Technet посилання technet.microsoft.com/en-us/library/ms187373(v=sql.105).aspx - ви можете змінити версію бази даних на вершині , щоб порівняти ту ж статтю для різних версій БД
Jagmag

2
У тексті 2005 р. Йдеться про СМОТРІ. Тож якщо ви робите "з мого перегляду з (nolock)", то він говорить, що блокування поширюється на всі таблиці та перегляди, що беруть участь у моєму перегляді (у вас може бути 10 приєднань). Не впевнений, що саме означає текст 2008 року, оскільки він додає "доступ до плану запитів" на додаток до переглядів.
Thierry_S

9

Ні. Ви встановлюєте рівень ізоляції, READ UNCOMMITTEDякий завжди краще, ніж давати окремі підказки щодо блокування. Або ще краще, якщо вам цікаві деталі, такі як консистенція , використовуйте знімок ізоляції .


@Remus: Я не впевнений, що в моєму випадку я можу ЧИТАЙТЕ НЕЗАКОНОДЕНО, оскільки я отримую доступ до з'єднання через NHibernate для виконання спеціального необмеженого дзвінка ADO.NET; чи можна це вказати в запиті, чи він підпорядковується рівню транзакції, присутньому в транзакції NHibernate?
DanP

Увімкніть дзвінок using (TransactionScope scope=new TransactionScope(..., TransactionOptions) {...}і встановіть IsolationLevelпараметри: msdn.microsoft.com/en-us/library/…
Remus Rusanu

@Remus: На жаль, управління транзакціями опікується на набагато вищому рівні, ніж це, тому це теж не є варіантом.
DanP

Я бачу. Тоді, щоб відповісти на ваше запитання: NOLOCK - це натяк на таблицю , і як такий він застосовується до набору рядків, до яких додається (таблиця, перегляд, TVF тощо). Якщо у запиті об’єднано кілька наборів рядків, для кожного з них потрібен власний підказку NOLOCK.
Рем Русану

2
Але чи розглядали ви ізоляцію знімків? ALTER DATABASE ... SET READ_COMMITTED_SNAPSHOT ON;. Результати є вражаючими, оскільки всі звичайні читання, що здійснюються, перетворюються на зчитування знімків, блокування вільне, але послідовне. Вартість збільшується tempdbнавантаження: msdn.microsoft.com/en-us/library/ms175492.aspx
Ремус Русану
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.