현재 환경에서 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 에서 실행 (잡음은 있지만 아마도 같은 결과)
- 힌트 대신 ISOLATION LEVEL 설정 (동일 결과)
- 테이블에서 잠금 에스컬레이션 해제 (같은 결과)
- 실제 쿼리 계획에서 스캔의 실제 실행 시간 검사 (동일한 결과)
- 힌트 다시 컴파일 (동일한 결과)
- 읽기 전용 파일 그룹 (동일한 결과)
가장 유망한 탐색은 휴지통 변수를 제거하고 결과 없음 쿼리를 사용하는 것입니다. 처음에는 NOLOCK이 약간 빠르지 만 데모에 상사에게 보여 주었을 때 NOLOCK은 느려졌습니다.
변수 할당으로 스캔 속도를 늦추는 NOLOCK은 무엇입니까?