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錯誤


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