oracle分區技術

oracle分區技術oracle

1、分區技術概述
一、表或索引的全部分區必須具有相同的邏輯結構。
二、利用分區技術,用戶能夠在分區級進行數據加載、索引建立及重建,或備份恢復等數據管理操做。
三、分區技術可以提升查詢性能。
四、分區技術能顯著縮短維護操做致使的停機時間。
五、對各分區的維護操做能夠相互獨立地進行。app

2、分區鍵和分區表
一、分區鍵的特色:
由1--16個數據列順序構成;
不能包含LEVEL、ROWID、MLSLABEL(虛列),也不能包含類型爲ROWID的列;
不能包含可爲空(NULL)的列。less


一張表最多 可由1024K-1個分區構成。
任何表都能被分區,除非其中含有數據類型爲LONG或者LONG RAW的列。
CLOB或者BLOB的類型列的表能夠被分區。函數

二、範圍分區
經過數據範圍進行分區。
--建立範圍分區表並使用 (MAXVALUE) 鍵值
create table scott.range_test(range_key date not null,EMID number,uname varchar2(20))
partition by range(range_key)
(partition part1 values less than (to_date('2015-01-01','yyyy-mm-dd')),
partition part2 values less than (to_date('2016-01-01','yyyy-mm-dd')),
partition part3 values less than (to_date('2017-01-01','yyyy-mm-dd')),
partition part4 values less than (to_date('2018-01-01','yyyy-mm-dd')),
partition part5 values less than (to_date('2019-01-01','yyyy-mm-dd')),
partition part_MAX values less than (MAXVALUE));

--查詢一個分區表的數據
select * from scott.range_test partition(part2)
--查詢用戶分區表信息
select table_name,partitioning_type,partition_count,status
from user_part_tables
--查詢用戶表分區信息
select table_name,partition_name,tablespace_name
from user_tab_partitions性能

--向範圍分區增長分區
alter table scott.range_test
add partition part6 values less than (to_date('2020-01-01','yyyy-mm-dd'));
--刪除一個分區,刪除這個分區時這個分區裏的數據也會一同刪除
alter table scott.range_test drop partition part4;ui

ORA-14074:分區界限必須調整爲高於最後一個分區界限。
一旦列表分區表有一個MAXVALUE分區,要再向這個表中增長更多的分區就必須拆分分區或者刪除MAXVALUE分區
,而後增長新的分區再加回MAXVALUE分區。spa

 

當插入的數據超出分區範圍時報錯以下:
ORA-14400:插入的分區關鍵字未映射到任何分區。
此時要新增相應的分區。設計

三、列表分區
列表分區根據離散的值列表。
--建立列表分區
create table list_exp
(state_name varchar2(20),city varchar2(20))
partition by list (city)
(partition SZ values ('SZ'),
partition SH values ('SH'),
partition BJ values ('BJ'));索引

--向列表分區增長分區
alter table list_exp
add partition TJ values('TJ');ip

--建立列表分區並使用 default 鍵值
create table list_exp2
(state_name varchar2(20),city varchar2(20))
partition by list (city)
(partition SZ values ('SZ'),
partition SH values ('SH'),
partition BJ values ('BJ'),
partition part_MAX values(default));

一旦列表分區表有一個DEFAULT分區,要能再向這個表中增長更多的分區就必須拆分分區或者刪除DEFAULT分區,
而後增長新的分區再加回DEFAULT分區。


CREATE TABLE "SCOTT"."EMP_LIST"
( "EMPNO" NUMBER(4,0),
"ENAME" VARCHAR2(10),
"JOB" VARCHAR2(9),
"MGR" NUMBER(4,0),
"HIREDATE" DATE,
"SAL" NUMBER(7,2),
"COMM" NUMBER(7,2),
"DEPTNO" NUMBER(2,0) not null
)
partition BY list(deptno)
(partition P10 values(10),
partition P20 values(20),
partition P30 values(30),
partition P40 values(40),
partition P50 values(50)
);
--向列表分區插入數據
insert into scott.emp_list select * from scott.emp;

