2011-01-25 5 views
1

さまざまな類似の質問がありましたが、あまりにも特定のDBを参照するか、未ソートデータを想定していました。次の使用されていないインデックス、汎用SQLでの順序付き挿入

可能であれば、SQLは移植可能でなければなりません。問題のインデックス列は、タイムスタンプを含むクラスタ化されたPKです。

タイムスタンプは、以前に挿入された値より大きい時間の99%です。ただし、まれにしか小さくても、既存の値と衝突することもあります。

私は現在、新しい値を挿入するには、このコードを使用しています:行が使用されていない、まだ

IF NOT EXISTS (select * from Foo where Timestamp = @ts) BEGIN 
    INSERT INTO Foo ([Timestamp]) VALUES (@ts); 
END 
ELSE BEGIN 
    INSERT INTO Foo ([Timestamp]) VALUES (
    (SELECT Max (t1.Timestamp) - 1 
    FROM Foo t1 
    WHERE Timestamp < @ts 
    AND NOT EXISTS (select * from Foo t2 where t2.Timestamp = t1.Timestamp - 1)) 
    ); 
END; 

場合、単に挿入します。そうでない場合は、EXISTS小切手を使用して、最も小さな空き行を見つけます。

私はデータベースに関しては初心者ですので、より良い方法があるかどうかはわかりません。私は、コードをよりシンプルに、より速く(1秒あたり約100-1000回の挿入)、または別のアプローチを全く使用するためのアイデアはいつでも開いています。

あなたのコメントをお寄せいただきありがとうございます。

私の場合の性質について説明する:タイムスタンプはデータをソートするために使用された唯一の値ですが、マイナーな不一致は無視できます。 FKの関係はありません。

しかし、私は自分のアプローチに欠陥があり、最初に提示されたアイデアを使用する理由を上回ることに同意します。私が正しく理解していれば、デザインを修正する簡単な方法は、定期的に自動インクリメントされたPK列を既知の(および名前を変更した)タイムスタンプ列と組み合わせてクラスタ化することです。

パフォーマンスPOVからは、これが最初のアプローチよりも悪化する可能性はありません。また、コードを多く簡略化します。

+1

私はあなたがseriosly間違った道にいると思います。まず第一に、あなたのタイムスタンプがどう違うのでしょうか?同時に2つのことが起こる場合、タイムスタンプは同じでなければなりません。第二に、PK(クラスタ化されているかどうか)に現実の価値を使用することは一般的に推奨されていません。オートインクリメントIDを使用し、タイムスタンプをそのまま保存してください。 (タイムスタンプフィールドにインデックスを使用することを検討することがあります) –

+1

タイムスタンプがデータの適切なプライマリキーであることを確認してください。時にはそれが重複することができれば、おそらくそうではありません。そうであれば、なぜその質問に答えるのに役立つかもしれないのか。または、これは基本的にアイデンティティーの問題です(つまり、タイムスタンプの違いを使って2つのレコードの違いを伝えることができます - 重複していると思われる場合はほとんど間違っていると思います)か、効率的なデータ取得の問題ですか?後者の場合、別のプライマリキーを選択してインデックスを片面更新の方に変更すると、よりうまくいく可能性があります。 – dataduck

答えて

3

あなたのPK値が一意であることが保証できない場合、それは良いPK候補ではありません。特にタイムスタンプであれば、ゴールドマン・サックスは高周波取引プログラムがインサートの衝突を引き起こし、1マイクロ秒前に挿入される可能性があると確信しています。システムがその取引のタイムスタンプを撃退するからです。

タイムスタンプの一意性を保証できないため、衝突の問題を処理するプレーンジェーンの自動インクリメントint/bigint列を使用することをお勧めします。必要に応じて、タイムスタンプフィールドをソートして素敵なストレートタイムラインを得ることができます。

3

代理アイデンティティ/オートナンバー/シーケンスキーを追加すると、プライマリキーは(timestamp、newkey)になります。

この方法では、あなたは上記のコードでロックの粒度と同時実行のヒントをいじる必要があると思います、コード

上記のコードを実行するには

せずに行の順序と一意性を維持する、またはTRY/CATCH to retry with the alternate value (SQL Server).これは、移植性を除去します。しかし、重い負荷の下では、代替値がすでに存在する可能性があるため、再試行を続ける必要があります。

4

このメソッドは災害のための処方箋です。最初の場所では、インサートがうまくいかないときにユーザーの煩わしさを引き起こす競合状態が発生します。さらに悪いことに、その値を外部キーとして使用している別のテーブルに追加する場合、すべてのトランザクションが1つのトランザクションに含まれていない場合、間違ったレコードに子データを追加している可能性があります。

また、外部キー関係を正しく設定しておらず、子レコードのすべてを取得せずにレコードを削除した場合は、最も低い未使用値を探すことが、データの整合性を乱すレシピです。今度は新しいレコードに属していないレコードに参加しました。

この手動の方法には欠陥があり、信頼性がありません。すべての主要なデータベースには、自動生成された値を作成する方法があります。その代わりに、問題は解決されテストされています。

タイムスタンプBTWはSQLサーバー予約語であり、決してフィールド名として使用しないでください。

0

キーとしてのタイムスタンプ?本当に?行が更新されるたびに、そのタイムスタンプが変更されます。 SQL Serverのタイムスタンプデータ型は、バージョニング行で使用するためのものです。 SQL Serverのdatetimeデータ型に相当するANSI/ISO SQLタイムスタンプ—と同じではありません。

タイムスタンプ列の「ソート」とは、タイムスタンプで保証されるのは、行が挿入または更新されるたびに新しいタイムスタンプ値を取得し、その値が一意の8オクテットバイナリ行に割り当てられていた以前の値とは異なる値を返します。その値にシステムクロックとの相関があるという保証はありません。

+0

フィールド 'Timestamp'はbigint型です。これはタイムスタンプタイプには関係しません。 – mafu

関連する問題