Effet de l'indice NOLOCK dans les instructions SELECT

199

Je suppose que la vraie question est:

Si je ne me soucie pas des lectures incorrectes , l'ajout de l' indicateur with (NOLOCK) à une instruction SELECT affectera les performances de:

  1. l'instruction SELECT en cours
  2. autres transactions par rapport au tableau donné

Exemple:

Select * 
from aTable with (NOLOCK)
Bob Probst
la source
3
Ces réponses SO et DBA sont un peu plus claires sur ce qui se passe réellement.
Trispé le

Réponses:

289

1) Oui , une sélection avec NOLOCKse terminera plus rapidement qu'une sélection normale.

2) Oui , une sélection avec NOLOCKpermettra à d'autres requêtes sur la table effectuée de se terminer plus rapidement qu'une sélection normale.

Pourquoi serait-ce?

NOLOCKgénéralement (en fonction de votre moteur de base de données) signifie me donner vos données, et je me fiche de l'état dans lequel elles se trouvent, et ne vous embêtez pas à les garder immobiles pendant que vous les lisez. C'est à la fois plus rapide, moins gourmand en ressources et très très dangereux.

Vous devez être averti de ne jamais effectuer de mise à jour ou d'exécuter quoi que ce soit de critique sur le système, ou lorsqu'une exactitude absolue est requise en utilisant des données provenant d'une NOLOCKlecture. Il est absolument possible que ces données contiennent des lignes qui ont été supprimées lors de l'exécution de la requête ou qui ont été supprimées dans d'autres sessions qui n'ont pas encore été finalisées. Il est possible que ces données incluent des lignes qui ont été partiellement mises à jour. Il est possible que ces données contiennent des enregistrements qui violent les contraintes de clé étrangère. Il est possible que ces données excluent les lignes qui ont été ajoutées à la table mais qui n'ont pas encore été validées.

Vous n'avez vraiment aucun moyen de savoir quel est l'état des données.

Si vous essayez d'obtenir des choses comme un nombre de lignes ou d'autres données récapitulatives où une certaine marge d'erreur est acceptable, NOLOCKc'est un bon moyen d'augmenter les performances de ces requêtes et d'éviter qu'elles aient un impact négatif sur les performances de la base de données.

Utilisez toujours cet NOLOCKindice avec une grande prudence et traitez toutes les données qu'il renvoie de manière suspecte.

tom.dietrich
la source
Merci. C'est ce que j'ai supposé mais j'ai été interrogé à ce sujet par un collègue et mes premières recherches m'ont fait me remettre en question. La documentation de SQLServer 2005 indique qu'avec NOLOCK est le schéma de verrouillage par défaut pour toutes les instructions select! Je suppose alors que mes indices seraient redondants dans ...
Bob Probst
2
... 2005 et sans effet. Nous exécutons 2000 en ce moment (grâce à notre fournisseur) et il n'y a pas de déclaration similaire dans la documentation.
Bob Probst
4
Votre ami doit lire la documentation. Conseil de table (Transact-SQL) msdn.microsoft.com/en-us/library/ms187373(SQL.90).aspx
Pittsburgh DBA
9
Note latérale: si cela était vrai, ce serait un chaos absolu.
Pittsburgh DBA
1
Les points 1 et 2 doivent être limités à 1) "... lorsqu'une action d'insertion / mise à jour / suppression est en attente sur la table ." et 2) "... permettra d' insérer / mettre à jour / supprimer des requêtes contre ...". Je voudrais (préférence personnelle) changer les instances de "plus vite" en "plus tôt" car la différence attend la fin d'un autre processus.
Trisped
61

NOLOCK accélère la plupart des instructions SELECT, en raison du manque de verrous partagés. De plus, l'absence de délivrance des verrous signifie que les écrivains ne seront pas gênés par votre SELECT.

NOLOCK est fonctionnellement équivalent à un niveau d'isolement de READ UNCOMMITTED. La principale différence est que vous pouvez utiliser NOLOCK sur certaines tables mais pas sur d'autres, si vous le souhaitez. Si vous prévoyez d'utiliser NOLOCK sur toutes les tables d'une requête complexe, il est plus facile d'utiliser SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED, car vous n'avez pas à appliquer l'indicateur à chaque table.

