SQL Server NOLOCKと結合


153

背景:実行したいパフォーマンスが重要なクエリがあり、ダーティリードは気にしません。

私の質問です。結合を使用している場合、それらにもNOLOCKヒントを指定する必要がありますか?

例えば; です:

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

に相当:

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

または(NOLOCK)、結合されたテーブルをロックしないようにするために、結合のヒントを指定する必要がありますか?

回答:


166

私はREAD UNCOMMITTED議論に対処するのではなく、あなたの元の質問だけを扱います。

はい、WITH(NOLOCK)結合の各テーブルで必要です。いいえ、クエリは同じではありません。

この演習を試してください。トランザクションを開始し、table1とtable2に行を挿入します。まだトランザクションをコミットまたはロールバックしないでください。この時点で、最初のクエリは正常に返され、コミットされていない行が含まれます。table2にはWITH(NOLOCK)ヒントがないため、2番目のクエリは返されません。


18

クエリでNOLOCKfor each を指定する必要があると確信していJOINました。しかし、私の経験はSQL Server 2005に限定されていました。

確認のためにMSDNを調べたところ、明確なものは見つかりませんでした。以下のステートメントは、2008年の場合、上記の2つのステートメントは同等であると私に思わせるようですが、2005年の場合はそうではありません。

[SQL Server 2008 R2]

すべてのロックヒントは、ビューで参照されるテーブルとビューを含め、クエリプランによってアクセスされるすべてのテーブルとビューに伝達されます。また、SQL Serverは対応するロック整合性チェックを実行します。

[SQL Server 2005]

SQL Server 2005では、すべてのロックヒントが、ビューで参照されるすべてのテーブルとビューに伝達されます。また、SQL Serverは対応するロック整合性チェックを実行します。

さらに、注意してください-これは2005年と2008年の両方に当てはまります。

クエリプランがテーブルにアクセスしない場合、テーブルヒントは無視されます。これは、オプティマイザがテーブルにまったくアクセスしないことを選択したか、代わりにインデックス付きビューにアクセスしたことが原因である可能性があります。後者の場合、OPTION (EXPAND VIEWS)クエリヒントを使用すると、インデックス付きビューへのアクセスを防ぐことができます。


@In Sane:興味深い...そのおかげで...それが完全に必要でなくても、JOINSに含めても害はないと私は思いますか?あなたが言及したように、NOLOCKに関するドキュメントはかなりまばらです。自分で決定的なものを見つけるのに苦労しました。
DanP

2
@InSane:どこからこの情報を入手しましたか?受け入れられた答えに反するようです。
Jay Sullivan

1
@notfed-technetリンクを参照してくださいtechnet.microsoft.com/en-us/library/ms187373(v=sql.105).aspx-データベースのバージョンを変更して、同じ記事を異なるバージョンのデータベースで比較することができます
Jagmag

2
2005年のテキストはVIEWSについて語っています。したがって、「from myview with(nolock)」を実行すると、nolockがmyviewに関係するすべてのテーブルとビューに伝達されることになります(そこに10の結合を含めることができます)。ビューに加えて「クエリプランによってアクセスされる」が追加されるため、2008年のテキストが正確に何を意味するのかわかりません。
Thierry_S 2016年

9

どちらでもない。READ UNCOMMITTED個別のロックヒントを与えるよりも常に良い分離レベルを設定します。または、一貫性などの詳細に関心がある場合スナップショット分離を使用してください。


@Remus:NHibernateを介して接続にアクセスし、特別な生のADO.NET呼び出しを実行しているため、自分のケースでREAD UNCOMMITTEDを使用できるかどうかわかりません。これはクエリでインラインで指定できますか、それともNHibernateトランザクションに存在するトランザクションレベルに従いますか?
DanP

ラップでの通話using (TransactionScope scope=new TransactionScope(..., TransactionOptions) {...}や設定IsolationLevelオプションに:msdn.microsoft.com/en-us/library/...
レムスRusanu

@Remus:残念ながら、トランザクション管理はこれよりはるかに高いレベルで処理されるため、これもオプションではありません。
DanP

そうですか。次に、あなたの質問に答えてください:NOLOCKはテーブルヒントなので、追加される行セット(テーブル、ビュー、TVFなど)に適用されます。クエリに複数の行セットが結合されている場合、それぞれに独自のNOLOCKヒントが必要です。
Remus Rusanu 2010

2
しかし、スナップショット分離を検討しましたか?ALTER DATABASE ... SET READ_COMMITTED_SNAPSHOT ON;。通常の読み取りコミットされた読み取りはすべてスナップショット読み取りになり、ロックフリーで一貫性があるため、結果は素晴らしいものになります。コストはtempdb負荷の増加です:msdn.microsoft.com/en-us/library/ms175492.aspx
Remus Rusanu
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.