Estou lutando contra o NOLOCK no meu ambiente atual. Um argumento que ouvi é que a sobrecarga do bloqueio diminui a velocidade de uma consulta. Então, criei um teste para ver o quanto essa sobrecarga pode ser.
Descobri que o NOLOCK realmente diminui a velocidade da digitalização.
No começo, fiquei encantado, mas agora estou confuso. Meu teste é inválido de alguma forma? O NOLOCK não deveria realmente permitir uma verificação um pouco mais rápida? O que está acontecendo aqui?
Aqui está o meu script:
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())
O que eu tentei que não funcionou:
- Executando em servidores diferentes (mesmos resultados, os servidores eram 2016-SP1 e 2016-SP2, ambos silenciosos)
- Executando no dbfiddle.uk em versões diferentes (barulhento, mas provavelmente os mesmos resultados)
- DEFINIR NÍVEL DE ISOLAMENTO em vez de dicas (mesmos resultados)
- Desativando a escalação de bloqueio na tabela (mesmos resultados)
- Examinando o tempo real de execução da verificação no plano de consulta real (mesmos resultados)
- Dica de recompilação (mesmos resultados)
- Grupo de arquivos somente leitura (mesmos resultados)
A exploração mais promissora vem da remoção da variável do lixo e do uso de uma consulta sem resultados. Inicialmente, isso mostrou o NOLOCK como um pouco mais rápido, mas quando mostrei a demonstração para o meu chefe, o NOLOCK voltou a ser mais lento.
O que há no NOLOCK que retarda uma varredura com atribuição de variável?