【问题标题】:What is the most efficient way to update a table during a merge operation?在合并操作期间更新表的最有效方法是什么?
【发布时间】:2012-04-10 02:21:56
【问题描述】:

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

从历史上看,我曾经使用过以下老把戏:-

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

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

我必须对 1) 进行性能打击。这是不可避免的。然而,在2),我已经相当挥霍了。我不仅更新了需要更新的内容,还更新了我匹配的所有内容(基础数据是否已更改)。

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

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

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

  • 优点:很简单。
  • 缺点:很垃圾。

2) 编写更多 UPDATE 语句,以在特定字段发生更改时更新该字段。

例如

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。同样的问题,真的。

【问题讨论】:

  • SQL Server?版本?您也许可以使用MERGE 声明...
  • 我知道 2008 带有 MERGE INTO,但是在对索引的影响方面不也有同样的问题吗?
  • 如果您要更新值未更改的字段,则可以。您可以随时为每个字段添加CASE 检查。
  • 做了更多的测试,不幸的是它没有得到优化......
  • 编写一个代码库怎么样?一方面,它可以生成您希望拥有的更新存储过程的所有排列,另一方面,在给定的情况下选择正确的存储过程来执行对象在内存中的状态。当我被困在实现数据库端分页、排序和过滤列表解决方案时,我做了类似的事情。 (基本上是选项 2,但以编程方式管理)。

标签: sql sql-server-2008 tsql indexing


【解决方案1】:

使用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 语句)。

【讨论】:

  • 直到最后一句话,一切都进展顺利! (不幸的是,这可能最终仍然是答案)。感谢您的意见,先生!
  • 你试过了吗?我在 SQL Server 2012 中得到 An action of type 'WHEN MATCHED' cannot appear more than once in a 'UPDATE' clause of a MERGE statement.。在 SQL Server 2008 中是否有所不同?
  • 来自merge documentation。 “MERGE 语句最多可以有两个 WHEN MATCHED 子句。”....“如果有两个 WHEN MATCHED 子句,那么一个必须指定一个 UPDATE 操作,一个必须指定一个 DELETE 操作”
  • 噢。我主要使用 DB2(它允许这样做),当我扫描 BOL page 中的 MERGE 时没有看到该语句。对不起。 :(
猜你喜欢
  • 2023-03-17
  • 2021-07-24
  • 2015-10-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-26
  • 2020-09-07
  • 2011-12-06
相关资源
最近更新 更多