2013-08-26 17 views
9

の任意の自動インクリメント私たちは、私は自動インクリメントの主キーとしてInvoiceIdフィールドを持つ以下の表持つSQL Server 2012のSP1のx64の(11.0.3000.0)SQL Serverの:主キー

を実行している:

CREATE TABLE Orders(
    InvoiceId   bigint   IDENTITY(1001,1) NOT FOR REPLICATION, 
    OrderId    varchar(8)  NOT NULL, 
    ... -- other fields removed for brevity 
    CONSTRAINT [PK_ORDERS] PRIMARY KEY CLUSTERED (InvoiceId) 
    ON [PRIMARY], 
) 

新しい行が挿入されているかのような単純なストアドプロシージャ次

SET XACT_ABORT ON 
SET NOCOUNT ON 

BEGIN TRANSACTION 
    INSERT INTO Orders(
      OrderId, 
      ... -- other fields removed for brevity 
     ) 
    VALUES (
      @orderId, 
      ... 
     )    

    SELECT @newRowId = SCOPE_IDENTITY() 
COMMIT TRANSACTION 

上記SPROCが新たに作成された行のIDを返す(Orders.InvoiceId)を発信者に送信する。

コードは完全に動作していました。[InvoiceId]が1001から始まり、連続した挿入ごとに1ずつ増加しています。

ユーザーが約130行を挿入しました。 [InvoiceId]は1130にあり、次の挿入時にその値はにジャンプしました!

data

私はちょうどここに何が起こったのように困惑しています:

は、ここでデータのスクリーンショットです。 auto-incが突然10,000ポイント近くをスキップしたのはなぜですか?

バーコードを生成するのに、[InvoiceId]の値を使用しています。そのため、値が特定の範囲、好ましくは連続した系列のままであることをお勧めします。

私はT-SQLのドキュメントを閲覧しましたが、私の問題に関連するものは見つかりませんでした。これはIDフィールドの通常の動作(任意の母集団)ですか?

UPDATE Marting & Aronのおかげで、私は回避策を見つけました。ここでは、マイクロソフトからofficial responseです:

SQL Server 2012のではIDプロパティの実装は、他の機能への投資に対応するために変更されて ました。 SQL Serverの以前のバージョンでは、ID生成の追跡は、生成された各ID値のトランザクションログレコードに依存していました。 SQL Server 2012では、バッチでID値を生成し、バッチの最大値である のみを記録します。これにより、 情報の量と頻度が削減され、トランザクションログに書き込まれ、挿入性が向上します。 スケーラビリティ。

あなたが利用可能な2つのオプションがありますSQL Serverの以前の バージョンと同じアイデンティティ生成セマンティクスが必要な場合:

は、このoを使用 トレースフラグ272•ログレコードが各 生成アイデンティティのために生成されるようになります値。アイデンティティ生成のパフォーマンスは、このトレースフラグをオンにすることによって影響される可能性があります( )。

この O NO CACHE 設定(http://msdn.microsoft.com/en-us/library/ff878091.aspx)で使用•シーケンス ジェネレータは、ログレコードが生成された各シーケンス 値のために生成されるようになります。 NO CACHEを使用すると、シーケンス値生成のパフォーマンスが になることがあります。

例:

CREATE SEQUENCE s1 AS INT START WITH 1 NO CACHE; 
CREATE TABLE t1 (Id INT PRIMARY KEY DEFAULT NEXT VALUE FOR s1, col INT NOT NULL); 
+5

'IDENTITY'は、連続した保証はありませんでしたが、それは突然サービスを再起動した後に大きなギャップを残してジャンプすることができます2012年の既知の問題があります。 –

+0

ありがとう@MartinSmith!私の場合、これは問題であるようです。アイデンティティの増分ジャンプの前にdbマシンをリブートしたことを覚えています!どうすればこの問題を回避できますか? – masroore

+1

連続性は保証されていませんが、遅い(ログに記録された)2008年の動作を得るために設定できるトレースフラグがあるか、キャッシュサイズが小さいシーケンスを使用することができます。 [ここでの説明](https://connect.microsoft.com/SQLServer/feedback/details/739013/failover-or-restart-results-in-reseed-of-identity)を参照してください。 –

答えて

2

更新Martingのおかげで& Aron、私は回避策を見つけました。

SQL Server 2012では、IDプロパティの実装が、他の機能への投資に対応するように変更されました。以前のバージョンのSQL Serverでは、ID生成のトラッキングは生成された各ID値のトランザクションログレコードに依存していました。 SQL Server 2012では、バッチでID値を生成し、バッチの最大値のみを記録します。これにより、トランザクションログに書き込まれる情報の量と頻度が削減され、挿入スケーラビリティが向上します。

あなたは、SQL Serverの以前のバージョンと同じID生成セマンティクスが必要な場合に利用できる2つのオプションがあります。

使用•トレースフラグ272このOログレコードが生成された各ID値のために生成されるようになりますが。アイデンティティ生成のパフォーマンスは、このトレースフラグをオンにすることによって影響を受ける可能性があります。

•NO CACHE設定(http://msdn.microsoft.com/en-us/library/ff878091.aspx)でシーケンスジェネレータを使用するo生成されたシーケンス値ごとにログレコードが生成されます。シーケンス値生成のパフォーマンスは、NO CACHEを使用することによって影響を受ける可能性があることに注意してください。

例:

CREATE SEQUENCE s1 AS INT START WITH 1 NO CACHE; 
CREATE TABLE t1 (Id INT PRIMARY KEY DEFAULT NEXT VALUE FOR s1, col INT NOT NULL); 
0

また、あなたはカウンターで専用のテーブルを持つことができます。 これは良いデザインパターンではありませんが、IDの仕組みを完全に制御できます。