ORACLE的分区(Partitioning Option)是一种处理超大型表的技术。分区是一种“分而治之”的技术,通过将大表和索引分成可以管理的小块,从而避免了对每个表作为一个大的、单独的对象进行管理,为大量数据提供了可伸缩的性能。分区通过将操作分配给更小的存储单元,减少了需要进行管理操作的时间,并通过增强的并行处理提高了性能,通过屏蔽故障数据的分区,还增加了可用性。
分区对应用是透明的,可以通过标准的SQL语句对分区表进行操作。Oracle 的优化器在访问数据时会分析数据的分区情况,在进行查询时,那些不包含任何查询数据的分区将被忽略,从而大大提高系统的性能。
分区原则
1 .表分区的指南
a、表的大小
对于大表进行分区,将有益于大表操作的性能和大表的数据维护。通常当表的大小超过1.5GB-2GB,或对于OLTP系统,表的记录超过1000万,都应考虑对表进行分区。
b、数据访问特性
基于表的大部分查询应用,只访问表中少量的数据。对于这样表进行分区,可充分利用分区排除无关数据查询的特性。
c、数据维护
某些表的数据维护,经常按时间段删除成批的数据,例如按月删除历史数据。对于这样的表需要考虑进行分区,以满足维护的需要。因为删除(Delete)大量的数据,对系统开销很大,有时甚至是不可接受的。
d、只读数据
如果一个表中大部分数据都是只读数据,通过对表进行分区,可将只读数据存储在只读表空间中,对于数据库的备份是非常有益的。
e、并行数据操作(Parallel DML)
对于经常执行并行操作(如Parallel Insert,Parallel Update等)的表应考虑进行分区。
f、表的可用性
当对表的部分数据可用性要求很高时,应考虑进行表分区。
2 .选择分区字段(Partition Key)
当确定分区字段时,有两个主要因素特别需要考虑:
a、增强表的管理和维护性
通过Partition Key,可以使数据维护基于某个分区进行,如Drop或Truncate一个或多个分区。通过Paratition Key可控制只读的数据存储在相应的分区中,且这些分区存储在只读的表空间里,这将提高数据备份的性能。这类Partition Key通常与时间相关。
b、提高访问表的性能
通过Partition Key,可使查询的数据定位在一个或少量的分区中;这需要考虑最常用的查询条件。注意在考虑提高查询效率这个因素的同时,还应兼顾数据维护管理的因素,尽可能地避免相互间地冲突。
分区对应用是透明的,可以通过标准的SQL语句对分区表进行操作。Oracle 的优化器在访问数据时会分析数据的分区情况,在进行查询时,那些不包含任何查询数据的分区将被忽略,从而大大提高系统的性能。
分区原则
1 .表分区的指南
a、表的大小
对于大表进行分区,将有益于大表操作的性能和大表的数据维护。通常当表的大小超过1.5GB-2GB,或对于OLTP系统,表的记录超过1000万,都应考虑对表进行分区。
b、数据访问特性
基于表的大部分查询应用,只访问表中少量的数据。对于这样表进行分区,可充分利用分区排除无关数据查询的特性。
c、数据维护
某些表的数据维护,经常按时间段删除成批的数据,例如按月删除历史数据。对于这样的表需要考虑进行分区,以满足维护的需要。因为删除(Delete)大量的数据,对系统开销很大,有时甚至是不可接受的。
d、只读数据
如果一个表中大部分数据都是只读数据,通过对表进行分区,可将只读数据存储在只读表空间中,对于数据库的备份是非常有益的。
e、并行数据操作(Parallel DML)
对于经常执行并行操作(如Parallel Insert,Parallel Update等)的表应考虑进行分区。
f、表的可用性
当对表的部分数据可用性要求很高时,应考虑进行表分区。
2 .选择分区字段(Partition Key)
当确定分区字段时,有两个主要因素特别需要考虑:
a、增强表的管理和维护性
通过Partition Key,可以使数据维护基于某个分区进行,如Drop或Truncate一个或多个分区。通过Paratition Key可控制只读的数据存储在相应的分区中,且这些分区存储在只读的表空间里,这将提高数据备份的性能。这类Partition Key通常与时间相关。
b、提高访问表的性能
通过Partition Key,可使查询的数据定位在一个或少量的分区中;这需要考虑最常用的查询条件。注意在考虑提高查询效率这个因素的同时,还应兼顾数据维护管理的因素,尽可能地避免相互间地冲突。
Oracle中提供了对表进行分区的机制,通过表分区,可以将表空间中数据按照某种方式分别存放到特定的分区中。表分区的作用:平衡IO操作,分区均匀,提高效率。
Oracle中表分区方法有:范围分区法、散列分区法、复合分区法、列表分区法。
范围分区:语法 Partition by range(); 适合数值型或日期型
示例:
1
create
table
Student
2 (
3 Studentid integer not null ,
4 Studentname varchar2 ( 20 ),
5 Score integer
6 )
7 Partition by range(Score)
8 (
9 Partition p1 values less than( 60 ),
10 Partition p2 values less than( 75 ),
11 Partition p3 values less than( 85 ),
12 Partition p4 values less than(maxvalue)
13 ) ;
2 (
3 Studentid integer not null ,
4 Studentname varchar2 ( 20 ),
5 Score integer
6 )
7 Partition by range(Score)
8 (
9 Partition p1 values less than( 60 ),
10 Partition p2 values less than( 75 ),
11 Partition p3 values less than( 85 ),
12 Partition p4 values less than(maxvalue)
13 ) ;
散列分区法:根据Oracle内部散列算法存储,语法 Partition by hash();
实例:
1
create
table
department
2 (
3 Deptno int ,
4 Deptname varchar2 ( 24 )
5 )
6 Partition by hash(deptno)
7 (
8 Partition p1,
9 Partition p2
10 );
2 (
3 Deptno int ,
4 Deptname varchar2 ( 24 )
5 )
6 Partition by hash(deptno)
7 (
8 Partition p1,
9 Partition p2
10 );
复合分区法:由上面两种方法复合而成
示例:
1
create
table
salgrade
2 (
3 grade number ,
4 losal number ,
5 hisal number
6 )
7 Partition by range(grade)
8 Subpartition by hash(losal,hisal)
9 (
10 Partition p1 values less than( 10 ),
11 (subpartition sp1,subpartition sp2),
12 Partition p2 values less than( 20 ),
13 (subpartition sp3,subpartition sp4)
14 )
2 (
3 grade number ,
4 losal number ,
5 hisal number
6 )
7 Partition by range(grade)
8 Subpartition by hash(losal,hisal)
9 (
10 Partition p1 values less than( 10 ),
11 (subpartition sp1,subpartition sp2),
12 Partition p2 values less than( 20 ),
13 (subpartition sp3,subpartition sp4)
14 )
列表分区法:适合字符型 语法Partition by list()
实例:
1
create
table
customer
2 (
3 custNo int ,
4 custname varchar ( 20 ),
5 custState varchar ( 20 )
6 )
7 Partition by list(custState)
8 (
9 Partition saia values ( ' 中国 ' , ' 韩国 ' , ' 日本 ' ),
10 Partition Europe values ( ' 英国 ' , ' 俄国 ' , ' 法国 ' ),
11 Partition ameria values ( ' 美国 ' , ' 加拿大 ' , ' 墨西哥 ' ),
12 );
13
2 (
3 custNo int ,
4 custname varchar ( 20 ),
5 custState varchar ( 20 )
6 )
7 Partition by list(custState)
8 (
9 Partition saia values ( ' 中国 ' , ' 韩国 ' , ' 日本 ' ),
10 Partition Europe values ( ' 英国 ' , ' 俄国 ' , ' 法国 ' ),
11 Partition ameria values ( ' 美国 ' , ' 加拿大 ' , ' 墨西哥 ' ),
12 );
13
表分区维护:
添加分区:alter table student add partition p5 values less than(120);
删除分区:alter table student drop partition p4;
截断分区:alter table student truncate partition p5;
合并分区:alter table student merge partitions p3,p4 into partition p6;
分区的应用举例:
1
、分区表的建立:
某公司的每年产生巨大的销售记录,DBA向公司建议每季度的数据放在一个分区内,以下示范的是该公司1999年的数据(假设每月产生30M的数据),操作如下:
STEP1、建立表的各个分区的表空间:
CREATE TABLESPACE ts_sale1999q1
DATAFILE ‘ / u1 / oradata / sales / sales1999_q1.dat’
SIZE 100M
DEFAULT STORAGE (INITIAL 30m NEXT 30m MINEXTENTS 3 PCTINCREASE 0 )
CREATE TABLESPACE ts_sale1999q2
DATAFILE ‘ / u1 / oradata / sales / sales1999_q2.dat’
SIZE 100M
DEFAULT STORAGE (INITIAL 30m NEXT 30m MINEXTENTS 3 PCTINCREASE 0 )
CREATE TABLESPACE ts_sale1999q3
DATAFILE ‘ / u1 / oradata / sales / sales1999_q3.dat’
SIZE 100M
DEFAULT STORAGE (INITIAL 30m NEXT 30m MINEXTENTS 3 PCTINCREASE 0 )
CREATE TABLESPACE ts_sale1999q4
DATAFILE ‘ / u1 / oradata / sales / sales1999_q4.dat’
SIZE 100M
DEFAULT STORAGE (INITIAL 30m NEXT 30m MINEXTENTS 3 PCTINCREASE 0 )
STEP2、建立基于分区的表:
CREATE TABLE sales
(invoice_no NUMBER,
...
sale_date DATE NOT NULL )
PARTITION BY RANGE (sale_date)
(PARTITION sales1999_q1
VALUES LESS THAN (TO_DATE(‘ 1999 - 04 - 01 ’,’YYYY - MM - DD’)
TABLESPACE ts_sale1999q1,
PARTITION sales1999_q2
VALUES LESS THAN (TO_DATE(‘ 1999 - 07 - 01 ’,’YYYY - MM - DD’)
TABLESPACE ts_sale1999q2,
PARTITION sales1999_q3
VALUES LESS THAN (TO_DATE(‘ 1999 - 10 - 01 ’,’YYYY - MM - DD’)
TABLESPACE ts_sale1999q3,
PARTITION sales1999_q4
VALUES LESS THAN (TO_DATE(‘ 2000 - 01 - 01 ’,’YYYY - MM - DD’)
TABLESPACE ts_sale1999q4 );
2 、分区表的扩容:
到了1999年年底,DBA应向表中加入2000年的表空间,同样是每季度一个表空间,由于公司业务欣欣向荣,预计每个分区为40M,操作如下。
STEP1、建立表空间:
CREATE TABLESPACE ts_sale2000q1
DATAFILE ‘ / u1 / oradata / sales / sales2000_q1.dat’
SIZE 130M
DEFAULT STORAGE (INITIAL 40m NEXT 40m MINEXTENTS 3 PCTINCREASE 0 )
其他表空间ts_sale2000q2,ts_sale2000q3,ts_sales2000q4如法炮制。
STEP2、为表添加表空间:
ALTER TABLE sales
ADD PARTITION sales2000_q1
VALUES LESS THAN (TO_DATE(‘ 2000 - 04 - 01 ’,’YYYY - MM - DD’)
TABLESPACE ts_sale2000q1;
其他分区sales2000_q1,sales2000_q1,sales2000_q1如法炮制。
3 、删除不必要的分区:
公司规定:销售的明细数据两年内必须保存在线。到2001年,DBA必须将1999年的数据备份(备份方法见5、EXPORT分区),将1999年的分区删除,将空间供后来的数据使用。如此循环,永远保持两年的销售数据在线。
STEP1、DROP 分区:
ALTER TABLE sales
DROP PARTION sales1999_q1;
ALTER TABLE sales
DROP PARTION sales1999_q2;
ALTER TABLE sales
DROP PARTION sales1999_q3;
ALTER TABLE sales
DROP PARTION sales1999_q4;
STEP2、利用操作系统的工具删除以上表空间占用的文件(表空间基于裸设备无须次步),UNIX系统为例:
oracle$ rm / u1 / oradata / sales / sales1999_q1.dat
oracle$ rm / u1 / oradata / sales / sales1999_q2.dat
oracle$ rm / u1 / oradata / sales / sales1999_q3.dat
oracle$ rm / u1 / oradata / sales / sales1999_q4.dat
4 、分区的其他操作:
分区的其他操作包括截短分区(truncate),将存在的分区划分为多个分区(split),交换分区(exchange),重命名(rename),为分区建立索引等。DBA可以根据适当的情况使用。
以下仅说明分裂分区(split),例如该公司1999年第四季度销售明细数据急剧增加(因为庆国庆、迎千禧、贺回归),DBA向公司建议将第四季度的分区划分为两个分区,每个分区放两个月份的数据,操作如下:
STEP1、按( 1 )的方法建立两个分区的表空间ts_sales1999q4p1,
ts_sales1999q4p2;
STEP2、给表添加两个分区sales1999_q4_p1,sales1999_q4_p2;
STEP3、分裂分区:
ALTER TABLE sales
SPLIT PARTITON sales1999_q4
AT TO_DATE (‘ 1999 - 11 - 01 ’,’YYYY - MM - DD’)
INTO (partition sales1999_q4_p1, partition sales1999_q4_p2)
5 、查看分区信息:
DBA要查看表的分区信息,可查看数据字典USER_EXTENTS,操作如下:
SVRMGRL > SELECT * FROM user_extents WHERE SEGMENT_NAME = ’SALES’;
SEGMENT_NA PARTITION_ SEGMENT_TYPE TABLESPACE
---------- ------------ --------------- --------------
SALES SALES1999_Q1 TABLE PARTITION TS_SALES1999Q1
SALES SALES1999_Q2 TABLE PARTITION TS_SALES1999Q2
SALES SALES1999_Q3 TABLE PARTITION TS_SALES1999Q3
SALES SALES1999_Q4 TABLE PARTITION TS_SALES1999Q4
SALES SALES2000_Q1 TABLE PARTITION TS_SALES1999Q1
SALES SALES2000_Q2 TABLE PARTITION TS_SALES1999Q2
SALES SALES2000_Q3 TABLE PARTITION TS_SALES1999Q3
SALES SALES2000_Q4 TABLE PARTITION TS_SALES1999Q4
5 、EXPORT分区:
ORACLE8的EXPORT 工具可在表的分区以及导出数据,例如到2001年,DBA必须将1999年的数据按分区导出,操作如下:
oracle$ exp sales / sales_password tables = sales:sales1999_q1 rows = Y
file = sales1999_q1.dmp
oracle$ exp sales / sales_password tables = sales:sales1999_q2 rows = Y
file = sales1999_q2.dmp
oracle$ exp sales / sales_password tables = sales:sales1999_q3 rows = Y
file = sales1999_q3.dmp
oracle$ exp sales / sales_password tables = sales:sales1999_q4 rows = Y
file = sales1999_q4.dmp
6 、IMPORT分区:
ORACLE8的IMPORT 工具可在表的分区以及导入数据,例如在2001年,用户要查看1999年的数据,DBA必须导入1999年的数据,使之在线,操作如下:
STEP1、建立表的1999年的四个表空间和相应的分区,参照( 2 );
STEP2、导入数据:
oracle$ imp sales / sales_password FILE = sales1999_q1.dmp
TABLES = (sales:sales1999_q1) IGNORE = y
oracle$ imp sales / sales_password FILE = sales1999_q2.dmp
TABLES = (sales:sales1999_q2) IGNORE = y
oracle$ imp sales / sales_password FILE = sales1999_q3.dmp
TABLES = (sales:sales1999_q3) IGNORE = y
oracle$ imp sales / sales_password FILE = sales1999_q4.dmp
TABLES =
某公司的每年产生巨大的销售记录,DBA向公司建议每季度的数据放在一个分区内,以下示范的是该公司1999年的数据(假设每月产生30M的数据),操作如下:
STEP1、建立表的各个分区的表空间:
CREATE TABLESPACE ts_sale1999q1
DATAFILE ‘ / u1 / oradata / sales / sales1999_q1.dat’
SIZE 100M
DEFAULT STORAGE (INITIAL 30m NEXT 30m MINEXTENTS 3 PCTINCREASE 0 )
CREATE TABLESPACE ts_sale1999q2
DATAFILE ‘ / u1 / oradata / sales / sales1999_q2.dat’
SIZE 100M
DEFAULT STORAGE (INITIAL 30m NEXT 30m MINEXTENTS 3 PCTINCREASE 0 )
CREATE TABLESPACE ts_sale1999q3
DATAFILE ‘ / u1 / oradata / sales / sales1999_q3.dat’
SIZE 100M
DEFAULT STORAGE (INITIAL 30m NEXT 30m MINEXTENTS 3 PCTINCREASE 0 )
CREATE TABLESPACE ts_sale1999q4
DATAFILE ‘ / u1 / oradata / sales / sales1999_q4.dat’
SIZE 100M
DEFAULT STORAGE (INITIAL 30m NEXT 30m MINEXTENTS 3 PCTINCREASE 0 )
STEP2、建立基于分区的表:
CREATE TABLE sales
(invoice_no NUMBER,
...
sale_date DATE NOT NULL )
PARTITION BY RANGE (sale_date)
(PARTITION sales1999_q1
VALUES LESS THAN (TO_DATE(‘ 1999 - 04 - 01 ’,’YYYY - MM - DD’)
TABLESPACE ts_sale1999q1,
PARTITION sales1999_q2
VALUES LESS THAN (TO_DATE(‘ 1999 - 07 - 01 ’,’YYYY - MM - DD’)
TABLESPACE ts_sale1999q2,
PARTITION sales1999_q3
VALUES LESS THAN (TO_DATE(‘ 1999 - 10 - 01 ’,’YYYY - MM - DD’)
TABLESPACE ts_sale1999q3,
PARTITION sales1999_q4
VALUES LESS THAN (TO_DATE(‘ 2000 - 01 - 01 ’,’YYYY - MM - DD’)
TABLESPACE ts_sale1999q4 );
2 、分区表的扩容:
到了1999年年底,DBA应向表中加入2000年的表空间,同样是每季度一个表空间,由于公司业务欣欣向荣,预计每个分区为40M,操作如下。
STEP1、建立表空间:
CREATE TABLESPACE ts_sale2000q1
DATAFILE ‘ / u1 / oradata / sales / sales2000_q1.dat’
SIZE 130M
DEFAULT STORAGE (INITIAL 40m NEXT 40m MINEXTENTS 3 PCTINCREASE 0 )
其他表空间ts_sale2000q2,ts_sale2000q3,ts_sales2000q4如法炮制。
STEP2、为表添加表空间:
ALTER TABLE sales
ADD PARTITION sales2000_q1
VALUES LESS THAN (TO_DATE(‘ 2000 - 04 - 01 ’,’YYYY - MM - DD’)
TABLESPACE ts_sale2000q1;
其他分区sales2000_q1,sales2000_q1,sales2000_q1如法炮制。
3 、删除不必要的分区:
公司规定:销售的明细数据两年内必须保存在线。到2001年,DBA必须将1999年的数据备份(备份方法见5、EXPORT分区),将1999年的分区删除,将空间供后来的数据使用。如此循环,永远保持两年的销售数据在线。
STEP1、DROP 分区:
ALTER TABLE sales
DROP PARTION sales1999_q1;
ALTER TABLE sales
DROP PARTION sales1999_q2;
ALTER TABLE sales
DROP PARTION sales1999_q3;
ALTER TABLE sales
DROP PARTION sales1999_q4;
STEP2、利用操作系统的工具删除以上表空间占用的文件(表空间基于裸设备无须次步),UNIX系统为例:
oracle$ rm / u1 / oradata / sales / sales1999_q1.dat
oracle$ rm / u1 / oradata / sales / sales1999_q2.dat
oracle$ rm / u1 / oradata / sales / sales1999_q3.dat
oracle$ rm / u1 / oradata / sales / sales1999_q4.dat
4 、分区的其他操作:
分区的其他操作包括截短分区(truncate),将存在的分区划分为多个分区(split),交换分区(exchange),重命名(rename),为分区建立索引等。DBA可以根据适当的情况使用。
以下仅说明分裂分区(split),例如该公司1999年第四季度销售明细数据急剧增加(因为庆国庆、迎千禧、贺回归),DBA向公司建议将第四季度的分区划分为两个分区,每个分区放两个月份的数据,操作如下:
STEP1、按( 1 )的方法建立两个分区的表空间ts_sales1999q4p1,
ts_sales1999q4p2;
STEP2、给表添加两个分区sales1999_q4_p1,sales1999_q4_p2;
STEP3、分裂分区:
ALTER TABLE sales
SPLIT PARTITON sales1999_q4
AT TO_DATE (‘ 1999 - 11 - 01 ’,’YYYY - MM - DD’)
INTO (partition sales1999_q4_p1, partition sales1999_q4_p2)
5 、查看分区信息:
DBA要查看表的分区信息,可查看数据字典USER_EXTENTS,操作如下:
SVRMGRL > SELECT * FROM user_extents WHERE SEGMENT_NAME = ’SALES’;
SEGMENT_NA PARTITION_ SEGMENT_TYPE TABLESPACE
---------- ------------ --------------- --------------
SALES SALES1999_Q1 TABLE PARTITION TS_SALES1999Q1
SALES SALES1999_Q2 TABLE PARTITION TS_SALES1999Q2
SALES SALES1999_Q3 TABLE PARTITION TS_SALES1999Q3
SALES SALES1999_Q4 TABLE PARTITION TS_SALES1999Q4
SALES SALES2000_Q1 TABLE PARTITION TS_SALES1999Q1
SALES SALES2000_Q2 TABLE PARTITION TS_SALES1999Q2
SALES SALES2000_Q3 TABLE PARTITION TS_SALES1999Q3
SALES SALES2000_Q4 TABLE PARTITION TS_SALES1999Q4
5 、EXPORT分区:
ORACLE8的EXPORT 工具可在表的分区以及导出数据,例如到2001年,DBA必须将1999年的数据按分区导出,操作如下:
oracle$ exp sales / sales_password tables = sales:sales1999_q1 rows = Y
file = sales1999_q1.dmp
oracle$ exp sales / sales_password tables = sales:sales1999_q2 rows = Y
file = sales1999_q2.dmp
oracle$ exp sales / sales_password tables = sales:sales1999_q3 rows = Y
file = sales1999_q3.dmp
oracle$ exp sales / sales_password tables = sales:sales1999_q4 rows = Y
file = sales1999_q4.dmp
6 、IMPORT分区:
ORACLE8的IMPORT 工具可在表的分区以及导入数据,例如在2001年,用户要查看1999年的数据,DBA必须导入1999年的数据,使之在线,操作如下:
STEP1、建立表的1999年的四个表空间和相应的分区,参照( 2 );
STEP2、导入数据:
oracle$ imp sales / sales_password FILE = sales1999_q1.dmp
TABLES = (sales:sales1999_q1) IGNORE = y
oracle$ imp sales / sales_password FILE = sales1999_q2.dmp
TABLES = (sales:sales1999_q2) IGNORE = y
oracle$ imp sales / sales_password FILE = sales1999_q3.dmp
TABLES = (sales:sales1999_q3) IGNORE = y
oracle$ imp sales / sales_password FILE = sales1999_q4.dmp
TABLES =