表分区有以下优点:1、数据查询:数据被存储到多个文件上,减少了I/O负载,查询速度提高。
2、数据修剪:保存历史数据非常的理想。
3、备份:将大表的数据分成多个文件,方便备份和恢复。
4、并行性:可以同时向表中进行DML操作,并行性性能提高。
当表中的数据量不断增大,查询数据的速度就会变慢,应用程序的性能就会下降,这时就应该考虑对表进行分区。
表进行分区后,逻辑上表仍然是一张完整的表,只是将表中的数据在物理上存放到多个表空间(物理文件上),这样查询数据时,不至于每次都扫描整张表。
Oracle中提供了以下几种表分区:一、范围分区:这种类型的分区是使用列的一组值,通常将该列成为分区键。
示例1:假设有一个CUSTOMER表,表中有数据200000行,我们将此表通过CUSTOMER_ID进行分区,每个分区存储100000行,我们将每个分区保存到单独的表空间中,这样数据文件就可以跨越多个物理磁盘。
下面是创建表和分区的代码,如下:CREATE TABLE CUSTOMER(CUSTOMER_ID NUMBER NOT NULL PRIMARY KEY,FIRST_NAME VARCHAR2(30) NOT NULL,LAST_NAME VARCHAR2(30) NOT NULL,PHONE VARCHAR2(15) NOT NULL,EMAIL VARCHAR2(80),STATUS CHAR(1))PARTITION BY RANGE (CUSTOMER_ID)(PARTITION CUS_PART1 VALUES LESS THAN (100000) TABLESPACE CUS_TS01, PARTITION CUS_PART2 VALUES LESS THAN (200000) TABLESPACE CUS_TS02)在创建表进行分区时,表空间必须先存在,而且建议将不同的分区放入不同的表空间中。
示例2:假设有ORDER_ACTIVITIES表,每6个月对订单进行清理,我们可以按月份对表进行分区,分区代码如下:CREATE TABLE ORDER_ACTIVITIES(ORDER_ID NUMBER(7) NOT NULL,ORDER_DATE DATE,TOTAL_AMOUNT NUMBER,CUSTOTMER_ID NUMBER(7),PAID CHAR(1))PARTITION BY RANGE (ORDER_DATE)(PARTITION ORD_ACT_PART01 VALUES LESS THAN(TO_DATE('01-MAY-2003','DD-MON-YYYY')) TABLESPACE ORD_TS01,PARTITION ORD_ACT_PART02 VALUES LESS THAN(TO_DATE('01-JUN-2003','DD-MON-YYYY')) TABLESPACE ORD_TS02,PARTITION ORD_ACT_PART02 VALUES LESS THAN(TO_DATE('01-JUL-2003','DD-MON-YYYY')) TABLESPACE ORD_TS03)二、列表分区:该分区的特点是某列的值只有几个,基于这样的特点我们可以采用列表分区。
示例1:CREATE TABLE PROBLEM_TICKETS(PROBLEM_ID NUMBER(7) NOT NULL PRIMARY KEY,DESCRIPTION VARCHAR2(2000),CUSTOMER_ID NUMBER(7) NOT NULL,DATE_ENTERED DATE NOT NULL,STATUS VARCHAR2(20))PARTITION BY LIST (STATUS)(PARTITION PROB_ACTIVE VALUES ('ACTIVE') TABLESPACE PROB_TS01, PARTITION PROB_INACTIVE VALUES ('INACTIVE') TABLESPACE PROB_TS02)三、散列分区:这类分区是在列值上使用散列算法,以确定将行放入哪个分区中。
当列的值没有合适的条件时,建议使用散列分区。
请看下列示例:示例1:CREATE TABLE HASH_TABLE(COL NUMBER(8),INF VARCHAR2(100))PARTITION BY HASH (COL)(PARTITION PART01 TABLESPACE HASH_TS01,PARTITION PART02 TABLESPACE HASH_TS02,PARTITION PART03 TABLESPACE HASH_TS03)四、复合范围列表分区:这种分区是基于范围分区和列表分区,表首先按某列进行范围分区,然后再按某列进行列表分区,分区之中的分区被称为子分区。
示例1:CREATE TABLE SALES(PRODUCT_ID VARCHAR2(5),SALES_DATE DATE,SALES_COST NUMBER(10),STATUS VARCHAR2(20))PARTITION BY RANGE(SALES_DATE)SUBPARTITION BY LIST (STATUS)(PARTITION P1 VALUES LESS THAN (TO_DATE('2003-01-01','YYYY-MM-DD')) TABLESPACE P1_TS(SUBPARTITION P1SUB1 VALUES ('ACTIVE') TABLESPACE SUBP1_TS1, SUBPARTITION P1SUB2 VALUES ('INACTIVE') TABLESPACE SUBP1_TS2),PARTITION P2 VALUES LESS THAN (TO_DATE('2003-03-01','YYYY-MM-DD')) TABLESPACE P2_TS(SUBPARTITION P2SUB1 VALUES ('ACTIVE') TABLESPACE SUBP2_TS1, SUBPARTITION P2SUB2 VALUES ('INACTIVE') TABLESPACE SUBP2_TS2))示例2:使用TEMPLATE模板CREATE TABLE SALES(PRODUCT_ID VARCHAR2(5),SALES_DATE DATE,SALES_COST NUMBER(10),STATUS VARCHAR2(20))PARTITION BY RANGE(SALES_DATE)SUBPARTITION BY LIST (STATUS)SUBPARTITION TEMPLATE(SUBPARTITION SUB1 VALUES ('ACTIVE') TABLESPACE SUBP1_TS1, SUBPARTITION SUB2 VALUES ('INACTIVE') TABLESPACE SUBP2_TS2)(PARTITION P1 VALUES LESS THAN (TO_DATE('2003-01-01','YYYY-MM-DD')) TABLESPACE P1_TS,PARTITION P2 VALUES LESS THAN (TO_DATE('2003-03-01','YYYY-MM-DD')) TABLESPACE P2_TS)五、复合范围散列分区:这种分区是基于范围分区和散列分区,表首先按某列进行范围分区,然后再按某列进行散列分区。
与上面的定义方式非常的类似,在此不单独举例。
表分区对于用户来说是透明的,在插入数据时Oracle会自动判断插入的数据,然后放入相应的表分区中。
但有时想单独查询某个分区中的数据时,就必须手工指定分区的名称。
示例1:(此示例基于:四、复合范围列表分区的示例一)向SALES表插入记录,不必指定表分区。
INSERT INTO SALES VALUES('00001','01-1月-02',100,'ACTIVE')/INSERT INTO SALES VALUES('00002','01-1月-01',200,'ACTIVE')/INSERT INTO SALES VALUES('00003','01-2月-03',300,'INACTIVE')/INSERT INTO SALES VALUES('00004','04-2月-03',300,'INACTIVE')/INSERT INTO SALES VALUES('00005','04-2月-02',300,'INACTIVE')/不指定表分区查看SALES表信息:SELECT * FROM SALES; 结果如下所示:指定P1表分区查询SALES表信息:SELECT * FROM SALES PARTITION(P1); 结果如下所示:指定P1SUB1子分区查询SALES表信息:SELECT * FROM SALES SUBPARTITION(P1SUB1); 结果如下所示:示例2:(此示例基于:四、复合范围列表分区的示例二)示例2基于TEMPLATE模板的表分区,查询稍稍烦琐一点。
指定P1表分区查询SALES表信息:SELECT * FROM SALES PARTITION(P1); 结果如下所示,和刚才查询一致。
指定SUB1子分区查询SALES表信息:SELECT * FROM SALES SUBPARTITION(SUB1); 出现如下错误信息:怎么解决以上问题呢?我们通过sys模式查看分区信息的数据字典,如下:可以看出子分区不叫SUB1,而是P1_SUB1,重新查询信息,如下图所示:有关表分区的一些维护性操作:一、添加分区以下代码给SALES表添加了一个P3分区ALTER TABLE SALES ADD PARTITION P3 VALUES LESSTHAN(TO_DATE('2003-06-01','YYYY-MM-DD'));注意:以上添加的分区界限应该高于最后一个分区界限。