Oracle - 故障转移表或查询操作

时间:2015-11-07 11:33:18

标签: sql oracle data-warehouse

出于性能原因,在DWH环境中,我需要将视图具体化为大约表格。 100列和50.000.000条记录。每天插入约60,000个新记录,并对现有记录执行~80.000更新。根据决定,我不允许使用物化视图,因为架构师声称这会导致性能问题。我不能再辩论这个案子了,这是一个不可改变的决定,我必须接受。 所以我想在夜间每天满载,例如截断并插入。但是如果作业失败,表格可能不是空的,但必须包含上次成功人口的数据。 因此,我想到了类似故障转移表的内容,如果出现任何错误,将使用它:

如果v_load_job_failed那么failover_table ELSE regular_table

根据预定义的条件,是否会使用类似故障转移表而不是其他表?类似于在执行之前重写或操作选择查询的触发器?

我知道这有点像一个肮脏的解决方法。

2 个答案:

答案 0 :(得分:1)

如果您有双倍存储(短暂)时间的空间,我建议

1)克隆现有表(所有索引,授权等)但名称带_TMP
2)加载_TMP
3)将基表重命名为_BKP
4)重命名_TMP以匹配基表
5)将_BKP重命名为_TMP
6)截断_TMP

ETA:#1将是"一次&#34 ;; 2-6将成为日常脚本的一部分。

这一切都假定(1)检测所有新记录和所有更新记录的性能,以及(2)使用MERGE(INSERT + UPDATE)将这些已更改的记录集成到基表中是"在"满载。

(就个人而言,无论如何,我倾向于满负荷的方法;当天有人调整了参与视图的参考值并更改了所有记录的值,你会发现自己在等待为期一周的50,000,000条记录更新。这种担忧完全消除了全负荷方法)

所有这一切,应该注意的是,如果MV被正确定义,MV-refresh方法在各方面都与此方法相同,除了: 1)更简单/更少移动的部件 2)更透明(视图def的SQL附加到MV,不包含在某些PL / SQL包或.sql脚本中) 3)不会有" blip"在表重命名之间,查询/进程可能看不到表并且失败。

ETA:可以通过"分区魔术来解决这个问题"以某种方式避免了#34; blip"数据或表缺失的时间。

例如,您可以拥有偶数天和奇数天的分区。在奇数天,插入数据(无提交),然后截断偶数天(同时丢弃旧日并暴露新的)。但值得复杂吗?您需要添加一个列来进行分区,并处理重新运行的复杂性 - 如果您的逻辑不严格,那么您最终会截断刚加载的数据。但是,这确实会阻止blip

一种避免任何" blip"并且少了一点"呐喊"易于: 1)添加" DUMMY"始终具有值1的列。 2)创建_TMP表(也使用" DUMMY"列)并按DUMMY列分区(因此所有行都转到同一分区)
- 每日剧本 - 3)加载_TMP表 4)交换_TMP表与主基表的分区,不带有包含索引的确认

需要重复的是:如果资源使用到MV-refresh,所有这些方法都是等效的;他们只是更复杂,往往会让开发人员感到精明和精明。解决已经解决的问题。

最后的注释 - 解决David Aldridge - 首先,每日刷新表不应该启用日志记录。在恢复方案中,只需确保在还原基表后执行刷新脚本的步骤。

在性能方面,行驶里程会有所不同;但根据我的经验,识别和修改更改/插入行的复杂性可能变得非常棘手(在某些时候,某人会做一些事情来基于您的脚本没有考虑到的数据;要么产生不正确的结果或性能障碍)。 DWH环境倾向于适应这样的过程而几乎没有问题。除非/直到完全刷新证明具有超出系统可以容忍的超出的开销,否则它通常是最简单的"设置它并且忘记它"方法

在该注释中,如果数据可以在逻辑上分成"可以更新的实时行" vs"永远不会更新的历史行",你可以想出一个只截断/重新加载" live"的分区方案和流程。每日数据。

答案 1 :(得分:0)

物化视图只是一组带有基础表的元数据,并且没有理由不能以类似于物化视图的内部机制的方式维护表。

我建议使用MERGE语句作为单个查询而不是截断/插入。它将完全成功或回滚以保留先前的数据。 60,000条新记录和80,000条修改记录并不多。

我认为,如果你至少从一个简单的单一SQL语句开始,然后看看它对你有什么用,你就不会出错。如果您决定使用多步骤进程,那么请确保它在部分可能出错的任何阶段自动恢复 - 这可能会变得非常棘手。