【发布时间】: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