如果您有空间(短暂)双重存储,我建议
1) 克隆现有表(所有索引、授权等),但使用 _TMP 命名
2) 加载_TMP
3) 将基表重命名为_BKP
4) 重命名 _TMP 以匹配基表
5) 将 _BKP 重命名为 _TMP
6) 截断_TMP
ETA:#1 将是“一次”; 2-6 将成为每日脚本的一部分。
这一切都假设 (1) 检测所有新记录和所有更新记录以及 (2) 使用 MERGE (INSERT+UPDATE) 将这些更改的记录集成到基表中的性能与满负载“不相上下”。
(就我个人而言,无论如何,我倾向于全负载方法;当有人调整并入视图 def 中的引用值并更改所有记录的值时,您会发现自己在等待长达一周的更新50,000,000 条记录。通过满载方法完全消除了这种担忧)
综上所述,应该注意的是,如果正确定义了 MV,则 MV-refresh 方法在各方面都与此方法相同,除了:
1) 更简单/更少移动的部件
2)更透明(视图def的SQL附在MV上,不埋在某个PL/SQL包或.sql脚本中)
3) 在表重命名之间不会有“昙花一现”的时间,查询/进程可能看不到表并失败。
ETA:可以通过多种方式使用“分区魔术”来解决此问题,从而避免数据或表丢失的“短暂”时间。
例如,您可以有一个偶数日和奇数日分区。在奇数日插入数据(不提交),然后截断偶数日(同时删除旧日并暴露新日)。但这值得复杂吗?您需要添加一列进行分区,并处理重新运行的复杂性 - 如果您的逻辑不严格,您最终会截断刚刚加载的数据。但是,这确实可以防止出现故障
一种确实可以避免任何“昙花一现”并且不太容易出现“哎呀”的方法:
1)添加始终具有值 1 的“DUMMY”列。
2) 创建 _TMP 表(也带有“DUMMY”列)并按 DUMMY 列分区(因此所有行都转到同一个分区)
-- 每日脚本 --
3)加载_TMP表
4) _TMP 表与主基表的交换分区 WITHOUT VALIDATION INCLUDING INDEXES
需要重复一下:如果资源使用到 MV-refresh,所有这些方法都是等效的;它们只是更复杂,而且往往会让开发人员觉得“精明”地解决了已经解决的问题。
最后一点 - 解决 David Aldridge - 首先,每日刷新表不应该启用日志记录。在恢复方案中,只需确保您有步骤在恢复基表后运行刷新脚本。
在性能方面,里程会有所不同;但根据我的经验,识别和修改更改/插入的行的复杂性可能会变得非常棘手(在某些时候,有人会对您的脚本没有考虑的基础数据做一些事情;要么产生不正确的结果,要么产生性能障碍)。 DWH 环境倾向于适应这样的过程而没有什么问题。除非/直到完全刷新证明的开销超出系统可以承受的范围,否则它通常是最简单的“设置后忘记”方法。
关于这一点,如果数据可以在逻辑上分为“可能更新的实时行”与“永远不会更新的历史行”,您可以提出分区方案和流程每天只会截断/重新加载“实时”数据。