質問

私は、できるだけ効率的にクエリを作成したいレポート開発者です。私は私に言ったDBAと仕事をしていました - 私は常に生産サーバーのレポートを扱っていたので、私は信じています - NOLOCK すべてのクエリで。

今、私は禁止されているDBAと仕事をしています NOLOCK いずれの状況でも - 私のレポートが(いくつかのテーブルにかなりのインデックスが不足しているため)、複製とシステムの更新を停止している場合でも。私の意見では、この場合、a NOLOCK 良いことでしょう。

私のSQLトレーニングのほとんどは、非常に異なる意見を持つさまざまなDBAに登場しているため、これをさまざまなDBAに尋ねたいと思いました。

役に立ちましたか?

解決

レポートがブロックされている場合、DBAが正しいことを更新します:絶対に使用してはいけません NOLOCK. 。そこにその事実がまさにその事実です それは 紛争は、あなたがいるならば、明確な兆候です します 誤ったレポートが表示されるDirty Readsを使用してください。

私の意見では、常により良い選択肢があります NOLOCK:

  • あなたの生産テーブルは有効であるだけで読み取られていて、決して変更されませんか?データベースの読み取り専用にマークしてください!
  • テーブルスキャンはロックの競合を引き起こしますか?テーブルを適切にインデックスすると、利点は複数あります。
  • 適切にインデックスを作成する方法を変更できません/わかりませんか?使用する スナップショット分離.
  • スナップショットを使用するためにアプリを変更できませんか?オンにする コミットされたスナップショットを読んでください!
  • 行バージョンの影響を測定し、パフォーマンスに影響を与える証拠がありますか?データにインデックスを付けることはできませんか?そして、あなたは大丈夫です 誤ったレポート?その後、少なくとも自分に好意を与えて使用します SET TRANSACTION ISOLATION LEVEL, 、クエリのヒントではありません。すべてのクエリを変更する代わりに、後で分離レベルを修正する方が簡単になります。

他のヒント

そうではありません いつも 悪い。

もちろん、それはあなたがあなたが何度も値を読むなどの現象を許可するだけでなく、あなたが抱えていない値を読み取ることができます(それは論理的に存在することはありません)。

そのような異常に遭遇しないことを保証する唯一の分離レベルは、シリアル化可能/スナップショットです。スキャンがこの行に到達する前に行を移動した場合(キーアップデートのため)、再現可能な読み取り値を見逃す可能性があります。

これらの問題は、下に発生する可能性が高くなります nolock ただし、デフォルトでは、この分離レベルで使用するため 読み取る64ページ以上があると推定した場合、割り当て順序付けされたスキャン. 。インデックスキーアップデートのために行間で行が移動すると発生する問題のカテゴリと同様に、これらの割り当て順序付けされたスキャンは、ページスプリットの問題に対しても脆弱です(新しく割り当てられたページがポイントよりもファイルの早い段階である場合、行を見逃す可能性があります。すでにスキャンされたページがファイルの後のページに分割されている場合、すでにスキャンまたは2回読み取ります)。

少なくとも単純な(シングルテーブル)クエリの場合、これらのスキャンの使用を思いとどまらせて、キー順序付けられたスキャンを取得することができます nolock 単に追加するだけです ORDER BY index_key クエリに Ordered のプロパティ IndexScantrue.

しかし、レポートアプリケーションが絶対に正確な数値を必要とせず、そのような矛盾のより大きな確率に耐えることができる場合、それは受け入れられるかもしれません。

しかし、確かに、魔法の「ターボ」ボタンであることを期待して、すべてのクエリでそれをチャックするべきではありません。また、その分離レベルで異常な結果に遭遇する可能性が高い場合、または結果がまったくない(「データの動きのためにノロックでスキャンを続けることはできませんでした」) nolock さらに悪化する可能性があります.

あなたの顧客はレポートで一貫性のない結果を容認しますか?答えがノーの場合は、nolockを使用しないでください - 並行性の下で結果を間違えることができます。いくつかの例を書きました ここ, ここ, 、 と ここ. 。これらの例は、読み取りと繰り返しの読み取りの下で一貫性のない出力を示していますが、それらを微調整して、Nolockでも誤った結果を得ることができます。

私が作成したレポートのほとんどは、現在のデータで実行されません。ほとんどの顧客が実行中のレポートは昨日のデータです。それが事実だったら、あなたの答えは変わりますか?

その場合、もう1つの可能なオプションがあります。
制作データベースでクエリを実行し、ロックをいじっている代わりに NOLOCK, 、本番データベースのコピーからレポートを実行できます。

あなたはそれをそのようにセットアップすることができます 毎晩バックアップから自動的に復元されます.
どうやらあなたのレポートは顧客のサイトのサーバーで実行されているようですので、これを設定することがあなたにとって実行可能なソリューションであるかどうかはわかりません。
(しかし、再び...とにかくバックアップが必要なので、必要なのはそれらを復元するためのサーバースペースだけです)

私は社内開発者なので、サーバーとデータベースを完全に制御できるので、これは私にとって簡単です。

昨日以上のデータのみが必要なレポートについては、少なくともこれを行うことができます。いくつかのレポートは、本番データベースにとどまる必要があるかもしれませんが、少なくともロードの一部を別のデータベース(またはさらに良い、別のサーバー)に移動する必要があります。

私も同じ状況を職場で持っています:
ほぼすべてのレポートのものに対して、このような制作データベースコピーを使用していますが、今日のデータが必要なクエリがいくつかあります。

ライセンス: CC-BY-SA帰属
所属していません dba.stackexchange
scroll top