Oracle - 故障转移表或查询操作
Posted
技术标签:
【中文标题】Oracle - 故障转移表或查询操作【英文标题】:Oracle - Failover table or query manipulation 【发布时间】:2015-11-07 11:33:18 【问题描述】:在 DWH 环境中,出于性能原因,我需要将视图具体化为一个大约为 10 的表格。 100 列和 50.000.000 条记录。每天插入约 60.000 条新记录,并对现有记录执行约 80.000 条更新。根据决定,我不允许使用物化视图,因为架构师声称这会导致性能问题。我不能再争论这个案子了,这是一个不可撤销的决定,我必须接受。 所以我想在晚上每天满负荷,例如截断并插入。但如果作业失败,该表可能不是空的,但必须包含上次成功填充的数据。 因此我想到了类似故障转移表之类的东西,如果出现任何问题,将使用它:
IF v_load_job_failed THEN failover_table ELSE 正则表
根据预定义的条件,是否会使用类似故障转移表而不是另一个表?类似于在执行之前重写或操作选择查询的触发器?
我知道这有点肮脏的解决方法。
【问题讨论】:
【参考方案1】:如果您有空间(短暂)双重存储,我建议
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 环境倾向于适应这样的过程而没有什么问题。除非/直到完全刷新证明的开销超出系统可以承受的范围,否则它通常是最简单的“设置后忘记”方法。
关于这一点,如果数据可以在逻辑上分为“可能更新的实时行”与“永远不会更新的历史行”,您可以提出分区方案和流程每天只会截断/重新加载“实时”数据。
【讨论】:
我看到满载的问题是,作业的持续时间与表中的数据总量有关,而不是更改量。因此,尽管您说得很对,有时可能需要完全重新加载(特别是您需要空间才能做到这一点),但我会担心工作会增加持续时间并增加重做存档的大小. OTOH 完全重新加载的一个优点是它可以让您使用经济的压缩技术,当然,以减少数据大小。 我刚刚有了另一个想法:如何将数据加载到同一张表的专用 TEMP 分区中,并在常规分区中成功填充后移动该分区。这是一个明智的做法吗? 这有很多变体。附加答案以提供概述 - 通常每个人都在做完全相同的事情(在看不到的地方加载数据,与旧数据交换,删除旧数据)。 参考日志——我明白你为什么会说如果每天的原始数据是一个完整的数据集,但当然不是。 请记住,这是一个新记录占总数的 0.12%,而修改的记录占总数的 0.16% 的情况。即使对新记录和更新记录的表和索引进行重做和撤消,这也可能比重新创建完整表及其所有索引的 I/O 少得多,而且 I/O 几乎总是数据仓库的瓶颈。当然,这在一定程度上取决于更新检测查询。【参考方案2】:物化视图只是一组带有基础表的元数据,没有理由不能以类似于物化视图内部机制的方式维护表。
我建议使用 MERGE 语句作为单个查询,而不是截断/插入。它要么完全成功,要么回滚以保持以前的数据完好无损。 60,000 条新记录和 80,000 条修改记录并不多。
我认为,如果您至少从一个简单的单一 SQL 语句开始,然后看看它如何为您工作,那么您就不会出错。如果您确实决定采用多步骤流程,请确保它在任何可能在中途出错的阶段自动恢复 - 这可能是个棘手的问题。
【讨论】:
以上是关于Oracle - 故障转移表或查询操作的主要内容,如果未能解决你的问题,请参考以下文章
Win2012R2 Hyper-V初级教程17 -- 非计划故障转移和故障转移(上)
hadoop hdfs 高可用性安装 测试 zookeeper 自动故障转移