Oracle 11g表分区与索引分区(《Oracle从入门到精通》读书笔记4)

一、概述

分区表的用途和优点:
1. 降低故障引起的损失;

2. 均衡I/O,减少竞争;

3. 提高查询速度,这一点在数据仓库的TP查询特别有用;

*TP查询:Transaction Processing,事务处理查询?这点不太清楚、网上资料也少,没查到


二、创建表分区

*首先通过下列语句找到目标数据库中的表空间名:

select tablespace_name,file_name,bytes/1024/1024 as MB from dba_data_files order by tablespace_name;


1. 范围分区:关键字RANGE,创建这种分区后,插入的数据会根据指定的分区键值范围进行分布,当数据在范围内均匀分布时,性能最好。

指定某一列的键值创建分区表:

例:创建一个商品零售表、包含四个分区,记录按照日期所在的季度分区:

create table ware_retail_part --创建一个描述商品零售的数据表
(
  id integer primary key,--销售编号
  retail_date date,--销售日期
  ware_name varchar2(50)--商品名称
)
partition by range(retail_date)
(
  --2011年第一个季度为part_01分区
  partition par_01 values less than(to_date('2011-04-01','yyyy-mm-dd')) tablespace TB_3,
  --2011年第二个季度为part_02分区
  partition par_02 values less than(to_date('2011-07-01','yyyy-mm-dd')) tablespace TB_4,
  --2011年第三个季度为part_03分区
  partition par_03 values less than(to_date('2011-10-01','yyyy-mm-dd')) tablespace TB_3,
  --2011年第四个季度为part_04分区
  partition par_04 values less than(to_date('2012-01-01','yyyy-mm-dd')) tablespace TB_4
);

之后我们向该表插入几条记录看下结果:

insert into ware_retail_part values(1,to_date('2011-01-21','yyyy-mm-dd'),'Pad');

insert into ware_retail_part values(2,to_date('2011-04-01','yyyy-mm-dd'),'Pad');

insert into ware_retail_part values(3,to_date('2011-07-25','yyyy-mm-dd'),'Pad');

insert into ware_retail_part values(4,to_date('2011-12-31','yyyy-mm-dd'),'Pad');

查询该表中某个分区中的数据:

select *from ware_retail_part partition(par_01);

指定某几列的键值创建分区表:

例:创建一个商品零售表、包含四个分区,按照日期和销售序号进行分区:

create table ware_retail_part2 --创建一个描述商品零售的数据表
(
  id integer primary key,--销售编号
  retail_date date,--销售日期
  ware_name varchar2(50)--商品名称
)
partition by range(id,retail_date)
(
  --part_01分区
  partition par_01 values less than(10,to_date('2011-04-01','yyyy-mm-dd')) tablespace TB_3,
  --part_02分区
  partition par_02 values less than(20,to_date('2011-07-01','yyyy-mm-dd')) tablespace TB_4,
  --part_03分区
  partition par_03 values less than(maxvalue,maxvalue) tablespace TB_3
);

最后一句有必要提一下,意思就是ID大于20、日期大于2011-07-01的记录全部存到第三个分区。

*注:这里指定的表空间块大小要一致,否则会报ORA-14519错误;这时需要修改对应表空间的块大小:

alter system set db_block_size=xxxx;

如果修改不了,可以参考这篇文章:http://blog.csdn.net/victory_xing126/article/details/45126247


2. 散列分区:又叫Hash分区;实在列的取值范围难以确定的情况下采用的分区方法。一般,下面几种情况可以采用Hash分区:

·DBA无法获知具体的数据值;

·数据的分布有Oracle处理;

·每个分区有自己的表空间。

例1:创建一个商品零售表,将表的ID列设为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 TB_3,
  partition par_02 tablespace TB_4
);

此时,向其中插入数据,Oracle会自动计算ID列的Hash值、从而决定该条记录该被存到哪个分区。

insert into ware_retail_part3 values(181,to_date('2011-01-21','yyyy-mm-dd'),'Pad');

insert into ware_retail_part3 values(271,to_date('2011-04-01','yyyy-mm-dd'),'Pad');

insert into ware_retail_part3 values(301,to_date('2011-07-25','yyyy-mm-dd'),'Pad');

insert into ware_retail_part3 values(431,to_date('2011-12-31','yyyy-mm-dd'),'Pad');

如果想知道某条记录被插入到哪个分区中,可以用下面的语句查询:

