【问题标题】:Should I partition/subpartition my table?我应该对我的表进行分区/子分区吗?
【发布时间】:2016-11-26 12:42:44
【问题描述】:

案例

  1. 系统有dispositives,基本由id, type, name组成。
  2. 我可能有N个dispositives
  3. 我有一个表来存储所有log 中的dispositives。这是系统中最大的表。 (现在计算 100 英里的记录)
  4. log 表有:id_dispositive, date, status

问题

显然,这些庞大的数据会导致性能问题。我必须存储至少两个月的日志值..

今天我有这个dispositivestype

TYPE     COUNT
---------------
1         78956  
2         125161
3         13213
4         6112
5         25426
6         12314
7         1241
8         622

我还有一些业务逻辑来提供这个log 表。无论如何,这是我的想法:

我的“解决方案”

我正在考虑对这个log 表进行分区。以下是问题:

  1. 值得吗?
  2. 我应该按类型分区吗?
  3. 我应该按类型分区和按日期进行子分区吗?
  4. 我可以通过编程方式进行吗?

由于这种类型是动态的,用户可以删除/插入新的。

因此,如果他们删除某种类型,我必须删除该类型的所有日志。 就像他们插入某种类型一样,我必须注册(存储)该类型的所有日志。

根据 Francesco Serra 的回答进行编辑

我正在尝试像这样创建表:

create table log(
       id_dispositive    number,
       type       number,
       date_verification    date,
       status  number
)
partition by range (date_verification) 
subpartition by list (type)  
subpartition TEMPLATE (
    SUBPARTITION type1 VALUES (1),
    SUBPARTITION type2 VALUES (2),
    SUBPARTITION type3 VALUES (3),
    SUBPARTITION type4 VALUES (4)
)(                           
interval (numtoyminterval(1,'MONTH'))(
   partition p0816 values less than (to_date('01/09/2016','dd/mm/yyyy'))
));

我得到了:

ORA-14004: PARTITION keyword not found.

【问题讨论】:

  • 如果它不是日志表的一部分,你将如何按类型分区?如果您通常按日期访问,您至少应该尝试按日期分区。使用 DBMS_REDEFINITION 对表进行分区,以最大限度地减少停机时间。
  • 嗯,它有id_dispositive。我可以用它来获取它的类型......就像分区所有 X 类型的 id?
  • 您可以在数字列上创建自动分区(如果可能在正确的分区中添加新行,如果分区不存在,则创建它)。您可以使用模板添加子分区。如果您对此解决方案感兴趣,请告诉我。
  • 分区是否有帮助在很大程度上取决于您将要运行的查询类型。如果您需要加速的查询有一个类型谓词,那么它可能会有所帮助,如果您总是选择所有类型,那么它不会有任何区别。
  • TYPE 的基数是多少?也就是说,它有大量的唯一值还是少量的?如果每种类型只使用几次,那么按它进行分区可能无济于事 - 索引会更好。

标签: database oracle oracle11g


【解决方案1】:

你可以这样尝试:使用 INTERVAL 告诉 oracle 创建自动分区。您必须定义列(数字或日期)和间隔(在我的示例中为 1 个月)。 Oracle 会以相同的时间间隔(在本例中为同一个月)将所有行放入同一分区。如果分区不存在则创建。

create table log(
       id_dispositive    number,
       date    date,
       status  number,
       type    number
)
partition by range (date)                              
interval (numtoyminterval(1,'MONTH'))(
   partition p0701 values less than (to_date('2007-02-01','yyyy-mm-dd'))
);

同样可以对类型列进行。更多信息:http://www.oracle.com/technetwork/articles/sql/11g-partitioning-084209.html

每个分区都可以使用 TEMPLATE 键进行子分区。

create table log(
       id_dispositive    number,
       date    date,
       status  number,
       type    number
)
partition by range (date) interval (numtoyminterval(1,'MONTH'))
subpartition by list (type)  
subpartition TEMPLATE (
    SUBPARTITION types1 VALUES (1, 2) TABLESPACE tbs_1,
    SUBPARTITION types2 VALUES (3, 4) TABLESPACE tbs_1
)                          
(
   partition p0701 values less than (to_date('2007-02-01','yyyy-mm-dd'))
);

在这种情况下,您无法创建自动子分区,如果要添加新类型,则必须运行 alter table 语句。这里有更多信息; https://docs.oracle.com/cd/B28359_01/server.111/b32024/part_admin.htm#i1006655.

在你的例子中:

create table prova_log(
       id_dispositive    number,
       type       number,
       date_verification    date,
       status  number
)
partition by range (date_verification) interval (numtoyminterval(1,'MONTH'))
subpartition by list (type)  
subpartition TEMPLATE (
    SUBPARTITION type1 VALUES (1),
    SUBPARTITION type2 VALUES (2),
    SUBPARTITION type3 VALUES (3),
    SUBPARTITION type4 VALUES (4)
)                          
(
   partition p0816 values less than (to_date('01/09/2016','dd/mm/yyyy'))
);

如果您尝试插入:

insert into prova_log values (1,1,TO_DATE('10/10/2016','dd/mm/yyyy'),1);

你会在你的桌子上看到 2 个分区。

现在我已经测试过了!

【讨论】:

  • 动态插入呢?
  • 对不起,我不明白你的问题。无论如何:当您在表中插入新行时,Oracle 将其放入正确的分区/子分区中,如果该分区不存在,它将被创建。
  • 如果我想为每种类型创建一个子分区怎么办?我可以以编程方式做到这一点吗?不知何故,如果子分区不存在,oracle 创建?
  • 子分区不能动态创建。对于新的子分区,您必须执行 alter table 并修改模板定义。
  • 我只是尝试按照您的建议创建表格,我收到了ORA-14004 作为有问题的版本。
猜你喜欢
  • 2016-11-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-17
  • 1970-01-01
  • 2012-12-30
  • 2018-06-12
  • 1970-01-01
相关资源
最近更新 更多