167 votes

NOLOCK et jointures du serveur SQL

Contexte : Je souhaite exécuter une requête dont les performances sont critiques et je ne me soucie pas des lectures sales.

Ma question est la suivante : si j'utilise des jointures, dois-je également spécifier l'indice NOLOCK sur celles-ci ?

Par exemple, c'est :

SELECT * FROM table1 a WITH (NOLOCK)
INNER JOIN table2 b WITH (NOLOCK) ON a.ID = b.ID

Équivalent à :

SELECT * FROM table1 a WITH (NOLOCK)
INNER JOIN table2 b ON a.ID = b.ID

Ou devrai-je préciser le (NOLOCK) sur la jointure pour m'assurer que je ne verrouille pas la table jointe ?

180voto

codeConcussion Points 7250

Je ne vais pas aborder la READ UNCOMMITTED argument, juste votre question originale.

Oui, vous avez besoin WITH(NOLOCK) sur chaque table de la jointure. Non, vos requêtes ne sont pas les mêmes.

Essayez cet exercice. Commencez une transaction et insérez une ligne dans les tables 1 et 2. Ne commettez pas ou n'annulez pas encore la transaction. À ce stade, votre première requête sera renvoyée avec succès et inclura les lignes non validées ; votre deuxième requête ne sera pas renvoyée parce que la table2 n'a pas les données de l'élément WITH(NOLOCK) un conseil sur ce sujet.

0 votes

Je peux confirmer que c'est toujours le cas en utilisant SQL Server 2016.

19voto

InSane Points 7832

J'étais à peu près sûr que vous deviez spécifier l'adresse de l'utilisateur. NOLOCK pour chaque JOIN dans la requête. Mais mon expérience était limitée à SQL Server 2005.

Quand j'ai regardé sur MSDN juste pour confirmer, je n'ai rien trouvé de précis. Les déclarations ci-dessous semblent me faire penser que pour 2008, vos deux déclarations ci-dessus sont équivalentes alors que pour 2005 ce n'est pas le cas :

[SQL Server 2008 R2]

Toutes les indications de verrouillage sont propagées à toutes les tables et les vues qui sont accessibles par le plan de requête y compris les tables et les vues référencées dans une vue. De plus, le serveur SQL effectue les contrôles de cohérence des verrous correspondants.

[SQL Server 2005]

En SQL Server 2005, toutes les indications de verrouillage sont propagées à toutes les tables et vues qui sont référencées dans une vue. De plus, SQL Server effectue les contrôles de cohérence des verrous correspondants.

En outre, il convient de noter - et cela s'applique aussi bien à 2005 qu'à 2008 :

Les indices de la table sont ignorés si la table n'est pas accessible par le plan de requête. Cela peut être dû au fait que l'optimiseur a choisi de ne pas accéder à la table du tout, ou parce qu'une vue indexée est accédée à la place. Dans ce dernier cas, l'accès à une vue indexée peut être empêché en utilisant l'attribut OPTION (EXPAND VIEWS) indice de requête.

0 votes

@In Sane : Intéressant... merci pour cette information... Je suppose que je ne fais pas de mal en l'incluant dans les JOINS, même si ce n'est pas entièrement nécessaire ? La documentation sur NOLOCK est plutôt rare, comme vous l'avez mentionné ; j'ai moi-même eu du mal à trouver quelque chose de concluant.

2 votes

@InSane : D'où tenez-vous cette information ? Elle semble aller à l'encontre de la réponse admise.

1 votes

@notfed - lien technet de référence technet.microsoft.com/fr/us/library/ms187373(v=sql.105).aspx - vous pouvez changer la version de la base de données en haut pour comparer le même article pour différentes versions de la base de données

10voto

Remus Rusanu Points 159382

Ni l'un ni l'autre. Vous réglez le niveau d'isolement sur READ UNCOMMITTED ce qui est toujours mieux que de donner des indices de verrouillage individuels. Ou, mieux encore, si vous vous souciez de détails tels que cohérence utiliser isolation instantanée .

0 votes

@Remus : Je ne suis pas sûr de pouvoir utiliser READ UNCOMMITTED dans mon cas, car j'accède à la connexion via NHibernate pour effectuer un appel ADO.NET brut spécial ; cela peut-il être spécifié en ligne dans la requête, ou cela obéira-t-il au niveau de transaction présent sur la transaction NHibernate ?

0 votes

Enveloppez l'appel dans using (TransactionScope scope=new TransactionScope(..., TransactionOptions) {...} et définir les IsolationLevel sur les options : msdn.microsoft.com/fr/us/library/

0 votes

@Remus : Malheureusement, la gestion des transactions est prise en charge à un niveau beaucoup plus élevé que cela, donc ce n'est pas non plus une option.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X