Voici des informations sur tous les niveaux d'isolement à votre disposition, ainsi que des conseils de tableau.

DÉFINIR LE NIVEAU D'ISOLEMENT DE TRANSACTION

Conseil de table (Transact-SQL)

Pittsburgh DBA
la source
2
Je suis d'accord, mais pas complètement; il est important de souligner qu'un indice NO LOCK / READ UNCOMMITTED n'améliore pas réellement la vitesse de la requête, mais le rend plus rapide car il n'a pas à attendre la fin des requêtes précédentes. Donc, vraiment, la requête semble plus rapide, plutôt que EST plus rapide (je pense).
Möoz
1
@BorhanMooz Eh bien, il y a des économies à ne pas avoir à demander de verrous au gestionnaire de verrouillage. Même s'il n'y a aucune autre requête en attente, cela a un coût et une surcharge de mémoire.
Pittsburgh DBA
1
J'en discutais avec certains de mes collègues de travail. Si je comprends bien, une requête utilisant un indice WITH (NOLOCK) nécessite toujours un verrouillage partagé par schéma ( mssqltips.com/sqlservertip/2470/… ).
Möoz
1
Oui, mais pas des milliers de verrous partagés sur des pages ou des extensions. Un verrou de schéma est UN verrou, pas des MILLIERS. Si nous voulons être pédants, nous pouvons continuer à en débattre, mais oui, il y aura une quantité minimale de frais généraux de verrouillage. Les économies sont importantes. Faites le calcul à ce sujet: msdn.microsoft.com/en-us/library/aa337559(v=sql.100).aspx
Pittsburgh DBA
6

Ce sera plus rapide car il n'a pas à attendre les verrous

StingyJack
la source
Combien plus rapide? Pourriez-vous fournir des chiffres d'amélioration de la vitesse?
Eugeniu Torica
5
"Combien" dépend de ce que vous faites spécifiquement avec vos données et du temps que vous devez généralement attendre pour une acquisition de verrou.
StingyJack
La seule référence correcte est celle que vous créez et exécutez vous-même. Ce que tout le monde vous dit est aussi bon que "le chèque est par la poste". J'ai prouvé à maintes reprises que de nombreux mythes et hypothèses étaient erronés en exécutant mes propres tests de performance.
TravisO
^ @TravisO - est tout à fait correct. J'ai fait exécuter NOLOCK plus lentement plusieurs fois. Je ne sais pas vraiment pourquoi, mais je l'utilise lors du dépannage et je ne veux pas (trop) affecter négativement la production
StingyJack
2
  • La réponse est Oui si la requête est exécutée plusieurs fois à la fois, car chaque transaction n'aura pas besoin d'attendre la fin des autres. Cependant, si la requête est exécutée une seule fois, la réponse est Non.

  • Oui . Il y a une forte probabilité qu'une utilisation prudente de WITH (NOLOCK) accélère globalement votre base de données. Cela signifie que d'autres transactions n'auront pas à attendre la fin de cette instruction SELECT, mais d'un autre côté, d'autres transactions ralentiront car elles partagent maintenant leur temps de traitement avec une nouvelle transaction.

Veillez à utiliser uniquementWITH (NOLOCK) dans les instructions SELECT sur les tables qui ont un index cluster.

WITH (NOLOCK) est souvent exploité comme un moyen magique pour accélérer les transactions de lecture de base de données.

Le jeu de résultats peut contenir des lignes qui n'ont pas encore été validées, qui sont souvent annulées ultérieurement.

Si WITH (NOLOCK) est appliqué à une table qui a un index non clusterisé, les index de ligne peuvent être modifiés par d'autres transactions pendant que les données de ligne sont diffusées dans la table de résultats. Cela signifie que le jeu de résultats peut manquer de lignes ou afficher plusieurs fois la même ligne.

READ COMMITTED ajoute un problème supplémentaire où les données sont corrompues dans une seule colonne où plusieurs utilisateurs changent la même cellule simultanément.

WonderWorker
la source