2

2セットのスケジュールが同一であるかどうかをすばやく判断し、これらの一意のスケジュールを参照できるキーを生成しようとしています。私はもともとHASHBYTESを使おうとしましたが、ハッシュできるのは8000文字のみであり、連結すると8000より長い日時がかなりの数あることにすぐに気付きました。

そこで、ChecksumとChecksum_Aggはこの種のもののために設計されているように見えるので、それらを使用しようとしました。チェックサムは、一意でない値を生成する可能性が高いことを認識しています。しかし、これらを相互に比較する必要がある私の範囲/コンテキストは非常に狭いので、私はそれを回避できると思いました。

残念ながら、ほんの少しのテストの結果、わずか4行の日時データでチェックサムの「衝突」を見つけることができることがわかりました。これは少し変だと思い、衝突のパターンを発見しました。

以下は、問題を示すサンプルスクリプトです。

@RowsTABLEを宣言します
((
    [GroupId] INT、
    [StartDate] DATETIME、
    [終了日]DATETIME
)。

--グループ1
INSERT INTO @Rows VALUES(1、 '2013-01-20 01:00:00.000'、 '2013-01-20 01:20:00.000')
INSERT INTO @Rows VALUES(1、 '2013-01-20 01:20:00.000'、 '2013-01-20 01:40:00.000')
--INSERT INTO @Rows VALUES(1、 '2013-01-20 01:40:00.000'、 '2013-01-20 02:00:00.000')
--INSERT INTO @Rows VALUES(1、 '2013-01-20 02:00:00.000'、 '2013-01-20 02:20:00.000')
--INSERT INTO @Rows VALUES(1、 '2013-01-20 02:20:00.000'、 '2013-01-20 02:40:00.000')
--INSERT INTO @Rows VALUES(1、 '2013-01-20 02:40:00.000'、 '2013-01-20 03:00:00.000')

--グループ2
INSERT INTO @Rows VALUES(2、 '2013-01-21 01:00:00.000'、 '2013-01-21 01:20:00.000')
INSERT INTO @Rows VALUES(2、 '2013-01-21 01:20:00.000'、 '2013-01-21 01:40:00.000')
--INSERT INTO @Rows VALUES(2、 '2013-01-21 01:40:00.000'、 '2013-01-21 02:00:00.000')
--INSERT INTO @Rows VALUES(2、 '2013-01-21 02:00:00.000'、 '2013-01-21 02:20:00.000')
--INSERT INTO @Rows VALUES(2、 '2013-01-21 02:20:00.000'、 '2013-01-21 02:40:00.000')
--INSERT INTO @Rows VALUES(2、 '2013-01-21 02:40:00.000'、 '2013-01-21 03:00:00.000')

SELECT [ChecksumAgg1] = CHECKSUM_AGG([CheckSum])
から
((
    SELECT [CheckSum] = CHECKSUM([StartDate]、[EndDate])
    FROM @Rows
    WHERE GroupId = 1
)G1

SELECT [ChecksumAgg2] = CHECKSUM_AGG([CheckSum])
から
((
    SELECT [CheckSum] = CHECKSUM([StartDate]、[EndDate])
    FROM @Rows
    WHERE GroupId = 2
)G2

結果は次のとおりです。

ChecksumAgg1:5681728

ChecksumAgg2:5681728

2つの一連の日付の唯一の違いは、1日離れていることです。しかし、それらは同じチェックサムを生成します!ただし、行数が偶数の場合のみ。グループ1のINSERTとグループ2のINSERTのコメントを解除すると、2つの異なるチェックサムが得られます。ただし、さらに別のペアのコメントを解除すると、別の一致が得られます。


最後に、2つの質問があります。これがどのように機能するのか、そしてなぜこのパターンがかなり予測可能なチェックサム値に影響を与えるように見えるのかについて、もう少し学びたいと思います。さらに重要なことに、非常に大きなデータセットの「フィンガープリント」を本質的に作成するためのより良い方法があるかどうかを知りたいと思います。このハッシュがグローバルに一意であることを保証できないことは理解していますが、チェックサムよりも優れたものが必要なようです。

チェックサム計算をだまし取ることができた1つの方法は、チェックサム関数に事前にフィードする日時にHASHBYTESを実行することでした。このようにして、チェックサムには、見た目が似ている一連の日付よりもはるかにランダムに見える値が供給されます。しかし、それで十分でしょうか?


編集-ここにもう少しコンテキストがあります。

基本的に、私は大量のスケジュールデータを持つ1つのシステムと、特定の時間にこれらのスケジュールに関心を持つ別のシステムを持っています。たとえば、複数のユーザーがこの複雑なスケジュールの一部の特定のバージョンを表示し、メタデータ(承認ステータス、メモなど)を追加したい場合があります。外部ソースが単一の日時に変更を加えた場合、同じスケジュールではなくなったため、このリンクを解除する必要があります。

コアスケジュールデータに変更を加える可能性のあるさまざまなシステムがあります。そのため、この懸念をコードレベルでバブリングして、これを何らかの方法で各スナップショットを表すエンティティに管理および「正規化」するのに苦労しています。変更をリッスンし、スケジュールを指しているものをすべてクリーンアップするために、100万の場所にフックを配置する必要があります。

4

3 に答える 3

2

一意性を確保するためにも何をしなければならないかを考えると、このチェックサムのすべてが問題に値すると思いますか?個人的には、作業を減らして1つの値だけを比較するのではなく、列を直接比較するだけでパフォーマンスが向上する(複雑さが軽減される)と思います。

また、日時の値は整数のペアにすぎないことにも注意してください。したがって、2つの値の組み合わせにチェックサムを適用すると、同じ値になる可能性があることはそれほど驚くべきことではありません。例えば:

SELECT CHECKSUM_AGG(x)
FROM
(
  SELECT CHECKSUM(1,2)
  UNION ALL 
  SELECT CHECKSUM(2,3)
) AS y(x);

SELECT CHECKSUM_AGG(x)
FROM
(
  SELECT CHECKSUM(2,2)
  UNION ALL 
  SELECT CHECKSUM(1,3)
) AS y(x);

結果:

----
49

----
49

だから私はただインデックスを付けてStartDate, EndDateそれで終わらせることを提案します。あなたはすでにかなり効率的なものをより効率的にしようとしています、そして私はあなたが反対を達成していると思います。

キーについては、IDENTITY列またはその他の代理を使用してください。CHECKSUM_AGG(CHECKSUM(HASHBYTES(col1),HASHBYTES(col2)))一意性をシミュレートするためにネストすることに利点はありません...

編集

または、新しい要件が与えられたROWVERSION場合、データが最後に読み取ったときと同じであることを確認したい場合は、列を使用してください。何百万ものチェックサム結果を追跡することが、行バージョンやその他の方法で計算された値を追跡することとどのように異なるのかわかりません。あなたがやろうとしていることを実行する組み込みのものがすでにあるとき、あなたはあまりにも一生懸命働いています...

于 2013-01-22T02:17:07.123 に答える
1

このページのコメントから:

http://msdn.microsoft.com/en-us/library/ms188920.aspx

Checksum_AggはXORを使用して構築されているようです。また、XORについては、同じ数を2回含めることで簡単に元に戻せる傾向があります。これは、それが偶数であるときにのみ気づいた理由を説明しています。

XORの問題を認識し、それにフィードするものを事前にスクランブルして、すべてのビットを混同するようにしている限り、問題はありません。

于 2013-01-22T02:08:36.250 に答える
0

私もこの問題に直面しました。これは、列のすべての値が同じである場合に表示されます。合計を計算するとき、おそらくこの列は必要ありません。

于 2014-08-27T08:39:00.000 に答える