在合并操作期间更新表的最有效方法是什么?

时间:2012-03-26 14:58:26

标签: sql sql-server-2008 tsql indexing

与许多开发人员一样,我使用数据执行大量合并操作,特别是SQL Server。

从历史上看,我使用了旧的技巧: -

1)对现有数据进行左连接,并插入任何我没有相应记录的内容。

2)1)之后,更新目标表中的行。

我必须在1)上取得成绩。这是不可避免的。然而,在2),我一直相当挥霍。我没有更新需要更新的内容,而是更新了我匹配的所有内容(基础数据是否已更改)。

事实证明,SQL Server对这种更新并不太聪明。它不执行预先检查以确定您要更新的内容与更新它的内容不同。因此,沿着这些行进行的更新会导致物理写入并影响引用该字段的任何索引。

所以,从我的POV来看,我的选择如下: -

1)正常进行,沉浸在我的日常工作的当前挥霍中(并且每天在大型数据库上刷新索引)

  • 优点:很容易。
  • 缺点:这是废话。

2)如果字段已更改,请编写更多更新特定字段的UPDATE语句。

e.g。

UPDATE
    p2 
SET
    [SpecificField] = p1.[SpecificField]
FROM
    @source p1,
    Dest p2
WHERE
    p2.ExternalKey = p1.ExternalKey
AND COALESCE(p1.[SpecificField],'') <> COALESCE(p2.[SpecificField],'')
  • 优点:它非常具体,只有在需要更新时才会更新。
  • 缺点:包含许多列的表的许多不同的更新语句。

3)Stack Overflow社区建议的东西无限好。

我真的很想去3)。我的选择真的限于1或2吗?注意。我已经研究过MERGE INTO。同样的问题,真的。

1 个答案:

答案 0 :(得分:2)

使用MERGE INTO,您可以选择向WHEN (NOT) MATCHED子句添加其他搜索子句。例如,

MERGE INTO table_to_upsert AS target
 USING source_table    AS source
    ON target.key1 = source.key1
   AND target.key2 = source.key2
   AND target.key3 = source.key3
WHEN MATCHED AND (target.value <> source.value) THEN
            UPDATE SET target.value     = source.value,
                       target.timestamp = source.timestamp
WHEN MATCHED AND (target.userid <> source.userid) THEN
            UPDATE SET target.userid    = source.userid,
                       target.timestamp = source.timestamp
WHEN NOT MATCHED THEN
            INSERT (key1, key2, key3, 
                    value, userid, timestamp)
            VALUES (source.key1, source.key2, source.key3,
                    source.value, source.userid, source.timestamp)

但是,如果一次更新多个列,这并不能真正解决您的问题,MERGE将采用评估为true的第一个WHEN (NOT) MATCHED(类似于CASE语句)。