分區原則:當數據量超過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
比本身備份再還原效率要高一點