2016-09-15 9 views
1

私たちは、変更ETLプロセスで変更検出を実装しようとしています。だから私たちは前に700Kレコードと約140カラム(私達は変更の列を決定するためにまだある)、約半分の時間のためのクエリの実行とテーブルについてSql - バルク暗号化ハッシュ生成

SET a.[HASH] = (SELECT 
        master.dbo.fn_varbintohexsubstring(0, HashBytes('md5', (SELECT TOP 1 * FROM customer_demographics_staging b WHERE b.customer_no = a.customer_no FOR XML RAW)), 1, 0)) 
FROM customer_demographics_staging a 

を使用して暗号化ハッシュを取得することを決めた

私たちはそれを取り消した。

私たちはこれを改善することができるクエリの数を減らすことは別として、とにかくありますか?

答えて

1

いくつかのことがあります。 HASH列のデータ型がvarbinary(20)の場合、MD5ハッシュを文字列に変換することに心配する必要はありません。ハッシュバイトを格納するだけです。その目的のために、変更検出のために暗号化ハッシュを使用する場合は、インラインテーブル値関数を使用して取得します。ここで私が使用して一緒にAdventureWorksの石畳の例です:それは私だったら、私はすべてのMD5を気にせず、ただ、おそらくテーブルに保存計算列として(CHECKSUM()機能を使用し、言っ

ALTER TABLE [HumanResources].[Employee] ADD [Hash] VARBINARY(20) NULL; 
GO 
CREATE FUNCTION dbo.CalculateHash(@EmployeeID AS INT) 
RETURNS TABLE 
AS 
    RETURN 

    SELECT e.[BusinessEntityID], HASHBYTES('md5', (
     SELECT * 
     FROM [HumanResources].[Employee] AS [e2] 
     WHERE [e2].[BusinessEntityID] = e.[BusinessEntityID] 
     FOR XML RAW 
    )) AS [Hash] 
    FROM [HumanResources].[Employee] AS [e] 
    WHERE [e].[BusinessEntityID] = @EmployeeID 

go 
SELECT TOP 10 [e].*, ch.[Hash] 
FROM [HumanResources].[Employee] AS [e] 
CROSS APPLY dbo.[CalculateHash]([e].[BusinessEntityID]) AS [ch] 
GO 

)。これは、複数の列をネイティブに取ることをサポートしています(つまり、行をXMLにシリアル化するオーバーヘッドが発生しません)。

+0

これは本当にうまく見えます。私はそれを行って、あなたに知らせるでしょう。 CHECKSUMの使用に関しては、値が変更されたときにそれが変更されない可能性があるため、変更検出には理想的ではありません。それが私たちの最初の選択でした。 – frostymarvelous

+0

私はそれがちょうどCYAだと思っています*任意の*ハッシュアルゴリズムが衝突を持っている限り(MD5が含まれています)。 'rowversion'カラムをテーブルに追加し、計算を完全にスキップすることもできます。 –

+0

ssisを使用してOracleデータベースからデータを抽出するので、Rowversionは機能しません。 – frostymarvelous

1

[Ben Thul]が既に言ったことに沿って、使いやすさだけでBINARY_CHECKSUM()に頼る傾向があります。 私はこの関数が8バイトの "but int"を返すことに同意します。例えば、MD5はvarの2倍のvarbinary(16)を返します。したがって、 'result-あなたが衝突に非常に小さなチャンスで終わることを意味する「スペース」。しかし、パラノイド私はそれを追加したいと思いますが、MD5の値が完全に一致していても、同じ(入力)値を持つわけではありません!

すべての正直なところ、私は違いを排除するためだけの機能を使用します。チェックサム(またはハッシュ)の結果が異なる場合は、値が異なることも100%確信できます。それらが同一である場合、ソース値を完全にチェックして、「誤った一致」がないかどうかを確認する必要があります。

あなたのユースケースは逆のようです:同一であるものを削除し、後者をハッシュコードのみで見てショートカットして、異なるものを探したいとします。正直言って、私はアプローチのファンではありません。あなたがステージングテーブルの '変更された'レコードを原因とする衝突に遭遇し、古いものと全く同じハッシュ値を取得する危険があるためです。変更をコピーします。ここでも、チャンスは非常に小さいですが、私が言ったように、それはこれに来るときあなたには、いくつかの発言、それにもかかわらず、このトラックをダウン続けたいと思いますならば、私は)

=被害妄想だ:

  • HashBytes 8000バイトの入力のみをサポートしています。 FOR XMLがあなたがそれらの140個の列
  • とのトラブルに遭遇する可能性があるXML構文によって追加のオーバーヘッドを考えると、私はそれをテーブルに書き込む前
  • を別のものにHashBytesの結果を変換する任意の(良い)理由が表示されませんかなり速いですが、CONCATと同じ速さではなく、同時に「より小さい」結果(cfポイント1)が得られますか?field1、field2、field3が "hello"、 "world" "の場合、" hello "、" "、" world "=と同様の結果になるような独自の問題が発生することに同意しますCONCAT-各フィールドのあまりにも...私たちはどれくらいの利益を残しているかわかりません=)
  • 私はあなたがすでにそれを持っていると思っていますが、ステージングテーブルのcustomer_noフィールドにクラスタ化されていますか。
+0

非常に有効なポイントをいただきありがとうございます。実際にはコンカットを使用することに決めました。また、トラッキングする列の数を制限しました(また、毎回注文を保障しています)。 LENを使用する代わりに、各列を区切ります。 varcharへの変換は、rawバイトを複数回使用しているので使用しないようにしています。 – frostymarvelous

関連する問題