Я боюсь проти НОЛОКУ в моєму поточному оточенні. Один з аргументів, які я чув, - це те, що накладні витрати блокування сповільнюють запит. Отже, я створив тест, щоб побачити, наскільки може бути цей наклад.
Я виявив, що 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, що сповільнює сканування зі змінним призначенням?