背景:実行したいパフォーマンスクリティカルなクエリがあり、ダーティリードを気にしません。
私の質問は結合を使用している場合、それらにも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)
ヒントを指定する必要がありますか?
READ UNCOMMITTED
引数ではなく、元の質問についてのみ説明します。
はい、結合の各テーブルでWITH(NOLOCK)
が必要です。いいえ、クエリは同じではありません。
この演習を試してください。トランザクションを開始し、table1とtable2に行を挿入します。トランザクションをまだコミットまたはロールバックしないでください。この時点で、最初のクエリは正常に返され、コミットされていない行が含まれます。 table2にはWITH(NOLOCK)
ヒントがないため、2番目のクエリは返されません。
クエリ内の各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)
クエリヒントを使用して、インデックス付きビューへのアクセスを防ぐことができます。
どちらでもない。分離レベルを READ UNCOMMITTED
に設定します。これは、個々のロックヒントを与えるよりも常に優れています。または、さらに良いことに、 consistency のような詳細に関心がある場合は、 snapshot isolation を使用します。