防止SQL数据仓库中数十亿行的插入重复?

时间:2018-03-21 19:06:56

标签: azure-sqldw

我正在尝试确定是否有一种实用的方法可以防止在表已经拥有数十亿行(比如说200亿)时使用Azure SQL DW将重复行插入到表中。

需要这个的根本原因是数据源是第三方发送了所谓的唯一数据,但有时会发送没有识别密钥的重复数据。遗憾的是,我不知道我们是否已收到他们发送的数据。

我尝试过创建一个包含行哈希列的表(从其他几列预先计算)并根据该行哈希分发数据。例如:

CREATE TABLE [SomeFact]
(
    Row_key BIGINT NOT NULL IDENTITY,
    EventDate DATETIME NOT NULL,
    EmailAddress NVARCHAR(200) NOT NULL,
    -- other rows
    RowHash BINARY(16) NOT NULL
)
WITH
(
    DISTRIBUTION = HASH(RowHash)
)

插入SQL大约是:

INSERT INTO [SomeFact]
(
    EmailAddress,
    EventDate,
    -- Other rows
    RowHash
)

SELECT
    temp.EmailAddress,
    temp.EventDate,
    -- Other rows
    temp.RowHash
FROM #StagingTable temp
WHERE NOT EXISTS (SELECT 1 FROM [SomeFact] f WHERE f.RowHash = temp.RowHash);

不幸的是,这太慢了。我添加了一些统计信息,甚至在RowHash上创建了一个二级索引,任何实际大小的插入(例如1000万行)都不会成功运行而不会因为事务大小而出错。我也尝试了5万批次,而且那些也太慢了。

2 个答案:

答案 0 :(得分:1)

我能想到的两件事情,就是你的查询中没有单例记录就是

  • 将您的临时表与事实表连接在一起并过滤一些NULL值。假设您在事实表中使用了Clustered Column Store,这应该比上面的便宜得多。
  • 使用现有事实表中的Select Distinct执行CTAS,并使用UNION将登台表中的Select Distinct连接在一起。

我的直觉说第一个选项会更快,但您可能想查看查询计划并测试这两种方法。

答案 1 :(得分:0)

你能分开主要的'表格由EventDate表示,假设新数据有最近的EventDate,CTAS只输出包含新数据的EventDate的分区,然后“合并”#39;合并' CTAS / UNION的数据与旧的'和'新'将数据放入具有相同分区模式的表中(UNION将删除重复项)或使用针对较小表开发的INSERT方法,然后将分区交换回主要的'表

注意 - 分区交换命令上有一个新选项,允许您直接交换'一步分区:" WITH(TRUNCATE_TARGET = ON)"。