insert into table_name1 select * from table_name2 --要求table_name1表必須存在。
select * into table_name1 from table_name2; --要求table_name1表不存在,insert時會自動
建立table_name1表。

四、哈希分區
對一個表執行散列分區時,oracle會對分區鍵應用一個散列函數,以此肯定數據應當放在N個分區中的哪一個分區
中。oracle建議N是2的一個冪(二、四、八、16等),從而獲得最佳的整體分佈。
散列分區設計是爲了能使數據很好地分佈在多個不一樣的設備上,爲表選擇的散列鍵應當是惟一的一個列或組列,
或者至少有足夠的相異值,以便行能在多個分區上很好地(均勻地)分佈。

--建立哈希分區
create table scott.hash_exp
(hash_key date not null,
eid varchar2(20) not null,
ename varchar2(20) not null)
partition by hash (hash_key)
(partition part_1 tablespace users,
partition part_2 tablespace test
);

--向哈希分區表插入數據
insert into scott.hash_exp values(TO_DATE('2004-10-01','yyyy-mm-dd'),'SZ10001','Alex');
insert into scott.hash_exp values(TO_DATE('2015-10-01','yyyy-mm-dd'),'SZ10002','Owen');
insert into scott.hash_exp values(TO_DATE('2018-10-01','yyyy-mm-dd'),'SZ10003','pipi');

--向哈希分區增長兩個分區
alter table scott.hash_exp
add partition part_3 tablespace test;
alter table scott.hash_exp
add partition part_4 tablespace users;

注意事項:
使用哈希分區將無從控制一行數據最終會存放在哪一個分區。
若是改變哈希分區的個數,數據會在全部分區中從新分佈,向一個哈希分區表增長或刪除一個分區時,將致使所
有的數據都重寫。
分區數應該是2的冪,若是分區數是2的冪,那麼分區將會均勻分佈。

五、組合分區
在組合分區中,頂層分區機制老是區間分區。第二級分區機制多是列表分區或散列分區。
*範圍--哈希組合分區,首先使用範圍分區進行第一級分區,而後根據哈希值進行第二級分類,最終將數據存放
在二級子分區。
*範圍--列表分區中,一級使用範圍分區,二級使用列表分區。

--建立範圍--哈希組合分區
create table scott.composite_exp
(range_key date not null,
hash_key int not null,
eid varchar2(20),
ename varchar2(20)
)
partition by range(range_key)
subpartition by hash(hash_key) subpartitions 2
(
partition part1 values less than(to_date('2015-01-01','yyyy-mm-dd'))
(subpartition part1_sub1,
subpartition part1_sub2
),
partition part_2 values less than(to_date('2016-01-01','yyyy-mm-dd'))
(subpartition part2_sub1,
subpartition part2_sub2
),
partition part_max values less than(MAXVALUE)
(subpartition partMAX_sub1,
subpartition partMAX_sub2
)
);

--建立範圍--散列分區
create table scott.compo_range_list_exp
(range_key date not null,
list_key int not null,
eid varchar2(20),
ename varchar2(20)
)
partition by range(range_key)
subpartition by list(list_key)
(
partition part1 values less than(to_date('2015-01-01','yyyy-mm-dd'))
(subpartition part1_sub1 values(1,3,5,7),
subpartition part1_sub2 values(2,4,6,8)
),
partition part_2 values less than(to_date('2016-01-01','yyyy-mm-dd'))
(subpartition part2_sub1 values(1,3),
subpartition part2_sub2 values(2,4),
subpartition part2_sub3 values(5,7),
subpartition part2_sub4 values(6,8)
),
partition part_max values less than(MAXVALUE)
(subpartition partMAX_sub1 values(default)
)
);

六、分區鍵修改引發的問題
分區鍵的實現分區的依據,若是用於肯定分區的列有修改,則須要考慮兩種狀況:
(1)、修改不會致使使用一個不一樣的分區,行仍屬於原來的分區。這在全部狀況下都獲得支持。
(2)、修改會致使跨行分區移動,只有當表啓用了行移動時才支持這種狀況,不然會產生一個錯誤。
例如:
SQL> update scott.range_test
2 set range_key = (to_date('2015-07-01','yyyy-mm-dd'))
3 where range_key = (to_date('2014-10-01','yyyy-mm-dd'));
update scott.range_test
set range_key = (to_date('2015-07-01','yyyy-mm-dd'))
where range_key = (to_date('2014-10-01','yyyy-mm-dd'))
ORA-14402: 更新分區關鍵字列將致使分區的更改

