私はクエリをできる限り効率的にしたいレポート開発者です。以前はDBAと一緒に仕事をしていて、本番サーバーのレポートを常に扱っていたので、すべてのクエリでNOLOCK
を使用するように言われました。
現在、私は、どのような状況でもNOLOCK
を禁止しているDBAと協力しています-私のレポートが(いくつかのテーブルのインデックスがかなり不足しているため)レプリケーションとシステムの更新を停止している場合でも。私の意見では、この場合、NOLOCK
は良いことです。
私のSQLトレーニングのほとんどは非常に異なる意見を持つさまざまなDBAに来たので、私はこれをさまざまなDBAに尋ねたかったのです。
レポートがDBAの正しい更新をブロックしている場合は、NOLOCK
を絶対に使用しないでください。 areの競合があるという事実自体が、が不正なレポートを取得するダーティリードを使用します。
私の意見では、NOLOCK
よりも優れた代替手段が常にあります。
SET TRANSACTION ISOLATION LEVEL
、クエリヒントではありません。すべてのクエリを変更するよりも、後で分離レベルを修正する方が簡単です。それは常に悪いことではありません。
もちろん、コミットされていない値(ロールバックされる可能性があり、したがって論理的に存在することはない)を読み取ることができ、値を複数回読み取る、またはまったく読み取らないなどの現象を許可することもできます。
このような異常が発生しないことを保証する唯一の分離レベルは、シリアライズ可能/スナップショットです。スキャンがこの行に到達する前に行が(キーの更新により)移動されると、反復可能な読み取り値の下で値が失われる可能性があります。
これらの問題は、nolock
で発生する可能性が高くなりますが、デフォルトでは、この分離レベルでは、読み取るページが64ページを超えると推定される場合、割り当て順スキャン が使用されるためです 。インデックスキーの更新が原因で行がページ間を移動するときに発生する問題のカテゴリと同様に、これらの割り当て順スキャンは、ページ分割の問題に対しても脆弱です(新しく割り当てられたページがファイル内でポイントよりも前にある場合、行が失われる可能性があります)既にスキャンされているか、既にスキャンされたページがファイル内の後続のページに分割されている場合は2回読み取られます)。
少なくとも単純な(単一のテーブル)クエリの場合、これらのスキャンの使用を思いとどまらせ、nolock
のOrdered
プロパティがIndexScan
になるようにクエリにORDER BY index_key
を追加するだけで、true
でキー順スキャンを取得できます。
しかし、レポート作成アプリケーションが完全に正確な数値を必要とせず、そのような不整合の高い可能性を許容できる場合、それは受け入れられる可能性があります。
しかし、魔法の「ターボ」ボタンであることを期待して、すべてのクエリでそれをチャックするべきではありません。その分離レベルで異常な結果が発生する可能性が高いか、まったく結果がない(「データ移動のためNOLOCKでスキャンを続行できませんでした」エラー)だけでなく、nolock
でパフォーマンスが発生する場合もありますはるかに悪化する可能性があります 。
私が作成するレポートのほとんどは、現在のデータでは実行されません。ほとんどの顧客が実行しているレポートは、昨日のデータです。その場合、答えは変わりますか?
その場合は、もう1つの選択肢があります。
本番データベースでクエリを実行してロックとNOLOCK
をいじる代わりに、本番データベースのコピーからレポートを実行できます。
毎晩バックアップから自動的に復元されます のように設定できます。
お客様のサイトのサーバーでレポートが実行されているようです。そのため、これを設定することが現実的な解決策になるかどうかはわかりません。
(ただし、繰り返しますが、とにかくバックアップが必要なので、復元に必要なサーバースペースがあれば十分です)
私は社内の開発者なので、サーバーとデータベースを完全に制御できるので、これは私にとっては簡単です。
これは、少なくとも昨日以前のデータのみを必要とするレポートに対して行うことができます。たぶん、一部のレポートは本番データベースに留まる必要がありますが、少なくとも一部の負荷を別のデータベース(またはさらに良いのは別のサーバー)に移動します。
私も仕事で同じ状況にあります:
ほぼすべてのレポートにこのような本番データベースのコピーを使用していますが、今日のデータを必要とするクエリがいくつかあります。