oracle 大表时间分区

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了oracle 大表时间分区相关的知识,希望对你有一定的参考价值。

现有一张大表,需要按时间分区,每天一个分区,请问一次性建立多久的时间分区比较合适?
一个月,三个月还是一年?会对数据库造成什么影响.

要看应用的运行环境,如果是在线运营的生产系统,最好一个月建一次,每次40天左右。
这么做出于几点考虑:
1.oracle修改分区时会造成使用这张表的存储过程暂时失效,虽然Oracle会自动在存储过程失效后第一次执行时recompile,但毕竟要耗时间,如果对时间性能要求非常高、且并发频繁的环境,很容易出事
2.不要使用子分区,原因:维护过于麻烦。因为客户维护人员的技术水平不是你能掌握的
3.40天的设定主要是留有一个缓冲区,防止在应维护那天临时有事无法维护。留10天的缓冲,应能保证及时维护。
4.不建议设定为3个月或1年,那样空间浪费太大。
参考技术A 生产库是每天跑数据前第一步建分区,意思是每天建一个分区
你这样一下子建几十个还没用到的分区,对空间太浪费了
还有不建议用子分区的方法追问

因为生产上的表是不能每天改的,所以要提前建立一些分区,最多一个月更改一次生产上的表分区,
还有,为什么不建议用子分区呢?

参考技术B 用月份为主分区 用日期为子分区 对 数据应该是没有什么影响 。追问

子分区的写法能告诉一下么?
对数据是没有影响,但是分区多了肯定会占用数据库的存储,这个分区的数量,应该控制在什么范围之内呢,或者说,多少个分区会达到最优的效果呢.
这个数量肯定不是越多越好把.

追答

分区表语句:
CREATE TABLE DM_RPT_M_TELECOM_WWW_DEV (
MONTH_NO VARCHAR2(6) NOT NULL, --月份
PROV_ID VARCHAR2(3) NOT NULL, --省份 你可以直接改成日期
VALUE1 VARCHAR2(20),
VALUE2 VARCHAR2(20),
VALUE3 VARCHAR2(20),
VALUE4 VARCHAR2(20),
VALUE5 VARCHAR2(20),
VALUE6 VARCHAR2(20),
VALUE7 VARCHAR2(20)

)

PARTITION BY RANGE (MONTH_NO)
SUBPARTITION BY LIST (PROV_ID)
SUBPARTITION TEMPLATE(
SUBPARTITION SUBPART_010 VALUES ('010'),
SUBPARTITION SUBPART_011 VALUES ('011'),
·····························································,
SUBPARTITION SUBPART_097 VALUES ('097'),
SUBPARTITION SUBPARTDEFAULT VALUES (DEFAULT)
)
(
PARTITION PART_201001 VALUES LESS THAN ('201002'),
PARTITION PART_201002 VALUES LESS THAN ('201003'),
············· ·····························································,
PARTITION PART_201012 VALUES LESS THAN ('201101')
) ;

关于Oracle 分区实现和操作的几个问题

前提:手头上有一个大表,数据量非常大,打算用分区表。查询条件集中在其中两列,一列为ID,一列为时间Time,即每个ID点在不同时间有大量数据插入,形如“select .....from table_name where id=... and time>...and time<... ”的查询语句会经常用到;问题如下:
1.我想用组合分区,请问可以用“范围-范围分区”吗?即大分区用Time范围分区,子分区用ID范围分区。如果可以,用什么语句建分区表,请给出核发代码。如果不可以,请问用什么分区比较好?(为方便维护,大分区必须用时间Time)
2.请问如何查询子分区的数据。
是请给出核心代码,打错字,不好意思。

1. 组合分区表的创建方式("范围-哈稀"),见附1
2. 楼主的需求,即"范围-范围分区",在ORACLE 9i, 10g经过测试都是不能实现的
在附1的基础上修改为"范围-范围"组合分区,创建时报错:ORA-14151:无效的表分区方法
3. 关于sxdtgsh兄的回答,我测了
3.1 没有maxvalue上限分区设置,在插入超出分区的数据时会报错ORA-14400: 插入的分区关键字未映射到任何分区
3.2 按回答的语句创建分区表没有问题,但数据无法按照楼主的需求分布
====附1
附录:创建"范围-哈稀"组合分区表

CREATE TABLE TAB11 (ID NUMBER,DT DATE)
PARTITION BY RANGE (DT)
SUBPARTITION BY HASH (ID) SUBPARTITIONS 2 -- 自分区个数,可以不写,由系统判断
(
PARTITION Y2012 VALUES LESS THAN (TO_DATE('2013-01-01','YYYY-MM-DD'))
(
SUBPARTITION Y2012_H1
,SUBPARTITION Y2012_H2
)
,PARTITION Y2013 VALUES LESS THAN (TO_DATE('2014-01-01','YYYY-MM-DD'))
(
SUBPARTITION Y2013_H1
,SUBPARTITION Y2013_H2
)
,PARTITION YMAX VALUES LESS THAN (MAXVALUE)
(
SUBPARTITION YMAX_H1
,SUBPARTITION YMAX_H2
)
)
====附2,请楼主检查最后查询的数据分布

