自从出现数据之间集成任务的时候,编程同步的问题常常出现:只需要更新真实更改的行,以节省资源并最小化锁定。过去的标准方法是完全替换或手动查找差异,这导致多余的操作并引发错误。
问题:在同步时,需要检测和更新仅已更改的数据,而不是全部更新。这对于性能、网络流量和完整性非常重要,尤其是在大规模或分布式数据库中。
解决方案:通常通过使用JOIN操作符比较源表和目标表,通过HASH或校验和计算差异,仅使用MERGE(或UPSERT)或特定触发器更新“不同”的行。
示例代码(在SQL Server中):
MERGE target_table AS t USING source_table AS s ON t.id = s.id WHEN MATCHED AND (t.name <> s.name OR t.value <> s.value) THEN UPDATE SET t.name = s.name, t.value = s.value WHEN NOT MATCHED BY TARGET THEN INSERT (id, name, value) VALUES (s.id, s.name, s.value);
关键特性:
MERGE是否总是能够保证在并发更新时没有竞争条件?
不,如果没有额外的事务控制,可能会出现竞争条件(race condition)。为了最大程度的准确性,请使用适当的事务隔离级别。
可以使用UPDATE ... JOIN而不是MERGE进行复杂同步吗?
通常可以,但这种方法无法将新行添加到目标表中。只有MERGE/UPSERT可以更新和添加。
UPDATE t SET t.name = s.name, t.value = s.value FROM target_table t JOIN source_table s ON t.id = s.id WHERE t.name <> s.name OR t.value <> s.value;
如果同步的表具有不匹配的列集怎么办?
建议明确列出对应的字段,而不是尝试更新“始终所有”字段。如有需要,请使用映射表或转换。
ETL工程师通过简单的UPDATE操作一口气“冲”入所有键的记录:表中有数千万行,过程耗时数小时并锁定服务器。没有单独的插入新行,导致丢失新数据。
优点:
缺点:
专家在插入之前计算行的校验和,过滤已更改的记录,使用MERGE快速同步并追加新行。整个过程在几分钟内完成,没有过载。
优点:
缺点: