前言分区表作为Oracle三大组件之一,在Oracle数据库中,起着至关重要的作用。 分区表有什么优点?
在运维开发过程中,发现有部分应用厂商在建表之初并未考虑到数据体量的问题,导致很多大表都没有建成分区表。在系统运行过程中,这些表的数据量一直在增大,当达到一定体量时,我们就需要考虑对其进行分区表转换,以提高数据库的性能。那么,如何操作呢? 一、介绍普通表转换为分区表,Oracle给我们提供了哪些方式呢?
以上几种方式中,我比较常用的是:数据泵导入,子查询插入,在线重定义。这三种方式的共同点都是 需要提前创建分区表结构的中间表或者目标表。 二、脚本在长时间的重复性工作中,“懒癌”发作的我就想着是否能通过自动化的方式构建分区表的建表语句呢?然后我发现了 梁敬彬大佬的 普通表自动转化为按月分区表的脚本。 经加工和提炼,将以上脚本修改为契合自己使用的脚本:
可以获取 分区表脚本 以及博主的联系方式 par_tab_deal.pkg 的使用方式为: --创建日志表 PART_TAB_LOGcreate table PART_TAB_LOG( TAB_NAME VARCHAR2(200), DEAL_MODEL VARCHAR2(200), SQL_TEXT clob, DEAL_TIME DATE, remark VARCHAR2(4000), exec_order1 number, exec_order2 number);--执行分区表转换BEGIN pkg_deal_part_tab.p_main(p_tab => 't1', p_deal_flag => 1, p_parallel => 8, p_part_colum => 'created_date', p_part_nums => 24, p_tab_tablespace => 'users', p_idx_tablespace => 'users');END;--查看日志select DBMS_LOB.SUBSTR(sql_text,1000)||';' from part_tab_log t where tab_name='T1' order by exec_order1,exec_order2;select sql_text||';' from part_tab_log t where tab_name='T1' order by exec_order1,exec_order2; ctas_par.prc 的使用方式: --直接执行输出即可BEGIN ctas_par(p_tab => 't1', p_part_colum => 'created_date', p_part_nums => 24, p_tablespace => 'users');END; 三、实战应用1、创建测试表T1由于实验需要一张基础表,因此通过下方步骤创建表 T1: --删除t1表DROP TABLE t1 PURGE;--创建t1表CREATE TABLE t1 ( id NUMBER, description VARCHAR2(50), created_date DATE, CONSTRAINT t1_pk PRIMARY KEY (id));--创建索引CREATE INDEX t1_created_date_idx ON t1(created_date);--插入数据INSERT INTO t1SELECT level, 'Description for ' || level, ADD_MONTHS(TO_DATE('01-JAN-2017', 'DD-MON-YYYY'), -TRUNC(DBMS_RANDOM.value(1,4)-1)*12)FROM dualCONNECT BY level <= 10000;COMMIT; 2、创建procedure执行脚本创建procedure: select 'alter '||object_type||' '||owner||'.'||object_name||' compile;'from dba_objects twhere t.object_type='PROCEDURE'and t.object_name='CTAS_PAR' ;
3 执行procedure执行procedure生成CTAS创建分区表语句:
alter session set nls_date_format="yyyy-mm-dd hh24:mi:ss";BEGIN ctas_par(p_tab => 'T1', p_part_colum => 'CREATED_DATE', p_part_nums => 24, p_tablespace => 'USERS');END;
--分区表获取分区列最小记录日期:2015-01-01 00:00:00--分区表ctas创建的完整语句如下: create table T1partition BY RANGE(CREATED_DATE)(partition T1_P201501 values less than (TO_DATE(' 2015-02-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) tablespace USERS,partition T1_P201502 values less than (TO_DATE(' 2015-03-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) tablespace USERS,partition T1_P201503 values less than (TO_DATE(' 2015-04-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) tablespace USERS,partition T1_P201504 values less than (TO_DATE(' 2015-05-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) tablespace USERS,partition T1_P201505 values less than (TO_DATE(' 2015-06-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) tablespace USERS,partition T1_P201506 values less than (TO_DATE(' 2015-07-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) tablespace USERS,partition T1_P201507 values less than (TO_DATE(' 2015-08-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) tablespace USERS,partition T1_P201508 values less than (TO_DATE(' 2015-09-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) tablespace USERS,partition T1_P201509 values less than (TO_DATE(' 2015-10-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) tablespace USERS,partition T1_P201510 values less than (TO_DATE(' 2015-11-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) tablespace USERS,partition T1_P201511 values less than (TO_DATE(' 2015-12-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) tablespace USERS,partition T1_P201512 values less than (TO_DATE(' 2016-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) tablespace USERS,partition T1_P201601 values less than (TO_DATE(' 2016-02-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) tablespace USERS,partition T1_P201602 values less than (TO_DATE(' 2016-03-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) tablespace USERS,partition T1_P201603 values less than (TO_DATE(' 2016-04-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) tablespace USERS,partition T1_P201604 values less than (TO_DATE(' 2016-05-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) tablespace USERS,partition T1_P201605 values less than (TO_DATE(' 2016-06-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) tablespace USERS,partition T1_P201606 values less than (TO_DATE(' 2016-07-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) tablespace USERS,partition T1_P201607 values less than (TO_DATE(' 2016-08-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) tablespace USERS,partition T1_P201608 values less than (TO_DATE(' 2016-09-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) tablespace USERS,partition T1_P201609 values less than (TO_DATE(' 2016-10-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) tablespace USERS,partition T1_P201610 values less than (TO_DATE(' 2016-11-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) tablespace USERS,partition T1_P201611 values less than (TO_DATE(' 2016-12-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) tablespace USERS,partition T1_P201612 values less than (TO_DATE(' 2017-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) tablespace USERS,partition T1_MAX values less than (maxvalue) tablespace USERS) nologging parallel 4 enable row movement tablespace USERS as select /*+parallel(t,8)*/ * from T1_01 t where 1 = 2;--附加日志和取消并行alter table T1 logging;alter table T1 noparallel; 如果只是需要分区表的建表语句,这里已经可以很简单的拼接出来: create table T1( id NUMBER, description VARCHAR2(50), created_date DATE)partition BY RANGE(CREATED_DATE)(partition T1_P201501 values less than (TO_DATE(' 2015-02-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) tablespace USERS,partition T1_P201502 values less than (TO_DATE(' 2015-03-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) tablespace USERS,partition T1_P201503 values less than (TO_DATE(' 2015-04-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) tablespace USERS,partition T1_P201504 values less than (TO_DATE(' 2015-05-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) tablespace USERS,partition T1_P201505 values less than (TO_DATE(' 2015-06-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) tablespace USERS,partition T1_P201506 values less than (TO_DATE(' 2015-07-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) tablespace USERS,partition T1_P201507 values less than (TO_DATE(' 2015-08-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) tablespace USERS,partition T1_P201508 values less than (TO_DATE(' 2015-09-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) tablespace USERS,partition T1_P201509 values less than (TO_DATE(' 2015-10-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) tablespace USERS,partition T1_P201510 values less than (TO_DATE(' 2015-11-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) tablespace USERS,partition T1_P201511 values less than (TO_DATE(' 2015-12-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) tablespace USERS,partition T1_P201512 values less than (TO_DATE(' 2016-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) tablespace USERS,partition T1_P201601 values less than (TO_DATE(' 2016-02-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) tablespace USERS,partition T1_P201602 values less than (TO_DATE(' 2016-03-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) tablespace USERS,partition T1_P201603 values less than (TO_DATE(' 2016-04-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) tablespace USERS,partition T1_P201604 values less than (TO_DATE(' 2016-05-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) tablespace USERS,partition T1_P201605 values less than (TO_DATE(' 2016-06-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) tablespace USERS,partition T1_P201606 values less than (TO_DATE(' 2016-07-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) tablespace USERS,partition T1_P201607 values less than (TO_DATE(' 2016-08-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) tablespace USERS,partition T1_P201608 values less than (TO_DATE(' 2016-09-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) tablespace USERS,partition T1_P201609 values less than (TO_DATE(' 2016-10-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) tablespace USERS,partition T1_P201610 values less than (TO_DATE(' 2016-11-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) tablespace USERS,partition T1_P201611 values less than (TO_DATE(' 2016-12-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) tablespace USERS,partition T1_P201612 values less than (TO_DATE(' 2017-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) tablespace USERS,partition T1_MAX values less than (maxvalue) tablespace USERS)ENABLE ROW MOVEMENTTABLESPACE USERS; 4、CTAS创建分区表实际执行前,需要先将原表T1进行 rename 操作: alter table lucifer.T1 RENAME TO T1_01;
确保当前表T1已经rename为T1_01,执行CTAS创建分区表: COMMENT ON TABLE T1 IS '';COMMENT ON COLUMN T1.ID IS '';COMMENT ON COLUMN T1.CREATED_DATE IS '';COMMENT ON COLUMN T1.DESCRIPTION IS ''; 重命名原表的索引和约束: --重命名索引ALTER INDEX T1_CREATED_DATE_IDX RENAME TO T1_CREATED_DATE_IDX_01;ALTER INDEX T1_PK RENAME TO T1_PK_01;--重命名唯一约束ALTER TABLE T1_01 RENAME CONSTRAINT T1_PK TO T1_PK_01;
create index T1_CREATED_DATE_IDX on T1 (CREATED_DATE) tablespace users;alter table T1 add constraint T1_PK primary key (ID) using index tablespace users;
通过以下查询可以发现,数据已被按月分到对应分区下。 SELECT COUNT(1) FROM t1;SELECT COUNT(1) FROM t1 PARTITION(T1_P201501);SELECT COUNT(1) FROM t1 PARTITION(T1_P201601);SELECT COUNT(1) FROM t1 PARTITION(T1_MAX);
|
|
来自: LuciferLiu > 《待分类》