select ora_hash(Hash键值, 分区数) from dual;


例2:创建一个分区表,让系统自动生成分区名,并把这两个分区分别放到表空间tb_3,tb_4中:

create table ware_retail_part4 --创建一个描述商品零售的数据表
(
  id integer primary key,--销售编号
  retail_date date,--销售日期
  ware_name varchar2(50)--商品名称
)
partition by hash(id)
<pre name="code" class="sql">partitions 2
store in(tb_3,tb_4);

 

例3:创建一个分区表,并指定其初始化空间大小为2MB:

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 TB_3,
  partition par_02 tablespace TB_4
);

3. 列表分区:与范围分区类似,但分区依据是根据分区键的“具体值”来决定

例1:保存客户信息的clients表,以province列的值创建列表分区:

create table clients
(
  id integer primary key,
  name varchar2(50),
  province varchar2(20)
)
partition by list(province)
(
  partition shandong values('山东省') tablespace TB_3,
  partition guangdong values('广东省') tablespace TB_4,
  partition yunnan values('云南省') tablespace TB_3
);

向其中插入数据:

insert into clients values (19,'East','云南省');

insert into clients values (29,'West','广东省');

insert into clients values (09,'North','山东省');

查下结果:

select * from clients partition(yunnan);

select * from clients partition(shandong);

select * from clients partition(guangdong);


4. 组合分区:顾名思义,把两种分区方法用到同一段分区创建语句中;Oracle在执行时会先对第一个分区键值用第一种分区方法进行分配,然后再按照第二种分区方法对分区内的数据进行二次分区

例1:创建人员信息表person2,根据编号为其创建3个范围分区,再在每个分区内根据姓名创建两个Hash子分区

 create table person2 					--创建以一个描述个人信息的表
(
  id number primary key,				--个人的编号
  name varchar2(20),					--姓名
  sex varchar2(2)					--性别
)
partition by range(id)--以id作为分区键创建范围分区
subpartition by hash(name)--以name列作为分区键创建hash子分区
subpartitions 2 store in(tb_3,tb_4)--hash子分区公有两个,分别存储在两个不同的命名空间中
(
  partition par1 values less than(5000),--范围分区,id小于5000
  partition par2 values less than(10000),--范围分区,id小于10000
  partition par3 values less than(maxvalue)--范围分区,id不小于10000
);


5. Interval分区:范围分区的增强功能,只有最开始的分区是永久分区。随着数据的增加会分配更多的部分、并自动创建新的分区和本地索引。
*关于什么是本地索引,可以参考:http://blog.csdn.net/tannafe/article/details/4132858

例1:创建销售记录表saleRecord,为该表创建Interval分区

create table saleRecord
(
 id number primary key, --编号
 goodsname varchar2(50),--商品名称
 saledate date,--销售日期
 quantity number--销售量
)
partition by range(saledate)
interval (numtoyminterval(1,'year'))--按年份自动分区
(
  --设置分区键值日期小于2012-01-01
  partition par_fist values less than (to_date('2012-01-01','yyyy-mm-dd'))
);

*对于已经进行了范围分区的表格,可以通过使用alter table命令的set interval选项扩展为Interval分区表,以最一开始创建的分区表ware_retail_part为例:

alter table ware_retail_partset interval(NUMTOYMINTERVAL(3,'month'));

*表分区策略:

(1)识别大表:

已经投入使用的系统,可以用analyze table语句进行分析;以上述CLIENTS表为例:

analyze table clients compute statistics;
select * from user_tables where table_name ='CLIENTS';

