场景:我拥有一个 ETL 流程。该流程涉及从不同来源提取数据并使我的数据库与最新数据同步。
假设我有一个名为 [catalog] 的表。它包含我公司的产品目录。此表的可信来源每四个小时向我发送一个 CSV。我提取该 CSV 并确保我的 [catalog] 表与其同步。我使用如下更新:
UPDATE mc
SET
[field1] = tc.[field1]
, [field2] = tc.[field2]
FROM [my].[catalog] as mc
INNER JOIN [their].[catalog] as tc
ON mc.id = tc.id
WHERE mc.[field1] <> tc.[field1]
OR mc.[field2] <> tc.[field2]
此命令将比较每个匹配项,并仅筛选出那些将看到有意义更改的行,然后仅更新这些行。我不想不必要地触碰任何行——这是 ETL 开发人员的长期任务。
不会执行任何琐碎更新(所谓琐碎更新,我指的是对某一行的更新,但该行中的任何字段均未发生改变)。未发生改变的行将保持原样,不受干扰。
这里用“不受干扰”这个词很贴切,因为更新一行而不影响值会产生不必要的成本。在内存和磁盘中,对行的更新会从物理上删除包含旧值的行,并插入包含新值的新行。所有这些更新都必须记录!因此,在什么都不做的过程中,我们已经在内存和磁盘上对表的索引和数据页进行了碎片化和分割。而且我们正在通过日志进行不必要的流量。
如果我们不做任何更改,那么简单的更新仍会导致内存和磁盘的混乱。为表提供一种自动忽略简单更新的方法,对于许多场景来说都是一大优势。
现在,假设某个笨手笨脚的开发人员通过某个客户端或程序更改进行了更新,该更新对大型表执行了类似操作,但没有包括任何措施来忽略“真正”不需要更新的行。我可以对表执行什么操作,让它表现得好像知道传递琐碎的更新一样?