web-dev-qa-db-ja.com

SQL Server NOLOCKおよび結合

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

私の質問は結合を使用している場合、それらにも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)ヒントを指定する必要がありますか?

136
DanP

READ UNCOMMITTED引数ではなく、元の質問についてのみ説明します。

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

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

143
codeConcussion

クエリ内の各NOLOCKに対して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)クエリヒントを使用して、インデックス付きビューへのアクセスを防ぐことができます。

16
Jagmag

どちらでもない。分離レベルを READ UNCOMMITTED に設定します。これは、個々のロックヒントを与えるよりも常に優れています。または、さらに良いことに、 consistency のような詳細に関心がある場合は、 snapshot isolation を使用します。

9
Remus Rusanu