(更详细的可以参考:http://blog.csdn.net/victory_xing126/article/details/44948521)

如果是研发中的系统,则要靠架构人员和客户的实际情况进行预估。

(2)根据大表的用途,确定分区方法(也就是上面说的范围分区、Hash分区、List分区,还是Interval分区);

(3)分区的表空间规划


三、管理表分区

1. 为一个已存在的分区表添加新的表分区

例:向上面的 clients表中新增一个省份为河北省的表分区:

alter table clients
add partition hebei values('河北省')
storage(initial 10k next 20k) tablespace tb_3
nologging;

最后的nologging,请参考:http://blog.csdn.net/sdl_ok/article/details/5474774

2. 合并分区:合并分区时,Oracle会自动:

·将待删除的分区内容挪到其他保留分区中;

·将待删除分区的内容和索引完全清楚;

·将一个或多个索引的本地索引分区标识为不可用(Unsable);

·对不可用的索引进行重建

(1)合并散列 分区:也就是将一个分区表的所有分区合并

alter table person coalesce partition;

(2)合并复合分区:也就是把若干个分区合并到其他保留子分区中:

比如,要将person2 的par3 分区合并到其他分区中:

alter table person2 modify partition par3 coalesce subpartition;

*注:这里说下如何查看一个表是否是分区表

先查看:

select tablespace_name from user_tables where table_name ='CLIENTS'

如果tablespace_name 为空,则表示这张表为分区表(当然,如果你把这张表的所有分区都建在同一个表空间上,那这个地方也会有值,这时就用下面的语句进行查询)

每张表的分区信息都存放在下列表中:
SELECT * FROM USER_TAB_PARTITIONS WHERE TABLE_NAME = 'CLIENTS'

3. 删除分区:可以从范围分区和复合分区中删除分区;但散列分区和复合分区中的散列子分区,只能通过合并来达到删除的目的

(1)删除一个表分区:删除后该分区的数据记录也会被删除,所以操作要谨慎。

alter table ware_retail_part drop partition par_03;

如果该表存在索引,那么需要重建该表的索引:

alter index ware_index rebuild;

*注:oracle不允许删除最后一个表分区,此外,如果该表的索引是范围分区的全局索引,那么需要重建所有索引的分区:

alter index ware_index rebuild index_01;

alter index ware_index rebuild index_02;

alter index ware_index rebuild index_04;

(2)先用DELETE删除表分区中的数据,然后在删除对应的分区,这样做的目的是让分区表的索引自动更新,即:

delete from tablename where [condition] ; --这里的condition注意,要恰好能将分区表中的数据清空

commit;

alter table ware_retail_part drop partition par_03;

(3)删除具有完整性约束的分区,这里提供两种办法:

·先禁用约束,然后删除该表的分区,在激活约束条件:

alter table table_name disable constraints constraints_name;

注:查看该表的约束条件语句:select constraint_name from USER_CONSTRAINTS where table_name=‘tablename’;

查看该表的具体哪一列被设置了约束:select * from USER_CONS_COLUMNS where  table_name=‘tablename’;

alter table table_name drop partition partition_name;

alter table table_name enable constraints constraints_name;

·第二种办法:先删除待删除分区中的数据,然后在删除分区:

delete from tablename where [condition] ; --这里的condition注意,要恰好能将分区表中的数据清空

commit;

alter table ware_retail_part drop partition par_03;

4. 并入分区:

·可以将两个相邻的范围分区合并为一个新分区,这个新分区继承原来两个分区的边界;

·如果原分区存在索引,则在合并时删除索引;

·如果被合并的分区为空,则新生成的分区表示为unsable;

·不能对HASH分区表执行合并操作;

例:创建销售记录表sales,以销售日期(季度)分为4个范围分区:

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 tb_3,
  --第二季度数据
  partition part_sea2 values less than(to_date('2011-07-01','yyyy-mm-dd')) tablespace tb_4,
  --第三季度数据
  partition part_sea3 values less than(to_date('2011-10-01','yyyy-mm-dd')) tablespace tb_3,
  --第四季度数据
  partition part_sea4 values less than(to_date('2012-01-01','yyyy-mm-dd')) tablespace tb_4
);

在sales表中创建局部索引:

create index index_3_4 on sales(saledate)
local(
partition part_seal tablespace tb_3,
partition part_sea2 tablespace tb_4,
partition part_sea3 tablespace tb_3,
partition part_sea4 tablespace tb_4
);

将第三个分区并入第四个分区:

alter table sales merge partitions part_sea3,part_sea4 into partition part_sea4;

重建局部索引:

alter table sales modify partition part_sea4 rebuild unusable local indexes;


四、索引分区

如果索引对应的表数据量很大,那么索引占用的空间也会很大,这是,需要对索引进行分区。

·本地索引:不反应基础表的结构,只能进行范围分区;

·全局索引:能够反映基础表的结构,当表被更改时,oracle会自动对本地索引所在的分区进行维护

1. 本地索引分区:通过和范围分区相同的列进行索引分区,也就是说,数据分区和索引分区是一一对应的,它有以下几个优点:

·如果只有一个分区需要维护,则只有一个本地索引受影响;

·支持分区独立性;