create table T_TEST
(
ID NUMBER(20) NOT NULL,
TIME DATE NOT NULL
)
partition by range(TIME, ID) -- 按时间、ID范围分区 这个例子是按年的
(
partition P_2012_10 values less than (to_date('2013-01-01','yyyy-MM-dd'), 10),
partition P_2012_20 values less than (to_date('2013-01-01','yyyy-MM-dd'), 20),
partition P_2012_MAX values less than (to_date('2013-01-01','yyyy-MM-dd'), MAXVALUE),
partition P_2013_10 values less than (to_date('2014-01-01','yyyy-MM-dd'), 10),
partition P_2013_20 values less than (to_date('2014-01-01','yyyy-MM-dd'), 20),
partition P_2013_MAX values less than (to_date('2014-01-01','yyyy-MM-dd'), MAXVALUE),
partition P_MAX values less than (MAXVALUE,MAXVALUE)
);
INSERT INTO T_TEST VALUES (1,TO_DATE('20121204 00:00:00','YYYYMMDD HH24:MI:SS'));
INSERT INTO T_TEST VALUES (12,TO_DATE('20121204 00:00:00','YYYYMMDD HH24:MI:SS'));
INSERT INTO T_TEST VALUES (32,TO_DATE('20121204 00:00:00','YYYYMMDD HH24:MI:SS'));
INSERT INTO T_TEST VALUES (2,TO_DATE('20131204 00:00:00','YYYYMMDD HH24:MI:SS'));
INSERT INTO T_TEST VALUES (12,TO_DATE('20131204 00:00:00','YYYYMMDD HH24:MI:SS'));
INSERT INTO T_TEST VALUES (33,TO_DATE('20131204 00:00:00','YYYYMMDD HH24:MI:SS'));
INSERT INTO T_TEST VALUES (3,TO_DATE('20141204 00:00:00','YYYYMMDD HH24:MI:SS'));
INSERT INTO T_TEST VALUES (23,TO_DATE('20141204 00:00:00','YYYYMMDD HH24:MI:SS'));
INSERT INTO T_TEST VALUES (43,TO_DATE('20151204 00:00:00','YYYYMMDD HH24:MI:SS'));
SELECT * FROM T_TEST;
SELECT * FROM T_TEST PARTITION(P_2012_10);
SELECT * FROM T_TEST PARTITION(P_2012_20);
SELECT * FROM T_TEST PARTITION(P_2012_MAX);
SELECT * FROM T_TEST PARTITION(P_2013_10);
SELECT * FROM T_TEST PARTITION(P_2013_20);
SELECT * FROM T_TEST PARTITION(P_2013_MAX);
SELECT * FROM T_TEST PARTITION(P_MAX);
参考技术A oracle 10g的组合分区只支持 range-list和range-hash。11g好像是可以range-range。如果id不多,可以用range-list。组合分区有时会导致数据字典异常大--数据库存在大量子分区的元数据,能不用就不用。表太大可以考虑分库分表,不是特别大就分区+分区索引。如果只有少数表需要做组合分区,倒可以考虑。
如果查询条件包含分区键,数据库会自动去分区找数据,也可以在查询表名后增加subpartition()来直接访问子分区数据
参考技术B --你要用time,id范围进行分区,只能用组合范围分区,只有大分区,没有子分区,下面的例子
create table T_TEST
(
ID NUMBER(20) NOT NULL,
TIME DATE NOT NULL
)
partition by range(TIME, ID) -- 按时间、ID范围分区 这个例子是按年的
(
partition P_2012_10 values less than (to_date('2013-01-01','yyyy-MM-dd'), 10),
partition P_2012_20 values less than (to_date('2013-01-01','yyyy-MM-dd'), 20),
partition P_2012_30 values less than (to_date('2013-01-01','yyyy-MM-dd'), 30),
partition P_2013_10 values less than (to_date('2014-01-01','yyyy-MM-dd'), 10),
partition P_2013_20 values less than (to_date('2014-01-01','yyyy-MM-dd'), 20),
partition P_2013_30 values less than (to_date('2014-01-01','yyyy-MM-dd'), 30)
);
--至于查询,如果你知道数据在那个分区里,可以指定分区查询,如果不知道,只要条件里有分区列,oracle会自动优化的。如果没有oralce会扫描全部分区,然后做all操作。

以上是关于oracle 大表时间分区的主要内容,如果未能解决你的问题,请参考以下文章

Oracle大表改为分区表及表空间切换方案

ORACLE 大表索引问题:数据量5亿+,做查询,按时间一个月分区,查询会用到3 4个字段,如何见索引

ORACLE表分区

Oracle中分区表中表空间属性

关于Oracle 分区实现和操作的几个问题

在 oracle 10g 中使用表分区