【问题标题】:Oracle Data Versioning/Partitioning Strategies/Best PracticesOracle 数据版本控制/分区策略/最佳实践
【发布时间】:2011-01-08 02:27:16
【问题描述】:

不确定这个主题是否完全传达了我想要实现的目标,但让我解释一下:

我们正在构建一个使用 Oracle 作为存储后端的应用程序。每年,去年的数据集都将被“存档”,并从头开始创建和填充一个新实例。 在同一架构中执行此操作的选项有哪些?

  1. 将版本信息保持在记录级别(我们认为这对于我们的用例来说太慢了)。
  2. 在表级别保留版本信息,因此对于每个新版本,我们将重新创建所有表,但使用新版本前缀。 (我们喜欢这个解决方案,因为我们可以在代码中完成这一切)。
  3. ?

难道没有可用的分区/个性/命名空间之类的东西可以让我们在 Oracle 中实现这一目标吗?

我的预言机经验相当有限,任何帮助将不胜感激!

【问题讨论】:

  • 数据归档后,您是否需要访问它?您是否会报告合并的多年数据集?
  • 是的,他们的数据有时仍会被访问(和写入)。
  • 听起来您只需要在表格设计中包含“YEAR”作为键。会不会有一些表不会被清空,比如 CUSTOMER 表?

标签: oracle database-design schema versioning ddl


【解决方案1】:

RDBMS 概念模型不太擅长维护数据的时间版本。所以在这方面欠缺的不仅仅是Oracle。

我不清楚您为什么认为将版本信息保持在记录级别会太慢。创建新版本太慢?还是在常规操作期间数据检索太慢?

您可以这样做。给定一个业务键为 CUSTOMER_REF 的表 CUSTOMERS,我通常可能会这样构建它(由于空间原因,我使用缩写语法而不是最佳实践):

create table customers 
( id number not null primary key
  , customer_ref number not null unique key
  , name varchar2(30) not null )
/

版本化的等效项如下所示:

create table customers 
( id number not null primary key
  , customer_ref number not null 
  , version_number number
  , name varchar2(30) not null
  , constraint whatever unique (customer_ref, version_number) )
/

这可以通过保持当前版本的 VERSION_NUMBER 为空,并且仅在归档时填充它来实现。任何查找都必须包含and version_number is null。这会有点麻烦,您可能需要将该列包含在您构建的任何其他索引中。

显然,在同一个表中维护所有版本的记录会增加表的大小,这可能会影响性能。 Oracle 的分区选项在这里绝对可以提供帮助。它还将为您提供一种创建明年数据集的简洁方法。但是,它是在企业许可证之上额外收费的,因此它是一个昂贵的选择。 Find out more.

其中最耗时的方面将是管理新版本表中的外键关系。假设您选择使用合成主键,归档过程将不得不生成新的 ID,然后在新版本的引用外键中将它们精心级联到它们的依赖记录。

考虑到这一点,每个版本的谨慎表格看起来都非常有吸引力。为了便于使用,我会保持当前版本不加前缀,这样存档就变成了一个简单的过程

create table customers_n as select * from customers; 

您可能希望在创建版本化表时避免停机。在这种情况下,您可以使用物化视图在归档切换之前捕获表的状态。当时钟敲响十二点时,您可以关闭刷新。 (警告:这是在思考,我从来没有做过这样的事情,所以在购买之前尝试一下。)

多个表(和分区)的一个相关优势是您可以将归档记录移动到只读表空间。这不仅可以保护它们免受不必要的更改,还意味着您可以将它们从后续备份中排除。

编辑

我注意到您曾评论说存档数据有时会被修改。在这种情况下,将其移至只读表空间并不可行。

【讨论】:

  • >> 我不清楚您为什么认为将版本信息保持在 >> 记录级别会太慢。创建新的>>版本太慢? >> 或者在常规 >> 操作期间数据检索太慢?在常规的检索操作中太慢了,但我必须说,我对它太慢的看法完全是基于没有事实的,完全是直觉。我们正在探索客户端以确定他们是否有分区选项,如果没有,我们将采用表版本控制策略。感谢您的意见,非常感谢!
【解决方案2】:

我要补充到 APC 所说的唯一内容是关于您要求“命名空间”。

Oracle 中的命名空间是一个模式,因此您可以在每个模式中拥有相同的对象名称。

当然,这一切都取决于您的应用必须如何访问多个版本,但在使用某种命名约定来维护同一架构中的表版本之前,我会倾向于每年使用不同的架构。原因是,最终你会做噩梦。至少对于不同的模式,所有 DDL 都可以相同,对对象的所有引用都相同,并且 ER 建模器和查询工具等工具将在该模式的上下文中工作。数据模型会发生变化,因此在某些时候您可能需要运行一些比较工具,如果您的所有表都被命名为 funky 并带有某种版本后缀,那将无法正常工作。

可以使用 fromuser/touser 或 remap_schema 选项通过导出或数据泵快速复制/移动架构,因此您不需要太多代码,除了从新版本中清除去年的数据。

我发现架构作为“容器”非常有用,而且我托管的大多数应用程序只有架构级别的权限,因此我可以保证应用程序可以轻松快速地从一个实例移动到另一个实例,或者应用程序的多个副本在同一个实例上并排托管。

【讨论】:

    【解决方案3】:

    架构可能会在几年之间发生变化。例如,在 2010 年,您有 15 列,但在 2011 年,您添加了第 16 列。 如果是这样,同一个应用程序是否适用于 2010 年和 2011 年的数据。

    如果架构是静态的,我会选择带有“YEAR”列的表并使用VPD/RLS/FGAC 应用 YEAR = '2010' 谓词。

    如果性能有问题,我只会担心分区。

    【讨论】:

      【解决方案4】:

      1) 间隔按年份和行中的某个日期字段对其进行分区。

      2) 将其添加到每个表的末尾并使用序列和触发器填充它。

      3) 然后在此列上按间隔年份划分。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-08-12
        • 1970-01-01
        • 2010-09-24
        • 2012-03-22
        • 2021-09-18
        • 1970-01-01
        相关资源
        最近更新 更多