解決這個障礙的關鍵就是啓動移動特性。容許從一個分區移動到另外一個分區。行的ROWID會因爲更新而改變。
例如:
SQL> select rowid from scott.range_test
2 where range_key = (to_date('2014-10-01','yyyy-mm-dd'));
ROWID
--------------------------------------------------------------------------------
AAAVckAAEAAABEvAAA

--啓用行移動
SQL> alter table scott.range_test enable row movement;
Table altered

--更新數據

SQL> update scott.range_test
2 set range_key = (to_date('2015-07-01','yyyy-mm-dd'))
3 where range_key = (to_date('2014-10-01','yyyy-mm-dd'));
1 row updated
SQL>commit;


--查看更新後的ROWID
SQL> SELECT ROWID from scott.range_test where uname='JESSICA';
ROWID
--------------------------------------------------------------------------------
AAAVclAAEAAABUyAAA

SQL> SELECT ROWID from scott.range_test where range_key = (to_date('2015-07-01','yyyy-mm-
dd'));
ROWID
--------------------------------------------------------------------------------
AAAVclAAEAAABUyAAA

如下狀況也會引發ROWID改變
(1)、更新IOT的主鍵可能致使ROWID改變,該行的通用ROWID(UROWID)也會改變。
(2)、oracle 10g的FALSHBACK TABLE命令可能改變行的ROWID。
(3)、oracle 10g的ALTER TABLE SHRINK命令也可能使行的ROWID改變。


七、索引分區
設計合理的分區索引對於表分區技術應用的好壞關係密切。分區索引有:本地前綴分區索引、本地非前綴索引和
全局分區索引。
前綴索引: 所謂前綴索引是指分區字段是索引字段的前綴。
本地非前綴分區索引: 建立的本地分區索引不使用表分區的分區鍵做爲前綴就是本地非前綴分區索引。在表分
區被DROP或者MERGE後,本地非前綴分區索引依然有效。
全局分區索引: 索引的分區與表的分區無關。有兩種類型:全局範圍分區索引和全局哈希分區索引。

本地分區索引不會受到表分區的變化影響,本地分區索引自動維護,全局分區索引一旦表分區變化則失效,須要
重建。

八、建立本地前綴分區索引
--建立本地前綴分區索引
create index scott.idx_range_test_rangekey on scott.range_test(range_key) local;


九、建立本地非前綴分區索引
--建立本地非前綴分區索引
create index scott.idx_range_test_eid on scott.range_test(emid) local;

十、建立全局索引
create index scott.idx_range_test_ename on scott.range_test(ename) global;

十一、新增分區
若是分區邊界不是MAXVALUE,那麼能夠直接添加一個新分區,若是邊界是MAXVALUE,則須要先刪除掉原有分區
,而後再添加,或者採用分區的拆分。
--刪除邊界分區
SQL>alter table pt drop partition p_max;
--新增分區
SQL>alter table pt add partition p_9000 values less than(9000) tablespace users;
--增長邊界分區
SQL>alter table pt add partition p_max values less than(maxvalue) tablespace users;

**表分區變化後,全局分區索引將失效,須要重建。

十二、移動分區
--建立一個新表空間
SQL>create tablespace newtbs datafile '/u01/app/oracle/oradata/newtbs.dbf' size 100m
autoextend on;
--移動表分區
SQL>alter table pt move partition p_9000 tablespace newtbs;

表分區移動後全局分區索引會失效,須要重建。
--手工重建全局分區索引
SQL>alter index idx_global_pt_owner rebuild;

1三、截斷表分區
SQL>alter table pt truncate partition p_9000;

1四、刪除表分區
SQL> alter table pt drop partition p_9000;

1五、拆分表分區
拆分分區是把一個分區拆分紅兩個分區,利用split技術能夠實現這種拆分。

 


--建立分區表
create table scott.pt
(owner,object_name,subobject_name,object_id,data_object_id,object_type,created,last_ddl_time,
timestamp,status,temporary,generated,secondary)
partition by range(object_id)
(partition p_3000 values less than(3000) tablespace users,
partition p_6000 values less than(6000) tablespace users,
partition p_max values less than(maxvalue)
)
as
select
owner,object_name,subobject_name,object_id,data_object_id,object_type,created,last_ddl_time,t
imestamp,status,temporary,generated,secondary
from dba_objects;

--建立全局索引
create index idx_global_pt_owner on pt(owner) global;

--建立本場前綴分區索引
create index idx_local_pt_object_id on pt(object_id) local;

--查看索引狀態
select index_name,status from user_indexes where table_name='PT';


--拆分分區
alter table pt split partition p_max at (9000)
into (partition p_9000 tablespace users,partition p_max tablespace users);

--重建全局索引
alter index idx_global_pt_owner rebuild;


--驗證拆分分區
select table_name,partition_name,tablespace_name from user_tab_partitions;

--查詢分區邊界值
select max(object_id),min(object_id) from pt partition(p_6000);


1六、合併分區
相鄰的分區能夠合併爲一個分區,新分區的下邊界爲原來邊界值較低的分區,上邊界爲原來邊界值較高的分區,
原先的局部索引也相應的會合並,全局索引會失效,須要重建。

--合併分區
alter table pt merge partitions p_6000,p_9000 into partition p_9000;

--查看錶分區狀況
select table_name,partition_name,tablespace_name from user_tab_partitions where
table_name='PT';

1七、分區交換
分區的交換能夠把一個表和分區表中的一個分區中的數據進行對換,分區的交換隻是一個數據字典的操做,所以
操做速度很快。
操做示例:
--截斷p_6000分區的數據
alter table scott.pt truncate partition p_6000;

--查詢分區數據
SQL> select count(*) from scott.pt partition(p_6000);

COUNT(*)
----------
0

--建立用於交換的表數據
SQL> create table scott.t_6000 as select
owner,object_name,subobject_name,object_id,data_object_id,object_type,created,last_ddl_time,t
imestamp,status,temporary,generated,secondary from dba_objects where object_id>=3000 and
object_id<6000;

Table created.

--使用EXCHANGE指令交換分區
alter table scott.pt exchange partition p_6000 with table scott.t_6000;
--驗證分區數據
SQL> select count(*) from scott.pt partition(p_6000);

COUNT(*)
----------
2998
SQL> select count(*) from scott.t_6000;

COUNT(*)
----------
0
--表scott.t_6000的數據被交換到了scott.pt表的partition(p_6000)裏了,表scott.t_6000表裏已經沒有數
據了。

--使用without validation 跳過數據檢查示例
--截斷p_6000分區的數據
alter table scott.pt truncate partition p_6000;
--建立用於交換的表數據
SQL> create table scott.t_7000 as select
owner,object_name,subobject_name,object_id,data_object_id,object_type,created,last_ddl_time,t
imestamp,status,temporary,generated,secondary from dba_objects where object_id>=3000 and
object_id<7000;
--不帶 without validation 參數交換數據
SQL> alter table scott.pt exchange partition p_6000 with table scott.t_7000;
alter table scott.pt exchange partition p_6000 with table scott.t_7000
*
ERROR at line 1:
ORA-14099: all rows in table do not qualify for specified partition
ORA-14099:表中不是全部行都符合指定的分區。


--使用without validation 跳過數據檢查
SQL> alter table scott.pt exchange partition p_6000 with table scott.t_7000 without
validation;

Table altered.

--驗證數據交換,發現會把交換表裏全部數據插入到partition(p_6000)裏。
SQL> select count(*) from scott.pt partition(p_6000);

COUNT(*)
----------
3970

--EXCHANGE還有一個子句 including indexes,指分區和表的索引相互交換,索引也能夠交換。

相關文章
相關標籤/搜索