·只有本地索引能够支持单一分区的装入和卸载;

·表分区和各自的本地索引可以同时恢复;

·本地索引可以单独重建;

·位图索引仅由本地索引支持

(1)创建范围分区的本地索引分区:

--准备表空间
create tablespace TEST_2 datafile 'C:\tsdbf\ts1.dbf'
size 10m
extent management local autoallocate;
create tablespace ts_2 datafile 'C:\tsdbf\ts2.dbf'
size 10m
extent management local autoallocate;
create tablespace tb_3 datafile 'C:\tsdbf\ts3.dbf'
size 10m
extent management local autoallocate;
--创建分区表:
create table studentgrade
(
  id number primary key,--记录id
  name varchar2(10),--学生名称
  subject varchar2(10),--学科
  grade number --成绩
)
partition by range(grade)
(
  --小于60分,不及格
  partition par_nopass values less than(60) tablespace TEST_2,
  --小于70分,及格
  partition par_pass values less than(70) tablespace ts_2,
  --大于或等于70分,优秀
  partition par_good values less than(maxvalue) tablespace tb_3
);
--创建本地索引分区
create index grade_index on studentgrade(grade)
local
(
  partition p1 tablespace TEST_2,
  partition p2 tablespace ts_2,
  partition p3 tablespace tb_3
);
--查看索引分区信息
select partition_name,tablespace_name from dba_ind_partitions where index_name = 'GRADE_INDEX';


(2)创建组合分区的本地分区索引

--创建范围-列表组合分区表:
create table studentgrade2
(
  id number primary key,--记录id
  name varchar2(10),--学生名称
  subject varchar2(10),--学科
  grade number --成绩
)
partition by range(grade)
subpartition by list(subject)
(
--小于60分,不及格
partition grade_nopass values less than ('60') tablespace ts_2
(
subpartition list1 values('math') tablespace ts_2,
subpartition list2 values('ch') tablespace tb_3,
subpartition list3 values('phy') tablespace test_2
)
,
--小于75分,及格
partition grade_pass values less than ('75')tablespace TEST_2
(
subpartition list4 values('math') tablespace ts_2,
subpartition list5 values('ch') tablespace tb_3,
subpartition list6 values('phy') tablespace test_2
)
,
--大于75分,优秀
partition grade_good values less than (maxvalue) tablespace tb_3
(
subpartition list7 values('math') tablespace ts_2,
subpartition list8 values('ch') tablespace tb_3,
subpartition list9 values('phy') tablespace test_2
)
);
--创建组合分区的、包含索引子分区的本地分区索引
create index subject_index on studentgrade2(subject)
local
(
partition p1 tablespace TEST_2
(
subpartition p11 tablespace test_2,
subpartition p12 tablespace test_2,
subpartition p13 tablespace test_2
)
,
partition p2 tablespace ts_2
(
subpartition p21 tablespace ts_2,
subpartition p22 tablespace ts_2,
subpartition p23 tablespace ts_2
)
, 
partition p3 tablespace tb_3
(
subpartition p31 tablespace tb_3,
subpartition p32 tablespace tb_3,
subpartition p33 tablespace tb_3
)
);

*注:索引的子分区数必须与基础表的子分区数相等,否则会报ORA-14186错误


2. 创建全局索引分区:当分区中出现许多事物并且要保证所有分区中的数据记录唯一时、采用这种索引;他的分区键不一定非要和表分区的分区键一致。

(1)创建范围分区的全局索引:

create index index_studentgrade on studentgrade(subject)

global partition by range(subject) --注意关键字global

(

partition p1 values less than(30),

partition p2 values less than(60),

partition p3 values less than (maxvalue)

);

(2)创建组合分区的全局分区索引:

