Я борюсь против NOLOCK в моей нынешней обстановке. Один аргумент, который я услышал, заключается в том, что накладные расходы на блокировку замедляют запрос. Итак, я разработал тест, чтобы увидеть, насколько эти затраты могут быть.
Я обнаружил, что NOLOCK на самом деле замедляет сканирование.
Сначала я был в восторге, но теперь я просто растерялся. Мой тест недействителен как-то? Разве NOLOCK не должен позволять немного более быстрое сканирование? Что тут происходит?
Вот мой сценарий:
USE TestDB
GO
--Create a five-million row table
DROP TABLE IF EXISTS dbo.JustAnotherTable
GO
CREATE TABLE dbo.JustAnotherTable (
ID INT IDENTITY PRIMARY KEY,
notID CHAR(5) NOT NULL )
INSERT dbo.JustAnotherTable
SELECT TOP 5000000 'datas'
FROM sys.all_objects a1
CROSS JOIN sys.all_objects a2
CROSS JOIN sys.all_objects a3
/********************************************/
-----Testing. Run each multiple times--------
/********************************************/
--How fast is a plain select? (I get about 587ms)
DECLARE @trash CHAR(5), @dt DATETIME = SYSDATETIME()
SELECT @trash = notID --trash variable prevents any slowdown from returning data to SSMS
FROM dbo.JustAnotherTable
ORDER BY ID
OPTION (MAXDOP 1)
SELECT DATEDIFF(MILLISECOND,@dt,SYSDATETIME())
----------------------------------------------
--Now how fast is it with NOLOCK? About 640ms for me
DECLARE @trash CHAR(5), @dt DATETIME = SYSDATETIME()
SELECT @trash = notID
FROM dbo.JustAnotherTable (NOLOCK)
ORDER BY ID --would be an allocation order scan without this, breaking the comparison
OPTION (MAXDOP 1)
SELECT DATEDIFF(MILLISECOND,@dt,SYSDATETIME())
То, что я пробовал, не сработало:
- Работа на разных серверах (одинаковые результаты, серверы были 2016-SP1 и 2016-SP2, оба тихие)
- Запуск на dbfiddle.uk на разных версиях (шумный, но, вероятно, тот же результат)
- УСТАНОВИТЬ УРОВЕНЬ ИЗОЛЯЦИИ вместо подсказок (те же результаты)
- Отключение повышения блокировки на столе (те же результаты)
- Изучение фактического времени выполнения сканирования в фактическом плане запроса (те же результаты)
- Перекомпилировать подсказку (те же результаты)
- Файловая группа только для чтения (те же результаты)
Наиболее многообещающее исследование происходит от удаления переменной корзины и использования запроса без результатов. Первоначально это показывало NOLOCK немного быстрее, но когда я показал демонстрацию своему боссу, NOLOCK снова стал медленнее.
Что такого в NOLOCK, который замедляет сканирование с присвоением переменных?