SELECTステートメントでのNOLOCKヒントの影響


199

本当の質問は次のとおりだと思います:

ダーティリードを気にしない場合、SELECTステートメントにwith(NOLOCK)ヒントを追加する、次のパフォーマンスに影響します。

  1. 現在のSELECTステートメント
  2. 指定されたテーブルに対する他のトランザクション

例:

Select * 
from aTable with (NOLOCK)

3
これらのSODBAの回答は、実際に何が起こっているかについて少し明確です。
2016年

回答:


289

1)はい、選択NOLOCK速く、通常の選択よりも完了します。

2)はい、あります。選択をNOLOCK使用すると、影響を受けるテーブルに対する他のクエリが通常の選択よりも速く完了します。

これはなぜでしょうか?

NOLOCK通常(DBエンジンによって異なります)はデータを提供することを意味します。データがどのような状態にあるかは気にしません。また、データを読み取っている間も気にしないでください。一度に速く、リソースをあまり消費せず、非常に危険です。

システムクリティカルな更新、またはNOLOCK読み取りから発生したデータを使用して絶対的な正確さが要求される場合は、絶対に更新を行わないでください。このデータには、クエリの実行中に削除された行、またはまだ確定されていない他のセッションで削除された行が含まれている可能性があります。このデータには、部分的に更新された行が含まれている可能性があります。このデータには、外部キーの制約に違反するレコードが含まれている可能性があります。このデータから、テーブルに追加されたがまだコミットされていない行が除外される可能性があります。

データの状態を知る方法はありません。

行数やその他の要約データなど、ある程度の誤差が許容できるものを取得しようとしている場合NOLOCKは、これらのクエリのパフォーマンスを向上させ、データベースのパフォーマンスに悪影響を与えないようにするための良い方法です。

NOLOCKヒントは常に細心の注意を払って使用し、返されたデータは疑わしく処理してください。


ありがとう。これは私が想定していたことですが、同僚から質問されましたが、私の最初の調査で自分自身に疑問が生じました。SQLServer 2005のドキュメントでは、NOLOCKはすべての選択ステートメントのデフォルトのロックスキームであると記載されています。私のヒントは次のように冗長になると思います...
Bob Probst

2
... 2005年、影響はありません。現在、2000を実行しています(ベンダのおかげです)。ドキュメントには同様のステートメントはありません。
Bob Probst、

4
友達はドキュメントを読む必要があります。テーブルヒント(Transact-SQL)msdn.microsoft.com/en-us/library/ms187373
ピッツバーグDBA

9
補足:これが真実なら、それは完全な混乱です。
ピッツバーグDBA、

1
ポイント1および2は1)に制限する必要があります。「... 挿入/更新/削除アクションがテーブルで保留中の場合」および2) "...は...に対する挿入/更新/削除クエリを許可します。"。私は(個人的な好みで) "速い"のインスタンスを "早い"に変更します。違いは別のプロセスが完了するのを待っているからです。
2016年

61

共有ロックがないため、NOLOCKを指定すると、ほとんどのSELECTステートメントが高速になります。また、ロックが発行されないことは、ライターがSELECTによって妨害されないことを意味します。

NOLOCKは、機能的にはREAD UNCOMMITTEDの分離レベルと同等です。主な違いは、選択した場合、一部のテーブルではNOLOCKを使用できるが、他のテーブルでは使用できないことです。複雑なクエリのすべてのテーブルでNOLOCKを使用する場合は、すべてのテーブルにヒントを適用する必要がないため、SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTEDを使用する方が簡単です。

これは、自由に使用できるすべての分離レベルと、テーブルのヒントに関する情報です。

トランザクション分離レベルを設定する

テーブルヒント(Transact-SQL)


2
私は同意しますが、完全ではありません。NO LOCK / READ UNCOMMITTEDヒントは実際にはクエリの速度を向上させませんが、以前のクエリが完了するのを待つ必要がないため、より高速に見えることを指摘することが重要です。つまり、実際には、クエリの方がISEMSよりも高速である(私は思う)。
Möoz

1
@BorhanMoozまあ、ロックマネージャからロックを要求する必要がないことから節約があります。待機中の他のクエリがない場合でも、これにはコストとメモリのオーバーヘッドがあります。
ピッツバーグDBA

1
私はこれについて同僚と話し合っていました。私が理解しているように、WITH(NOLOCK)ヒントを使用するクエリでは、スキーマ共有ロックを取得する必要があります(mssqltips.com/sqlservertip/2470/…)。
Möoz

1
はい。ただし、ページまたはエクステントに対する何千もの共有ロックはありません。スキーマロックは1つのロックであり、数千ではありません。知識を深めたい場合は、これについて引き続き議論できますが、はい、ロックのオーバーヘッドは最小限になります。節約は重要です。これについて計算してください
ピッツバーグDBA


6

ロックを待つ必要がないため、より高速になります。


どれくらい速く?速度向上の数値を教えてください。
Eugeniu Torica

5
「どのくらい」は、データを使用して具体的に何をしているのか、およびロックの獲得を通常待つ必要がある時間に依存します。
StingyJack 2010

正しいベンチマークは、自分で作成して実行したものだけです。誰もがあなたに言うことは、「小切手は郵便にある」と同じくらい良いです。私は自分のベンチマークを実行することにより、多くの神話と仮定が間違っていることを何度も証明しました。
TravisO 2013

^ @TravisO-完全に正しい。NOLOCKの実行を数回遅くしました。理由は完全には
わかり

2
  • 各トランザクションは他のトランザクションが完了するのを待つ必要がないため、クエリが一度に複数回実行される場合、答えは「はい」です。ただし、クエリが1回で実行されると、答えは「いいえ」になります。

  • はい。WITH(NOLOCK)を注意深く使用すると、データベース全体の速度が上がる可能性がかなりあります。つまり、他のトランザクションはこのSELECTステートメントの終了を待つ必要はありませんが、その一方で、他のトランザクションは新しいトランザクションと処理時間を共有しているため、速度が低下します。

のみに注意してくださいWITH (NOLOCK)クラスタ化インデックスを持つテーブルのSELECTステートメントで使用するように。

WITH(NOLOCK)は、データベースの読み取りトランザクションを高速化する魔法の方法としてよく利用されます。

結果セットには、まだコミットされていない、後でロールバックされることが多い行を含めることができます。

WITH(NOLOCK)が非クラスター化インデックスを持つテーブルに適用される場合、行データが結果テーブルにストリーミングされるときに、他のトランザクションによって行インデックスが変更される可能性があります。これは、結果セットが行を欠落するか、同じ行を複数回表示する可能性があることを意味します。

READ COMMITTEDは、複数のユーザーが同じセルを同時に変更する単一の列内でデータが破損するという追加の問題を追加します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.