--创建范围-列表组合分区表
create table studentgrade3
(
  id number primary key,--记录id
  name varchar2(10),--学生名称
  subject varchar2(10),--学科
  grade number --成绩
)
partition by range(grade)
subpartition by list(subject)
(
--小于60分,不及格
partition grade_nopass values less than ('60') tablespace ts_2
(
subpartition list1 values('math') tablespace ts_2,
subpartition list2 values('ch') tablespace tb_3,
subpartition list3 values('phy') tablespace test_2
),
--小于75分,及格
partition grade_pass values less than ('75') tablespace TEST_2
(
subpartition list4 values('math') tablespace ts_2,
subpartition list5 values('ch') tablespace tb_3,
subpartition list6 values('phy') tablespace test_2
),
--大于75分,优秀
partition grade_good values less than (maxvalue) tablespace tb_3
(
subpartition list7 values('math') tablespace ts_2,
subpartition list8 values('ch') tablespace tb_3,
subpartition list9 values('phy') tablespace test_2
)
);
--创建包含子分区的全局分区索引<strong>(这段有问题、还在钻研中...希望有看到的大神赐教)</strong>
create index index_studentgrade3 on studentgrade3(grade,subject)
global partition by range(grade)
global subpartition by list(subject)
(
partition p1 values less than(30)
(
subpartition p11  values('math') tablespace ts_2,
subpartition p12  values('ch') tablespace tb_3,
subpartition p13  values('phy') tablespace test_2
)
,
partition p2 values less than(50)
(
subpartition p21  values('math') tablespace ts_2,
subpartition p22  values('ch') tablespace tb_3,
subpartition p23  values('phy') tablespace test_2
)
,
partition p3 values less than (maxvalue)
(
subpartition p31  values('math') tablespace ts_2,
subpartition p32  values('ch') tablespace tb_3,
subpartition p33  values('phy') tablespace test_2
)
);

例2:对上面的studentgrade表的name列创建hash分区的全局索引:

create index ind_studentgrade on studentgrade(name) global partition by hash(name);

3. 管理索引分区:




实际操作:

--更名,范围分区的全局索引index_studentgrade下的p2分区

alter index index_studentgrade rename partition p2 to p2new;

--更名,组合分区的局部索引subject_index下的p11子分区

alter index subject_index rename subpartition p11 to p11new;

--重建,局部索引分区

alter index grade_index rebuild partition p1;

--重建,组合分区的局部索引分区

alter index subject_index rebuild partition p1;

ORA-14287: 不能 REBUILD (重建) 组合范围分区的索引的分区;这个和书上讲的不一致,研究中...

--重建,组合分区的局部索引子分区

alter index subject_index rebuild subpartition p11;

--删除全局索引分区:

alter index index_studentgrade drop partition p1;

--分割表分区:

ALTER TABLE table_name SPLIT partition partition_name AT (分割点) INTO (PARTITION new_partition_name1 TABLESPACE ts1,PARTITIONnew_partition_name2 TABLESPACE ts2) ;

比如:

alter table studentgrade split partition par_good at (100) into (partition par_hun tablespace ts_2, partition par_error tablespace tb_3);

--分割全局分区索引:

alter index index_studentgrade split partition p2 at(40) into(partition par2_39 tablespace ts_2, partition par2_41 tablespace tb_3);

*注:如果要对maxvalue值所在的索引分区进行分割,则要先添加一个maxvalue分区,否则会报ORA-14080错误


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Oracle11gOracle数据库管理系统的一个版本,它提供了强大的功能和工具,用于管理和处理大量的数据。从入门到精通Oracle11g需要掌握以下几个方面。 首先,了解Oracle数据库的基本概念和架构非常重要。Oracle11g由实例和数据库组成,实例是数据库在内存中运行的副本,数据库是存储数据的物理文件。了解数据库的组成和相互关系,可以帮助我们更好地理解和管理Oracle11g。 其次,学习和掌握SQL语言是使用Oracle11g的基础。SQL是一种结构化查询语言,用于与数据库交互和操作数据。掌握SQL的各种语法、查询、更新、删除、插入等常用操作,是使用Oracle11g的基础。 第三,熟悉Oracle11g的管理工具和管理技术。Oracle提供了许多管理工具,如Enterprise Manager、SQL*Plus等,这些工具可以帮助我们管理和监视数据库,进行性能调优和故障排除等工作。 第四,深入了解Oracle11g的高级功能和特性。Oracle11g提供了许多高级功能,如分区索引、数据恢复、安全性等。学习和理解这些高级功能,可以使我们更好地利用Oracle11g的功能和优势。 最后,实践是提升Oracle11g技能的关键。通过实际操作和练习,我们可以更好地理解和掌握Oracle11g的各种功能和技术,提高我们的数据库管理和开发能力。 总而言之,要从入门到精通Oracle11g,我们需要学习和掌握Oracle的基本概念和架构,熟练运用SQL语言,熟悉Oracle的管理工具和管理技术,深入了解Oracle的高级功能和特性,并且通过实践不断提升自己的技能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值