Je me bats contre NOLOCK dans mon environnement actuel. Un argument que j'ai entendu est que la surcharge du verrouillage ralentit une requête. J'ai donc conçu un test pour voir à quel point ces frais généraux pourraient être.
J'ai découvert que NOLOCK ralentit réellement mon scan.
Au début, j'étais ravi, mais maintenant je suis juste confus. Mon test est-il invalide d'une manière ou d'une autre? NOLOCK ne devrait-il pas permettre un scan légèrement plus rapide? Qu'est-ce qu'il se passe ici?
Voici mon 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())
Ce que j'ai essayé n'a pas fonctionné:
- Fonctionnant sur différents serveurs (mêmes résultats, les serveurs étaient 2016-SP1 et 2016-SP2, tous deux silencieux)
- Fonctionnant sur dbfiddle.uk sur différentes versions (bruyant, mais probablement les mêmes résultats)
- DÉFINIR LE NIVEAU D'ISOLEMENT au lieu des indices (mêmes résultats)
- Désactiver l'escalade des verrous sur la table (mêmes résultats)
- Examen du temps d'exécution réel de l'analyse dans le plan de requête réel (mêmes résultats)
- Astuce de recompilation (mêmes résultats)
- Groupe de fichiers en lecture seule (mêmes résultats)
L'exploration la plus prometteuse vient de la suppression de la variable corbeille et de l'utilisation d'une requête sans résultat. Au début, cela montrait NOLOCK comme légèrement plus rapide, mais quand j'ai montré la démo à mon patron, NOLOCK était redevenu plus lent.
Qu'est-ce que NOLOCK ralentit un scan avec affectation de variable?