Oracle原理:表分区

目录

1.范围分区、散列分区、列表分区、复合分区。

2.11g新增的引用分区、间隔分区、基于虚拟列的分区、系统分区。


1.范围分区、散列分区、列表分区、复合分区。

允许用户将一个表分成多个区,用户可以执行查询时,只访问表中的特定分区;将不同的分区存储在不同的磁盘,提高访问性能和安全性;并且可以独立的备份和恢复每个分区;SQLSever2005有了分区表内容,但是建分区表时比较麻烦,Oracle建分区表相比比较简单。和索引相比都是为了提高查询速度,但是分区是物理上的,因为在做增删查改时,数据库会根据 where 后面的筛选条件来进行遍历,普通表遍历时会从零号数据块遍历到高水位线。但是有了表分区后,可以快速锁定数据内存的位置范围,在范围中进行遍历,大大加快了查询速度。

分区方法4种:

范围分区:表中的一列或者多列进行范围分区

create table student(
sno int,
entrance_date date,
sname varchar2(20)
)
partition by range(entrance_date)(
  partition s1 values less than (date'2015-7-1'),
  partition s2 values less than (date'2016-7-1'),
  partition s3 values less than (date'2017-7-1'),
  partition s4 values less than (date'2018-7-1')
);
insert into student values(1,date'2015-5-30','A');
insert into student values(2,date'2015-7-1','B');
insert into student values(3,date'2016-7-1','A');
insert into student values(4,date'2018-1-30','A');
--insert into student values(5,date'2019-5-30','A'); --汇报无法映射到任何分区的错误
commit;

按分区查找信息:

select * from student partition(s1) where sname='A';

查询分区信息:

select * from user_tab_partitions where table_name ='STUDENT';
在范围分区中,会根据某个字段(entrance_date)的值进行判断该放入哪一块分区中,s1分区为2015-7-1之前的,不包含当天,s2,从2015-7-1 当天 到2016-7-1 之前 ,超出分区范围的数据是没有办法插入的,要添加分区外的数据只能先添加分区。

alter table student add partition s5 values less than(maxvalue);
insert into student values(5,date'2019-5-30','A');

散列分区:当数据字段没有什么逻辑关系时,可以考虑散列分区。散列分区会把数据分散分配到各个区中,采用HASH函数决定了存储数据到哪块分区上。这样分区内的数据量就比较平均。hash分区的hash函数无法自定义,由Oracle 自动提供。

create table student_hash(
sno int,
entrance_date date,
sname varchar2(20)
)
partition by HASH(sno)(
  partition s1 ,
  partition s2
);
insert into student_hash values(1,date'2015-5-30','A');
insert into student_hash values(2,date'2015-7-1','B');
insert into student_hash values(3,date'2016-7-1','A');
insert into student_hash values(4,date'2018-1-30','A');
commit;

 

列表分区:

和范围分区类似,当字段的取值是一个范围时,可以采用范围分区;当字段的取值是个枚举时,可以采用列表分区。例如像所在省份 这样的字段,就相比范围分区更适合用列表分区。 

create table student_list(
sno int,
entrance_date date,
address varchar2(20)
)
partition by LIST(address)(
  partition 东南沿海 values ('福建','广东','浙江'),
  partition 东北 values ('黑龙江','辽宁','吉林'),
  partition 西部 values ('西藏','新疆')
);
insert into student_list values(1,date'2015-5-30','福建');
insert into student_list values(2,date'2015-7-1','广东');
insert into student_list values(3,date'2016-7-1','西藏');
--insert into student_list values(4,date'2018-1-30','湖北');
commit;

同样的,插入不在分区范围的数据时,会报错。

复合分区:

就是范围分区和散列分区结合  或者 列表分区和散列分区相结合的分区。 此时的散列分区只能做范围分区和列表分区的子分区。

create table student_range_hash(
sno int,
entrance_date date,
address varchar2(20)
)
partition by range(entrance_date)
subpartition by hash(sno)   --子分区hash(sno)
subpartitions 4   --指明每个范围分区中有4个hash分区
(
  partition s1 values less than (date'2015-7-1'),
  partition s2 values less than (date'2016-7-1'),
  partition s3 values less than (date'2017-7-1'),
  partition s4 values less than (date'2018-7-1'),
  partition s5 values less than (maxvalue)
);

查看分区信息 和查看子分区信息:

