我正在设计一个新的实验室数据库。
我的主数据表将至少有id (PK NUMBER)
和created_on (DATE)
。此外,对于任何两个条目,具有较高的条目id
将具有较晚的created_on
日期。
我计划分区created_on
以提高最近输入数据的性能。由于列一起增加,表也将被id
隐式分区。Oracle 不会知道隐含的分区,id
以利用id
.
两个问题:
如何强制两列一起增加?
如何利用这种隐式分区进行表连接?
我正在设计一个新的实验室数据库。
我的主数据表将至少有id (PK NUMBER)
和created_on (DATE)
。此外,对于任何两个条目,具有较高的条目id
将具有较晚的created_on
日期。
我计划分区created_on
以提高最近输入数据的性能。由于列一起增加,表也将被id
隐式分区。Oracle 不会知道隐含的分区,id
以利用id
.
两个问题:
如何强制两列一起增加?
如何利用这种隐式分区进行表连接?
在我看来,分区的决定应该更多地基于对表维护活动(清除、归档等)的需要,而不是性能。在您的情况下,我猜您可能会对日期范围的样本执行索引范围扫描,因此请确保日期索引也是本地(而不是全局)分区的。如果您截断分区,这也将消除重建索引的需要。我还猜测 PK 上的连接将使用 rowid 搜索,因此这将在索引范围扫描之后发生,并且分区无法影响这一点。
[编辑]
关于关联 PK 和 CREATED_ON 列,我使用了几个系统,这些系统从以 YYYYMMDD 为前缀的序列构造数字键并且效果很好。你必须:
自由估计您每天将拥有的样本数量
定义一个序列,将其作为最大值,然后循环回 0
有一个返回 YYYYMMDD || 的函数 {sequence value left-padded with
zeros to the appropriate fixed length} 在需要密钥时从触发器或应用程序代码中调用
有些人不同意在密钥中嵌入含义,但在实践中,查看样本 ID 并了解它的处理时间很有用
真正重要的问题是:您是否需要按 ID 范围进行查询?您不太可能需要使用ID BETWEEN :A AND :B
. 因此,Oracle 不会从相关分区方案中受益。对于所有重要的事情,您可以使用 aGUID
作为主键,您将获得更好的可扩展性INSERTS
。
老实说,这很棘手。多列分区是一种选择,您可以在多个列上创建基于范围的分区。在 11g 中,您可以将其作为 A 列上的分区和 B 列上的子分区来实现,但在 10g 中,您必须在两列上按范围进行分区。我认为棘手的部分是知道要分区的边界,因为您可能希望两个分区方案“同步”。
在这种情况下,为了提高“table_id”连接的性能,您还应该将相应的“created_on”存储在您将主要连接的表中。如果你这样做,你总是可以同时加入“table_id”和“created_on”,这样你的“PARTITION RANGE ALL”就会变成“PARTITION RANGE SINGLE”。您可以衡量速度增益并将其与额外的存储成本进行权衡。
编辑:
如何保持两个领域一起增加:
ALTER TABLE my_table MODIFY created_on DEFAULT SYSDATE;
并在所有插入中从序列中填写 ID。
如何强制两列一起增加?
假设它是批量加载并且 id 是在批量加载时生成的序列,您可以在加载之间更改序列以更好地控制用于每个分区的序列范围。如果序列和创建时间是在批量加载之前分配的,您可能需要在 ETL 过程中确定每个创建日期的最小/最大 ID 是多少。
created_on 上的范围分区,id 上的范围子分区。每个分区应该只有一个子分区。
假设,因为这是一个新的数据库,你将有 11g 对虚拟列的检查约束怎么样。虚拟列 date_partition
CASE WHEN created_on BETWEEN ... AND ... THEN 'PARTITION_1' WHEN created_on BETWEEN ... AND ... THEN 'PARTITION_2' ... END
id_partition 上的类似虚拟列,尽管您必须查询以获得每个分区的最小/最大 PK。应该很快,因为作为主键,上面有一个索引。
然后添加一个约束,使得 id_partition = date_partition