我应该如何对 oracle 数据库表进行水平分区?

Jos*_*ton 5 oracle aggregate partitioning

我们有一个租用的数据仓库,我们正在做报告。查询开始需要很长时间,我们正在寻找减少这种情况的选项。目前有两个想法。

  1. 创建租户特定的聚合表,并从中查询。

  2. 根据租户对数据进行水平分区。

第一个选项意味着对于每个加入的新租户,我们都需要创建一组新表。这并不难,因为新租户的注册会提前几周通知,如果我们忘记了,就会很早就发现缺少报告。

对我来说,对数据进行分区听起来是一种更好的方法,因为我们不会复制数据。我们不必依赖于将新数据传输到聚合表的过程。

我想知道这些选项中的哪一个会更好,如果有人以前有过类似的经历。对数据进行分区真的有帮助吗?或者与将所有数据放在一个“空间”中没有太大区别?

而且,在 Oracle 10g 中,如何对数据进行水平分区?如果我有下表:

TABLE Transaction(id, tenant_id, a, b, c, d)
Run Code Online (Sandbox Code Playgroud)

我们将很快迁移到 Oracle 11g,因此将不胜感激跨版本分区的任何差异。

(注意:我尝试使用分区标签,但没有足够的代表,如果其他人可以添加一个很酷的标签)

Gai*_*ius 8

首先回答你的第二个问题:是的,你应该分区。Oracle 的查询优化器有一个特性叫做分区消除,它会检查分区的谓词,并且只在适当的分区上执行 SQL。

分区还将所有数据保留在一个空间中。从概念上讲,可以将其视为具有相同结构的许多表,UNION ALL如果您要执行以下操作,它们之间具有隐式关系SELECT要从整个表中,则。除了“幕后”,Oracle 根据您指定的条件将实际行分类到正确的“表”中。任何不符合任何条件的行进入所谓的“默认”分区。

对于您想要做的事情,“范围分区”可能是一个好方法(因此您可以稍后添加更多租户),例如:

create table transaction (id, tenant_id, a, b, c, d)
partition by range(tenant_id)
partition p_tenant1 values less than (2) tablespace ts_tenant1
partition p_tenant2 values less than (3) tablespace ts_tenant2
partition p_tenant3 values less than (4) tablespace ts_tenant3
partition p_tenantd values less than (MAXVALUE) tablespace ts_default;
Run Code Online (Sandbox Code Playgroud)

然后后来

alter table transaction 
add partition p_tenant4 values less than (5) tablespace ts_tenant4;
Run Code Online (Sandbox Code Playgroud)

这将创建一些看起来和行为就像普通表一样的东西,但实际上tenant_id=1 的行将位于表空间 ts_tenant1 的分区中,并且查询将忽略所有其他分区。跨整个表的查询可以在每个分区上并行运行。如果在这种情况下tenant_id=4,该行将位于 ts_default 中,除非您添加新分区,但INSERT不会因为没有分区而被拒绝!

FWIW 在我的站点,我们在 40Tb DW 中使用分区表,您无需担心这种方法的扩展或执行,如果您选择了很好的分区策略(例如,您可以在租户 ID 上分区,然后在月上进行子分区),创建正确的索引,等等。

  • 我链接到的手册的“分区概念”部分是一个很好的起点。分区还可以让你做其他很酷的事情,比如你想清除超过某个年龄的数据,并且你有按日期分区,只需删除逻辑上是“TRUNCATE”而不是“DELETE”的分区,这样既方便又快捷。您可以使用两种索引,它们可以跨越整个表,或者是每个分区,因为要使用的正确索引取决于您的访问模式。例如,如果您有可以在一个分区内执行的查询,您可能需要分区索引。 (2认同)