select * from user_tab_partitions where table_name ='STUDENT_RANGE_HASH';
select * from user_tab_subpartitions where table_name ='STUDENT_RANGE_HASH';

2.11g新增的引用分区、间隔分区、基于虚拟列的分区、系统分区。

引用分区:一定要有个主键和外键之间的关系。外键表可以继承父表的分区方式,而不用自己新建。

----------创建主表--------
create table student_hash(
sno int primary key,
entrance_date date,
sname varchar2(20)
)
partition by HASH(sno)(
  partition s1 ,
  partition s2
);
insert into student_hash values(1,date'2015-5-30','A');
insert into student_hash values(2,date'2015-7-1','B');
insert into student_hash values(3,date'2016-7-1','A');
insert into student_hash values(4,date'2018-1-30','A');
commit;
----------副表创建 (设立主键,设立外键)---------
create table score_pointer(
exam_id int primary key,
sno int not null,
score int,
constraint fk_score foreign key(sno) references student_hash(sno)
)
partition by reference(fk_score);   ---引用分区关联外键

select * from user_tab_partitions where table_name ='STUDENT_HASH' or table_name ='SCORE_POINTER';

在引用分区中,副表的分区字段属性和主表的分区字段的属性一样。主表用了散列分区,那么副表就用散列分区,使用的hash函数和主表是一致的;如果主要用了范围分区,那么分区的类型和分区的取值范围主表和副表都是一致的。

 

间隔分区:

完全自动根据 间隔阈值 来创建范围分区。是范围分区的扩展。间隔分区属于范围分区。在范围分区中,当每次输入的值超出分区范围时,就会报错,而间隔分区会新建分区自动扩展 可输入的范围。自动扩展多大呢?自动扩展的大小就是间隔阈值。

create table student(
sno int,
entrance_date date,
sname varchar2(20)
)
partition by range(entrance_date)
interval ( numtoyminterval(1,'MONTH') ) --每超出最大范围一个月自动创建一个分区。
(
  partition s1 values less than (date'2015-7-1'),   -----初始化分区
  partition s2 values less than (date'2016-7-1'), 
  partition s3 values less than (date'2017-7-1'),
  partition s4 values less than (date'2018-7-1')
);
insert into student values(1,date'2015-5-30','A');
insert into student values(2,date'2015-7-1','B');
insert into student values(3,date'2016-7-1','A');
insert into student values(4,date'2018-1-30','A');
insert into student values(5,date'2019-5-30','A');
insert into student values(5,date'2021-5-30','A');
commit;

select * from user_tab_partitions where table_name ='STUDENT' 

刚开始初始化了4个分区,当插入entrance_date=date'2019-5-30'时就会创建一个从 2019-5-1 到2019-6-1的分区;当插入entrance_date=date'2021-5-30'时就会创建一个从 2021-5-1 到2021-6-1的分区,。分区范围为分区阈值所指定的1个月。从初始化的分区范围最大值2018-7-1开始分,连续一个月一个月的加。

基于虚拟列的分区:范围分区、散列分区、列表分区等可以作用在虚拟列上的。分区原理和传统分区没区别。

create table score(
exam_id int primary key,
sno int not null,
score int,
score_percent as (score /150.0 * 100.0) virtual   ---指明虚拟列
)
partition by HASH(score_percent)(
  partition s1 ,
  partition s2
);

系统分区:不需要指定分区列,不需要范围等,只需要指定分区的个数就行,一切分区的控制和管理由Oracle来完成。

create table score2(
exam_id int primary key,
sno int not null,
score int,
score_percent as (score /150.0 * 100.0) virtual
)
partition by system(
  partition s1 ,
  partition s2
);

 

 

操作分区时,和查找普通表是完全相同,Oracle会自动把数据保存到对应的分区上,删除的时候也会自动地找到相应的分区把数据删除。增删查改语句时可以 显示指定要操作的分区。

添加/删除/截断分区:

ALTER TABLE [tablename]   ADD /DROP /TRUNCATE     PARTITION  [partitionName] ;

 

合并分区:在分区相邻的情况下可以进行分区合并:

ALTER TABLE [tablename]  MERGE PARTITIONS [分区名1],[分区名2]  INTO PARTITION [新分区名];

拆分分区: 适用于分区类型为范围分区的拆分。

ALTER TABLE [tablename]  SPLIT PARTITION [分区名] 

AT(拆分的临界点)  

INTO  (   PARTITION [新分区名1]  , PARTITION [新分区名2] );

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章