IDENTITY_INSERT ONが一度に1つのテーブルでしか許可されないのはなぜですか?


20

これは、というケースですIDENTITY_INSERTが一度に一つのデータベーステーブルにONにのみ設定することができますが、なぜですか?IDENTITY列はグローバルに一意ではないため、複数のテーブルに同時にIDを挿入することによって引き起こされる危険な状況は考えられません(少なくともIDENTITY INSERTを使用するよりも危険ではありません)。

IDENTITY INSERTはめったに使用されるべきではありませんが、ハードリミットの理由は何ですか?


1
たぶん抑止力はあるので、めったに使用されないのですか?
レムスルサヌ

@RemusRusanuそれは、私が考えていたようなことです。複数のテーブルで誤ってIIをONのままにしないでください。
ベンブロッカ

@Ben複数のテーブルで誤ってオンにするのは、1つのテーブルで誤ってオンにするのよりも悪いのはなぜですか?どちらも同じ種類の問題につながる可能性があります。私はあなたの質問に本当に興味があり、抑止力が答えだとは思いません。そうでなければ、エンジンにはもっと多くの制限があるでしょう。しかし、これを頻繁に行う必要があると感じた場合、おそらく疑わしい点があることに同意します。
アーロンバートランド

SQL Serverが予約されたキーワードを使用して列に名前を付けるように他の悪い習慣の多くを可能にするので、私は、わからない抑止力についてのいずれかQ.で暗示よう@AaronBertrandそれは、ありません(あなたは] [使用しない場合でも、時々 !)
ベンBrockaを

@Benの権利は、必ずしもあなたのためではなく、質問に出くわした読者のためのものでした。
アーロンバートランド

回答:


12

難しくすることだと思います。いつでもそのままにしておくことができるのであれば、なぜIDフィールドさえ持っているのでしょうか?

ただし、実際にはいくつかの制限があります。

  • その接続でのみ持続します
  • 接続ごとに1つのテーブルでのみ設定可能

接続に関連した制限に基づいて、私はそれが主にそうであると思うので、それは決して誤ってオンのままにされません。

誰かがあなたのテーブルのいずれかでID挿入をオンにした場合、あなたは気づかず、(通常)無効な挿入が実行され、IDフィールドの整合性が壊れたと想像してください。

制約または一意のインデックスが設定されていない場合、IDフィールドには重複した値が含まれることがあることに注意してください...


1
+1重複についてのあなたの最後の点は、多くを見逃していると思います。人々は、それを設定したIDENTITY場合にもユニークな制約になると考えています。もちろん、反論するのは非常に簡単です。
アーロンバートランド

@AaronBertrandしかし、重複IDのリスクは、IDENTITY INSERTがオンになっているどのテーブルでもまったく同じです。なぜハード制限なのでしょうか?接続に対してのみ持続するという事実は、予防策としてはるかに理にかなっていると思います。
ベンブロッカ

重複IDの問題がハード制限の理由であることを示唆していませんでした。
アーロンバートランド

6

私の推測では、これは実装による制限でした。複数のテーブルでこの設定を許可すると、パフォーマンスが低下する可能性がありました。

これはセッションパラメータであるため、設定を単一のテーブルで有効にできるということは、単純なフラグと、サーバー側のセッションに保存するテーブルのオブジェクトIDであることを意味します。たぶん、これは単一の整数です:IDENTITY_INSERTがアクティブでない場合は0、テーブルのdatabaseid + objectidのコーディング。

セッション内の複数のテーブルにパラメータを設定できるようにすると、サーバーはそのようなオブジェクトの動的リストを保存し、すべての挿入ステートメントをチェックします。セッションが1,000個のテーブルのパラメーターをアクティブにすることを想像してください。

  1. これは、サーバーがセッション変数に1000個のアイテムを割り当てたことを意味します
  2. これは、サーバーがこのセッションのすべての挿入ステートメントについて1000項目のリストを確認する必要があることも意味します。

また、identity_insertをonに設定すると、サーバーでパフォーマンス全体のパフォーマンスが低下する可能性があります。sybaseには、「ID書き込みセットファクター」があり、テーブルのIDカウンターの値を一度だけ保存することができました(値はメモリに保持され、たまにサーバーに書き込まれますシャットダウン )。SQL Serverは同じコードに基づいているため、おそらく同等の最適化が行われますが、テーブルでidentity_insertをアクティブにすると、サーバーがすべての挿入のID値を保存するように制約される可能性があります。したがって、1つのセッションが1つのテーブルの挿入でパフォーマンスヒットした場合、これはおそらく受け入れられますが、サーバー上のすべてのauto_incrementテーブルでperfヒットできる場合はそうではありません。


+1おそらくここにいくつかの真実。INSERTセッションでは一度に1つしか実行できないため、ギャップサイズの引数は購入しませんIDENTITY。また、1000万のハードコードされた値を簡単に挿入できます。
アーロンバートランド

ギャップサイズは、クラッシュの場合に発生するものに関連しています。sybaseでは、サーバーがクラッシュすると、最後のIDが失われる(メモリ内にあった)ため、ギャップを残して再起動します(IDバーニングセットファクターを参照)
Olivier S

したがって、SQL Serverでは、ID列を持つ1,000,000行を挿入しているときにエンジンがクラッシュした場合、またはSET IDENTITY_INSERT有効なときに1,000,000ハードコーディングされた値でID列をオーバーライドした場合に何か異なることが起こると示唆していますか?ギャップサイズが複数のテーブルに影響を与えることは、単一のテーブルに影響を与えることとは異なることを示唆しているだけです。
アーロンバートランド

私の推測-私はこれの絶対的な証拠を持っていません-テーブルのSET IDENTITY_INSERTは挿入ごとに自動インクリメントのディスクへの書き込みを強制するということです。根拠は、[挿入値は何もすることができるため、サーバは考えることができない「私はディスクに書き込む場合は[OK]を、唯一のすべての1000行と、クラッシュした場合には、私は安全に私が最後に保存された値1000を追加することができます」ということでしょう
オリビエS
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.