Walczę z NOLOCK w moim obecnym środowisku. Jednym z argumentów, jaki słyszałem, jest to, że narzut związany z blokowaniem spowalnia zapytanie. Dlatego opracowałem test, aby zobaczyć, ile to może kosztować.
Odkryłem, że NOLOCK faktycznie spowalnia mój skan.
Na początku byłem zachwycony, ale teraz jestem tylko zdezorientowany. Czy mój test jest jakoś nieważny? Czy NOLOCK nie powinien pozwolić na nieco szybsze skanowanie? Co tu się dzieje?
Oto mój skrypt:
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())
To, co próbowałem, nie zadziałało:
- Działa na różnych serwerach (te same wyniki, serwery były 2016-SP1 i 2016-SP2, oba ciche)
- Działa na dbfiddle.uk w różnych wersjach (głośne, ale prawdopodobnie takie same wyniki)
- USTAW POZIOM IZOLACJI zamiast podpowiedzi (te same wyniki)
- Wyłączanie eskalacji blokady na stole (te same wyniki)
- Badanie rzeczywistego czasu wykonania skanu w rzeczywistym planie zapytań (te same wyniki)
- Wskazówka dotycząca ponownej kompilacji (te same wyniki)
- Grupa plików tylko do odczytu (te same wyniki)
Najbardziej obiecujące badanie polega na usunięciu zmiennej kosza i zastosowaniu zapytania „brak wyników”. Początkowo pokazało to NOLOCK jako nieco szybszy, ale kiedy pokazałem demo mojemu szefowi, NOLOCK powrócił do spowolnienia.
Co takiego jest w NOLOCK, który spowalnia skanowanie z przypisywaniem zmiennych?