分区原则:当数据量超过2000W时,能够考虑使用分区表
原理:将一张表分红好几个区域(表空间划分的磁盘空间)
做用:提升效率算法
分区表尽可能建表时建立,
若是是后期优化时建分区表,必定要先备份oracle
分区类型 | 类型描述 |
---|---|
range: | 按照范围分区,一般是按照时间字段分区,好比申请时间,入职时间 |
list: | 按照分布分区,好比身份证号码最后一位 |
hash: | 按照hash值分配分区,相对平均的分配到建立的分区中 |
partition by range (字段) ( partition 分区名1 values less than (值1或日期1), partition 分区名2 values less than (值2或日期2), partition 分区名3 values less than (值3或日期3),... partition 分区名4 values less than (maxvalue) ); /*values less than 特色: values <值1 values>=值1 and values <值2 values>=值2 and values <值3 values>=值3 and values <值4 ...*/
关键字 | 描述 |
---|---|
partition by | 指明是分区表,range肯定分区方式,join_date是分区键,必须是表中的一列 |
partition | 后跟分区名字,分区名字必须全库惟一,不能重复 |
values less than | 即当分区键的值小于其后的值时,数据落入本分区 |
maxvalue | 用于最大分区 |
create table testRANGE ( v_date date, v_month varchar2(6), v_day varchar2(8), client_no varchar2(4), fee number ) partition by range(v_date) ( partition p_201712 values less than (to_date('2018/01/01 00:00:00','yyyy/mm/dd HH24:mi:ss')), partition p_201801 values less than (to_date('2018/02/01 00:00:00','yyyy/mm/dd HH24:mi:ss')), partition p_201802 values less than (to_date('2018/03/01 00:00:00','yyyy/mm/dd HH24:mi:ss')), partition p_201803 values less than (to_date('2018/04/01 00:00:00','yyyy/mm/dd HH24:mi:ss')) );
插入数据时,指定分区表或者不指定分区表都是能够的,
指定分区表时,要正确指定,否则会报错less
insert into testRANGE select to_date('20180331','yyyymmdd'),'201803','20180331','0001',80 from dual; commit
insert into testRANGE partition(p_201803) select to_date('20180331','yyyymmdd'),'201803','20180331','0001',80 from dual; commit
SQL> select * from testRANGE partition(p_201803); V_DATE V_MONTH V_DAY CLIENT_NO FEE ----------- ------- -------- --------- ---------- 2018/3/31 201803 20180331 0001 80 2018/3/31 201803 20180331 0001 80
SQL> SQL> select * from testRANGE WHERE 2 V_DATE>=TO_DATE('20180301','YYYY/MM/DD') 3 AND 4 V_DATE<TO_DATE('20180401','YYYY/MM/DD') 5 ; V_DATE V_MONTH V_DAY CLIENT_NO FEE ----------- ------- -------- --------- ---------- 2018/3/31 201803 20180331 0001 80 2018/3/31 201803 20180331 0001 80
表必定是分区表才能新增测试
alter table testRANGE add partition p_201804 values less than (to_date('20180501 00:00:00','YYYYMMDD HH24:MI:SS'));
alter table testrange drop partition p_201803;
当删除某一个数据分区时,原先属于该分区的数据,也会消失
慎重优化
SQL> select * from testRANGE; V_DATE V_MONTH V_DAY CLIENT_NO FEE ----------- ------- -------- --------- ----------
新建code
create table testlist ( id number(8), name varchar(50), gender varchar(1), --性别 m_s varchar(1) --婚姻状态 ) partition by list (m_s) ( partition p_married values ('1'), --已婚 partition p_unmarried values ('2'), --未婚 partition p_divorce values ('3'), --离异 partition p_widowed values (4) --丧偶 );
插入数据hash
insert into testlist select 1,'tom','1','2' from dual union all select 2,'join','2','2' from dual union all select 3,'josn','2','3' from dual union all select 4,'mon','1','4' from dual;
查看未婚的数量it
SQL> select count(1) from testlist 2 where m_s='2'; COUNT(1) ---------- 2 SQL> SQL> select count(1) from testlist 2 partition(p_unmarried); COUNT(1) ---------- 2
也叫散列分区,用的频率较低,io
当数据较大,要建分区表时
可是又没有合适的范围字段和列字段
会将表里的数据,根据哈希算法,相对平均的分配到建立的分区中table
新建
create table testhash ( id varchar(10), name varchar(100) ) partition by hash (id) ( partition aa, partition bb, partition cc );
插入数据
insert into testhash select '1','name1' from dual union all select '2','name2' from dual union all select '3','name3' from dual union all select '4','name4' from dual union all select '5','name5' from dual union all select '6','name6' from dual;
查看数据在三个分区表的分布状况
SQL> select * from testhash partition(aa); ID NAME ----- ------- 2 name2 4 name4 SQL> select * from testhash partition(bb); ID NAME ----- ------- 1 name1 3 name3 5 name5 6 name6 SQL> select * from testhash partition(cc); ID NAME ----- -------
将上面的三大分区,两两组合
在使用中一般将范围分区做为主分区
新建
create table testemp ( v_empno varchar2(10), v_name varchar2(100), v_date date, v_deptno varchar2(3) ) partition by range (v_date) subpartition by list (v_deptno) ( partition p_201712 values less than (to_date('2018/01/01 00:00:00','yyyy/mm/dd hh24:mi:ss')) (subpartition a1 values('10'), subpartition a2 values('20'), subpartition a3 values('30'), subpartition a4 values('40')), partition p_201801 values less than (to_date('2018/02/01 00:00:00','yyyy/mm/dd hh24:mi:ss')) (subpartition b1 values('10'), subpartition b2 values('20'), subpartition b3 values('30'), subpartition b4 values('40')) );
插入数据
insert into testemp select '001','name1',to_date('20180102','yyyymmdd'),10 from dual union all select '002','name2',to_date('20171027','yyyymmdd'),10 from dual;
查看主分区
SQL> select * from testemp partition(p_201712); V_EMPNO V_NAME V_DATE V_DEPTNO -------- -------- ----------- -------- 002 name2 2017/10/27 10
查看子分区
SQL> select * from testemp subpartition(b1); V_EMPNO V_NAME V_DATE V_DEPTNO -------- ------- ----------- -------- 001 name1 2018/1/2 10
新建
create table testzz ( stat_id varchar2(10), stat_date date ) partition by range (stat_date) interval (numtoyminterval (1,'month')) ( partition p1 values less than (to_date('2018/02/01 00:00:00','yyyy/mm/dd hh24:mi:ss')) );
month
处也可改成year
插入数据
其中两条数据不符合分区状况
insert into testzz select '1',to_date('20180118','yyyymmdd') from dual union all select '2',to_date('20180218','yyyymmdd') from dual union all select '3',to_date('20180318','yyyymmdd') from dual;
查看表结构时,发现多了两个表结构
partition SYS_P21 values less than (TO_DATE(' 2018-03-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN'))
partition SYS_P22 values less than (TO_DATE(' 2018-04-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN'))
用上面的表testzz
分区p1
来测试
SQL> select * from testzz partition(p1); STAT_ID STAT_DATE ---------- ----------- 1 2018/1/18
建立一个和testzz表结构相同的表,并建立数据
SQL> create table testswap as 2 select * from testzz where 1=2; Table created
insert into testswap select '0001',to_date('20180101','yyyymmdd') from dual union all select '0002',to_date('20180103','yyyymmdd') from dual union all select '0003',to_date('20180104','yyyymmdd') from dual;
SQL> select * from testswap; STAT_ID STAT_DATE ---------- ----------- 0001 2018/1/1 0002 2018/1/3 0003 2018/1/4
将分区表testzz的p1分区和普通表testswap进行交换
注意:这里的testswap表中的时间是符合p1分区的规则的
SQL> alter table testzz 2 exchange partition p1 3 with table testswap; Table altered
再次查看
SQL> select * from testswap; STAT_ID STAT_DATE ---------- ----------- 1 2018/1/18 SQL> select * from testzz partition(p1); STAT_ID STAT_DATE ---------- ----------- 0001 2018/1/1 0002 2018/1/3 0003 2018/1/4
比本身备份再还原效率要高一点