web-dev-qa-db-ja.com

列ストアの社会保障番号をDECIMAL(10,9)として保存

私は、SSNとBirthDateでマッチングを実行して重複レコードを検索する非常に大規模なデータベース(10B +行)に取り組んでいます。テーブルは列ストア圧縮(SQL SERVER 2016)を使用しており、SSNをDECIMAL(10,9)として保存して、先頭のゼロを保持し、CHAR/VARCHARからパフォーマンスヒットを奪わないようにすることができました。誰かがこれを試したのか、これが期待どおりに機能しない理由があるのか​​と思っています。 INTにキャストして先頭のゼロを失うだけでよいことはわかっていますが、これは私にとってより良い解決策のように思えました。

ISNULL(TRY_CAST('.' + SSN AS DECIMAL(10,9)),0) AS DecimalSSN

いつでもRIGHT(TRY_CAST(DecimalSSN AS VARCHAR),9) AS SSNで文字列にキャストできます

2
AAndrus

DECIMALを使用して、行ストアテーブルまたは列ストアテーブルを持つSSNを格納しません。 INTデータ型には、DECIMALに比べて次の利点があります。

  • SQL Serverの方が一般的に高速です
  • ビットマップフィルターをストレージエンジンにプッシュダウンできます。
  • 列がNULLを許可しない場合、結合にプローブの残差を必要としない「完全なハッシュ関数」が許可されます。

SSN列のパフォーマンスを向上させる必要がある場合は、先頭に1を付けたINTを使用します。これにより、望ましいと思われる先頭のゼロが保持されます。すべてのSSNを同じ形式で保存し、必要な場合にのみキャストする必要があります。たとえば、SSNを文字列としてエンドユーザーに表示する必要がある場合、SELECT RIGHT(CAST(1012345678 AS INT), 9)"012345678"を返します。それ以外の場合は、未加工の値を使用します。

クエリがどのように見えるかはわかりませんが、テーブルに100kのSSNがあり、それらのSSNが10億行ある別のテーブルにあるかどうかを確認する必要があるとします。クエリは次のようになります。

SELECT *
FROM dbo.SSNS_TO_CHECK_3 c
WHERE NOT EXISTS (
    SELECT 1
    FROM dbo.ALL_SSNS_CCI_INT_LEADING_1 t
    WHERE c.SSN = t.SSN
)
OPTION (MAXDOP 1);

先頭に1が付いたINT列を使用すると、上記の query が私のマシンで7秒かかります。 query を提案したDECIMAL(10、9)形式では、マシンで63秒かかります。ほとんどすべての時間がビットマップ演算子に費やされています。

列ストアには追加の考慮事項がありますが、ここでは関係ありません。 INTは、DECIMAL(10、9)と比較して、私が知っているあらゆる点で優れています。

6
Joe Obbish