11.1 分区技术概述
11.2 创建表分区
11.2.1 范围分区
关键字range
当表结构采用范围分区时,首先考虑分区的列应该符合范围分区的方法,其次要考虑列的数据值的取值范围,最后考虑列的边界问题。
SQL> create table ware_retail_part
2 (
3 id integer primary key,
4 retail_date date,
5 ware_name varchar2(50)
6 )
7 partition by range(retail_date)
8 (
9 partition par_01 values less than(to_date('2011-04-01','yyyy-mm-dd')) tablespace TBS_TEST_1,
10 partition par_02 values less than(to_date('2011-07-01','yyyy-mm-dd')) tablespace TBS_TEST_2,
11 partition par_03 values less than(to_date('2011-10-01','yyyy-mm-dd')) tablespace TBS_TEST_3,
12 partition par_04 values less than(to_date('2012-01-01','yyyy-mm-dd')) tablespace TBS_TEST_4
13 );
Table created
create table ware_retail_part
(
id integer primary key,
retail_date date,
ware_name varchar2(50)
)
partition by range(retail_date)
(
partition par_01 values less than(to_date('2011-04-01','yyyy-mm-dd')) tablespace TBS_TEST_1,
partition par_02 values less than(to_date('2011-07-01','yyyy-mm-dd')) tablespace TBS_TEST_2,
partition par_03 values less than(to_date('2011-10-01','yyyy-mm-dd')) tablespace TBS_TEST_3,
partition par_04 values less than(to_date('2012-01-01','yyyy-mm-dd')) tablespace TBS_TEST_4
);
insert into ware_retail_part
values(1,to_date('2011-01-20','yyyy-mm-dd'),'ipad');
insert into ware_retail_part
values(2,to_date('2011-04-15','yyyy-mm-dd'),'iphone');
insert into ware_retail_part
values(3,to_date('2011-07-25','yyyy-mm-dd'),'ipod');
通过分区表查询数据:
SQL> select * from ware_retail_part partition(par_02);
ID RETAIL_DATE WARE_NAME
--------------------------------------- ----------- --------------------------------------------------
2 2011-4-15 iphone
range分区的字段可以是两个或者多个
create table ware_retail_part2
(
id integer primary key,
retail_date date,
ware_name varchar2(50)
)
partition by range(id,retail_date)
(
partition par_01 values less than(10000,to_date('2011-12-01','yyyy-mm-dd')) tablespace TBS_TEST_1,
partition par_02 values less than(20000,to_date('2012-12-01','yyyy-mm-dd')) tablespace TBS_TEST_2,
partition par_03 values less than(maxvalue,maxvalue) tablespace TBS_TEST_3,
);
11.2.2 散列分区(HASH分区)
create table ware_retail_part3
(
id integer primary key,
retail_date date,
ware_name varchar2(50)
)
partition by hash(id)
(
partition par_01 tablespace TBS_TEST_1,
partition par_02 tablespace TBS_TEST_2
);
SQL> insert into ware_retail_part3
2 values(99,to_date('2011-11-11','yyyy-mm-dd'),'mac');
1 row inserted
SQL> select * from ware_retail_part3;
ID RETAIL_DATE WARE_NAME
--------------------------------------- ----------- --------------------------------------------------
99 2011-11-11 mac
SQL> select * from ware_retail_part3 partition(par_01);
ID RETAIL_DATE WARE_NAME
--------------------------------------- ----------- --------------------------------------------------
SQL> select * from ware_retail_part3 partition(par_02);
ID RETAIL_DATE WARE_NAME
--------------------------------------- ----------- --------------------------------------------------
99 2011-11-11 mac
由系统自动分配分区名:
create table ware_retail_part4
(
id integer primary key,
retail_date date,
ware_name varchar2(50)
)
partition by hash(id)
partitions 2
store in(TBS_TEST_1,TBS_TEST_2);
指定所有分区的初始分配空间
create table ware_retail_part5
(
id integer primary key,
retail_date date,
ware_name varchar2(50)
)
storage(initial 2048k)
partition by hash(id)
(
partition par_01 tablespace TBS_TEST_1,
partition par_02 tablespace TBS_TEST_2
);
11.2.3 列表分区
如果表的某个列的值可以枚举,则可以考虑对表进行列表分区
create table clients
(
id integer primary key,
name varchar2(50),
province varchar2(50)
)
partition by list(province)
(
partition shangdong values('山东'),
partition guangdong values('广东'),
partition yunan values('云南')
);
SQL> insert into clients
2 values(19,'stone','云南');
1 row inserted
SQL> col id for a10;
SQL> col name for a10;
SQL> col province for a10;
SQL> select * from clients partition(yunan);
ID NAME PROVINCE
---------- ---------- ----------
19 stone 云南
11.2.4 组合分区
oracle支持以下组合分区方案
a、范围-范围分区
b、范围-散列分区
c、范围-列表分区
d、列表-列表分区
e、列表-范围分区
f、列表-散列分区
create table person2
(
id number primary key,
name varchar2(50),
sex varchar2(2)
)
partition by range(id)
subpartition by hash(name)
subpartitions 2 store in(TBS_TEST_1,TBS_TEST_2)
(
partition par1 values less than(5000),
partition par2 values less than(10000),
partition par3 values less than(maxvalue)
);
11.2.5 Interval分区
范围分区的一种增强功能,只有最开始的分区是永久分区,随着数据的增多会分配更多的部分,并自动创建新的分区和本地索引。
create table salerecord
(
id number primary key,
goodsname varchar2(50),
saledate date,
quantity number
)
partition by range(saledate)
interval(numtoyminterval(1,'year'))
(
partition par_first values less than(to_date('2012-01-01','yyyy-mm-dd'))
);
对于已经进行了范围分区的表,可以通过使用alter table命令的set interval选项扩展成为interval分区。
11.3 表分区策略
1、识别大表(analyze table)
2、大表如何分区,一般按时间分区
3、分区的表空间规划
11.4 管理表分区
11.4.1 添加表分区
alter table clients
add partition hebei values('河北')
storage(initial 10k next 20k) tablespace TBS_TEST_1
nologging;
11.4.2 合并分区
1、合并散列分区
alter table ... coalesce partition
SQL> alter table ware_retail_part4 coalesce partition;
Table altered
2、合并复合分区
alter table ... modify
SQL> alter table person2 modify partition par3 coalesce subpartition;
Table altered
11.4.3 删除分区
可以从范围分区或复合分区中删除分区,但是散列分区和复合分区的散列子分区,只能通过合并来达到删除的目的
1、删除一个表分区
删除分区时,该分区的数据也被删除,如果不希望删除数据,则必须采用合并分区的方法。
alter table ... drop partition
SQL> alter table ware_retail_part drop partition par_04;
Table altered
2、删除有数据和全局索引的表分区
如果分区表中包含了数据,并且在表中定义了一个或者多个全局索引,可以使用alter table ... drop partition语句删除表分区,这样可以保留全局索引,但是索引会被标识为不可用(unusable),因而需要重建索引。
SQL> alter table ware_retail_part drop partition par_03;
Table altered
3、使用delete和alter table ... drop partition语句
先执行delete语句删除分区的所有数据行
delete from ware_retail_part where retail_date >= to_date('2011-07-01','yyyy-mm-dd');
SQL> alter table ware_retail_part drop partition par_02;
Table altered
4、删除具有完整性约束的分区
两种方法:
(1)首先禁止完整性约束,然后执行alter table ... drop partition,最后激活约束
alter table books_1 disable constraints book_pk;
alter table books_1 drop partition part_01;
alter table books_1 enable constraints book_pk;
(2)首先执行delete语句删除分区中的行,然后用alter table ... drop partition语句删除分区
delete from books_1 where bookno<1000;
alter table books_1 drop partition part_01;
11.4.4 并入分区
使用merge partition语句,不能对hash分区执行merge partition语句
(1)创建销售记录表并分区
create table sales
(
id number primary key,
goodsname varchar2(10),
saledate date
)
partition by range(saledate)
(
partition part_sea1 values less than(to_date('2011-04-01','yyyy-mm-dd')) tablespace TBS_TEST_1,
partition part_sea2 values less than(to_date('2011-07-01','yyyy-mm-dd')) tablespace TBS_TEST_2,
partition part_sea3 values less than(to_date('2011-10-01','yyyy-mm-dd')) tablespace TBS_TEST_3,
partition part_sea4 values less than(to_date('2012-01-01','yyyy-mm-dd')) tablespace TBS_TEST_4
);
(2)创建局部索引
create index index_3_4 on sales(saledate)
local
(
partition part_sea1 tablespace TBS_TEST_1,
partition part_sea2 tablespace TBS_TEST_2,
partition part_sea3 tablespace TBS_TEST_3,
partition part_sea4 tablespace TBS_TEST_4
);
(3)使用alter table ... merge partition把第三个分区并入到第四个分区
alter table sales merge partitions part_sea3,part_sea4 into partition part_sea4;
(4)重新建立局部索引
SQL> alter table sales modify partition part_sea4 rebuild unusable local indexes;
Table altered
11.5 创建索引分区
一般来说,如果索引对应的表数据量非常大,比如几百万甚至上千万条数据,建议对索引进行分区。
11.5.1 索引分区概述
11.5.2 本地索引分区
本地索引分区就是使用和分区表同样的分区键进行分区的索引,也就是说,索引分区所采用的列与该表的分区所采用的列是相同的
(1)准备好所需要的表空间
create tablespace ts_1 datafile '/ora/app/oracle/oradata/stone1/ts1.dbf'
size 10m
extent management local autoallocate;
create tablespace ts_2 datafile '/ora/app/oracle/oradata/stone1/ts2.dbf'
size 10m
extent management local autoallocate;
create tablespace ts_3 datafile '/ora/app/oracle/oradata/stone1/ts3.dbf'
size 10m
extent management local autoallocate;
(2)创建分区表
create table studentgrade
(
id number primary key,
name varchar2(10),
subject varchar2(10),
grade number
)
partition by range(grade)
(
partition par_nopass values less than(60) tablespace ts_1,
partition par_pass values less than (80) tablespace ts_2,
partition par_good values less than(maxvalue) tablespace ts_3
);
(3)创建本地索引分区
create index grade_index on studentgrade(grade)
local
(
partition p1 tablespace ts_1,
partition p2 tablespace ts_2,
partition p3 tablespace ts_3
);
(4)查看索引分区信息
SQL> select partition_name,tablespace_name from dba_ind_partitions where index_name='GRADE_INDEX';
PARTITION_NAME TABLESPACE_NAME
------------------------------ ------------------------------
P1 TS_1
P2 TS_2
P3 TS_3
11.5.3 全局索引分区
全局索引就是没有与分区表有相同分区键的分区索引。当分区中出现许多事务并且要保证所有分区中的数据记录唯一时,采用全局索引分区
无论表是否采用分区,都可以对表采用全局索引分区。此外,不能对cluster表,位图索引采用全局索引分区。
create table books
(
isbn varchar2(50) primary key,
name varchar2(50),
author varchar2(50),
version integer,
pbdate date,
saleprice number
);
create index index_saleprice on books(saleprice)
global partition by range(saleprice)
(
partition p1 values less than(30),
partition p2 values less than(50),
partition p3 values less than(maxvalue)
);
SQL> create index index_isbn on books(isbn)
global partition by hash(isbn);
ORA-01408: 此列列表已索引
SQL> select index_name from dba_indexes where table_name='BOOKS';
INDEX_NAME
------------------------------
SYS_C0011235
INDEX_SALEPRICE
SQL> drop index sys_c0011235;
drop index sys_c0011235
ORA-02429: 无法删除用于强制唯一/主键的索引
SQL> select table_name,constraint_name from user_constraints where table_name='BOOKS';
TABLE_NAME CONSTRAINT_NAME
------------------------------ ------------------------------
BOOKS SYS_C0011235
SQL> alter table books disable constraint sys_c0011235;
Table altered
SQL> create index index_isbn on books(isbn)
2 global partition by hash(isbn);
Index created
11.6 管理索引分区
11.6.1 索引分区管理的操作列表
对索引分区进行维护的alter index子句
维护分类 |
索引类型 |
范围分区 |
hash或list分区 |
组合分区 |
删除索引分区 |
全局 |
drop partition |
局部 |
无效 |
重建索引分区 |
全局 |
rebuild partition |
局部 |
rebuild partition |
rebuild subpartition |
更名索引分区 |
全局 |
rename partition |
局部 |
rename partition |
rename subpartition |
分割索引分区 |
全局 |
split partition |
局部 |
无效 |
11.6.2 索引分区管理的实际操作
1、删除索引分区
SQL> alter index index_saleprice drop partition p2;
Index altered
SQL> alter index index_saleprice drop partition p1;
Index altered
对于全局索引分区,不能删除索引的最高分区,否则系统会提示错误
在删除若干索引分区后,如果只剩一个索引分区,则需要对这个分区进行重建
SQL> alter index index_saleprice rebuild partition p3;
Index altered
2、重命名索引分区
语法格式:
alter index index_name
rename partition partition_old_name to partition_new_name
SQL> alter index index_saleprice rename partition p3 to p_new;
Index altered