Эффект подсказки NOLOCK в операторах SELECT

199

Я предполагаю, что реальный вопрос:

Если меня не волнует грязное чтение, добавление подсказки with (NOLOCK) к оператору SELECT повлияет на производительность:

  1. текущий оператор SELECT
  2. другие транзакции против данной таблицы

Пример:

Select * 
from aTable with (NOLOCK)
Боб Пробст
источник
3
Эти ответы SO и DBA немного яснее относительно того, что на самом деле происходит.
Trisped

Ответы:

289

1) Да , выбор с NOLOCKзавершится быстрее, чем обычный выбор.

2) Да , выбор с помощью NOLOCKпозволит другим запросам к выполненной таблице завершаться быстрее, чем обычный выбор.

С чего бы это?

NOLOCKобычно (в зависимости от вашего механизма БД) означает, что вы предоставляете мне свои данные, и мне все равно, в каком состоянии они находятся, и не беспокойтесь о том, чтобы держать их неподвижно, пока вы читаете их. Это одновременно быстрее, менее ресурсоемко и очень и очень опасно.

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

У вас действительно нет возможности узнать, в каком состоянии находятся данные.

Если вы пытаетесь получить такие данные, как количество строк или другие сводные данные, где допустимый предел погрешности приемлем, то NOLOCKэто хороший способ повысить производительность этих запросов и избежать их негативного влияния на производительность базы данных.

Всегда используйте NOLOCKподсказку с большой осторожностью и относитесь к любым данным, которые она возвращает, с подозрением.

tom.dietrich
источник
Спасибо. Это то, что я предполагал, но коллега спросил меня об этом, и мое первоначальное исследование заставило меня задаться вопросом. В документации SQLServer 2005 говорится, что NOLOCK является схемой блокировки по умолчанию для всех операторов select! Тогда я бы предположил, что мои подсказки будут излишними в ...
Боб Пробст
2
... 2005 и не имеют никакого эффекта. Мы запускаем 2000 прямо сейчас (спасибо нашему поставщику), и в документации нет подобных заявлений.
Боб Пробст
4
Твой друг должен прочитать документацию. Подсказка к таблице (Transact-SQL) msdn.microsoft.com/en-us/library/ms187373(SQL.90).aspx
администрация
9
Примечание: если бы это было правдой, это был бы абсолютный хаос.
Питтсбург DBA
1
Пункты 1 и 2 должны быть ограничены 1) «... когда на столе ожидают действия вставки / обновления / удаления ». и 2) «... позволит вставлять / обновлять / удалять запросы к ...». Я бы (личное предпочтение) изменил бы экземпляры «быстрее» на «раньше», поскольку разница ожидает завершения другого процесса.
Trisped
61

NOLOCK делает большинство операторов SELECT быстрее из-за отсутствия общих блокировок. Кроме того, отсутствие выдачи блокировок означает, что ваш SELECT не будет мешать писателям.

NOLOCK функционально эквивалентен уровню изоляции READ UNCOMMITTED. Основным отличием является то, что вы можете использовать NOLOCK для одних таблиц, но не для других, если хотите. Если вы планируете использовать NOLOCK для всех таблиц в сложном запросе, то использовать SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED проще, поскольку вам не нужно применять подсказку к каждой таблице.

Вот информация обо всех уровнях изоляции в вашем распоряжении, а также табличные подсказки.

УСТАНОВИТЬ УРОВЕНЬ ИЗОЛЯЦИИ

Таблица Подсказка (Transact-SQL)

Питтсбург DBA
источник
2
Я согласен, но не полностью; важно отметить, что подсказка NO LOCK / READ UNCOMMITTED на самом деле не повышает скорость запроса, а делает его более быстрым, поскольку ему не нужно ждать завершения предыдущих запросов. Так что на самом деле, запрос выглядит быстрее, а не быстрее (я думаю).
Möoz
1
@ BorhanMooz Ну, есть сбережения от того, что нет необходимости запрашивать блокировки у менеджера блокировок. Даже если другие запросы не ожидают, это требует затрат и затрат памяти.
Питтсбург DBA
1
Я обсуждал это с некоторыми из моих коллег по работе. Насколько я понимаю, запрос, использующий подсказку WITH (NOLOCK), по-прежнему требует достижения блокировки Shama -Shared ( mssqltips.com/sqlservertip/2470/… ).
Möoz
1
Да, но не тысячи общих блокировок на страницах или экстентах. Блокировка схемы - это ОДНА блокировка, а не ТЫСЯЧИ. Если мы хотим быть педантичными, мы можем продолжать обсуждать это, но да, накладные расходы будут минимальными. Экономия значительная. Посчитай
Питтсбург DBA
6

Это будет быстрее, потому что не нужно ждать блокировки

StingyJack
источник
Насколько быстрее? Не могли бы вы предоставить какие-либо цифры улучшения скорости?
Евгений Торика
5
«Сколько» зависит от того, что вы конкретно делаете со своими данными, и от того, сколько времени вам обычно приходится ждать получения блокировки.
StingyJack
Единственный правильный тест - это тот, который вы создаете и запускаете сами. Все, что вам говорят, так же хорошо, как «чек по почте». Я много раз доказывал, что многие мифы и предположения ошибочны, выполняя собственные тесты.
TravisO
^ @TravisO - полностью правильно. Я выполнял NOLOCK медленнее несколько раз. Не совсем уверен, почему, но я использую это при устранении неполадок, и я не хочу негативно (чрезмерно) влиять на производство
StingyJack
2
  • Ответ « Да», если запрос выполняется несколько раз за раз, потому что каждой транзакции не нужно ждать завершения других. Однако, если запрос выполняется один раз, тогда ответ - Нет.

  • Да . Существует значительная вероятность того, что осторожное использование WITH (NOLOCK) ускорит вашу базу данных в целом. Это означает, что другим транзакциям не придется ждать завершения этого оператора SELECT, но, с другой стороны, другие транзакции будут замедляться, поскольку теперь они делят время обработки с новой транзакцией.

Будьте осторожны, чтобы использовать толькоWITH (NOLOCK) в инструкциях SELECT для таблиц с кластеризованным индексом.

WITH (NOLOCK) часто используется как магический способ ускорить транзакции чтения базы данных.

Результирующий набор может содержать строки, которые еще не были зафиксированы и которые впоследствии часто откатываются.

Если WITH (NOLOCK) применяется к таблице, имеющей некластеризованный индекс, то индексы строк могут быть изменены другими транзакциями, поскольку данные строк передаются в таблицу результатов. Это означает, что в наборе результатов могут отсутствовать строки или отображаться одна и та же строка несколько раз.

READ COMMITTED добавляет дополнительную проблему, когда данные повреждены в одном столбце, когда несколько пользователей одновременно изменяют одну и ту же ячейку.

Чудотворец
источник