1. 程式人生 > >oracle分區表的使用和查詢

oracle分區表的使用和查詢

listt mon phone rod active col ria div sha

一 創建和使用分區表

1.範圍分區(RANGE)

範圍分區將數據基於範圍映射到每一個分區,這個範圍是你在創建分區時指定的分區鍵決定的。這種分區方式是最為常用的,並且分區鍵經常采用日期。當使用範圍分區時,請考慮以下幾個規則: 1)每一個分區都必須有一個VALUES LESS THEN子句,它指定了一個不包括在該分區中的上限值。分區鍵的任何值等於或者大於這個上限值的記錄都會被加入到下一個高一些的分區中。
2)所有分區,除了第一個,都會有一個隱式的下限值,這個值就是此分區的前一個分區的上限值。
3)在最高的分區中,MAXVALUE被定義。MAXVALUE代表了一個不確定的值。這個值高於其它分區中的任何分區鍵的值,也可以理解為高於任何分區中指定的VALUE LESS THEN的值,同時包括空值。 假設有一個CUSTOMER表,表中有數據200000行,我們將此表通過CUSTOMER_ID進行分區,每個分區存儲100000行,我們將每個分區保存到單獨的表空間中,這樣數據文件就可以跨越多個物理磁盤。下面是創建表和分區的代碼,如下:
CREATE
TABLE CUSTOMER ( CUSTOMER_ID NUMBER NOT NULL PRIMARY KEY, FIRST_NAME<span style="white-space:pre"> </span>VARCHAR2(30) NOT NULL, LAST_NAME<span style="white-space:pre"> </span>VARCHAR2(30) NOT NULL, PHONE<span style="white-space:pre"> </span>
VARCHAR2(15) NOT NULL, EMAIL<span style="white-space:pre"> </span>VARCHAR2(80), STATUS<span style="white-space:pre"> </span>CHAR(1) ) PARTITION BY RANGE (CUSTOMER_ID) ( PARTITION CUS_PART1 VALUES LESS THAN (100000) TABLESPACE CUS_TS01, PARTITION CUS_PART2
VALUES LESS THAN (200000) TABLESPACE CUS_TS02 );

例二:按時間劃分

CREATE TABLE ORDER_ACTIVITIES   
(   
    ORDER_ID      NUMBER(7) NOT NULL,   
    ORDER_DATE    DATE,   
    TOTAL_AMOUNT NUMBER,   
    CUSTOTMER_ID NUMBER(7),   
    PAID   CHAR(1)   
)   
PARTITION BY RANGE (ORDER_DATE)   
(  
  PARTITION ORD_ACT_PART01 VALUES LESS THAN (TO_DATE(01- MAY -2003,DD-MON-YYYY)) TABLESPACEORD_TS01,  
  PARTITION ORD_ACT_PART02 VALUES LESS THAN (TO_DATE(01-JUN-2003,DD-MON-YYYY)) TABLESPACE ORD_TS02,  
  PARTITION ORD_ACT_PART02 VALUES LESS THAN (TO_DATE(01-JUL-2003,DD-MON-YYYY)) TABLESPACE ORD_TS03  
);  

例三:MAXVALUE

CREATE TABLE RANGETABLE  
(   
  idd   INT PRIMARY KEY ,   
  iNAME VARCHAR(10),   
  grade INT    
)   
PARTITION  BY  RANGE (grade)   
(   
      PARTITION  part1 VALUES  LESS  THEN (1000) TABLESPACE  Part1_tb,   
      PARTITION  part2 VALUES  LESS  THEN (MAXVALUE) TABLESPACE  Part2_tb   
);  
  
--——在表上執行查詢  
select * from RANGETABLE;  
  
--——在表分區上執行查詢  
select * from RANGETABLE partition(part1);  

2.列表分區(LIST)

該分區的特點是某列的值只有幾個,基於這樣的特點我們可以采用列表分區。創建一個按字段數據列表固定可枚舉值分區的表。插入記錄分區字段的值必須在列表中,否則不能被插入。

例一:

<span style="font-size: 12px;"><span style="font-family:SimSun;">CREATE TABLE PROBLEM_TICKETS   
(   
    PROBLEM_ID   NUMBER(7) NOT NULL PRIMARY KEY,   
    DESCRIPTION  VARCHAR2(2000),   
    CUSTOMER_ID  NUMBER(7) NOT NULL,   
    DATE_ENTERED DATE NOT NULL,   
    STATUS       VARCHAR2(20)   
)   
PARTITION BY LIST (STATUS)   
(   
      PARTITION PROB_ACTIVE   VALUES (ACTIVE) TABLESPACE PROB_TS01,   
      PARTITION PROB_INACTIVE VALUES (INACTIVE) TABLESPACE PROB_TS02  
);</span></span><span style="font-family:georgia, verdana, Arial, helvetica, sans-seriff;font-size:14px;">  
</span>  

例二:

<span style="font-family:SimSun;font-size:12px;">CREATE  TABLE  ListTable  
(   
    id    INT  PRIMARY  KEY ,   
    name  VARCHAR (20),   
    area  VARCHAR (10)   
)   
PARTITION  BY  LIST (area)   
(   
    PARTITION  part1 VALUES (guangdong,beijing) TABLESPACE  Part1_tb,   
    PARTITION  part2 VALUES (shanghai,nanjing)  TABLESPACE  Part2_tb   
);</span>  

3.哈希分區(散列分區)(HASH)

例一:
CREATE TABLE HASH_TABLE   
(   
  COL NUMBER(8),   
  INF VARCHAR2(100)   
)   
PARTITION BY HASH (COL)   
(   
  PARTITION PART01 TABLESPACE HASH_TS01,   
  PARTITION PART02 TABLESPACE HASH_TS02,   
  PARTITION PART03 TABLESPACE HASH_TS03   
)  

簡寫:

CREATE TABLE emp  
(  
    empno NUMBER (4),  
    ename VARCHAR2 (30),  
    sal   NUMBER   
)  
PARTITION BY  HASH (empno) PARTITIONS 8  
STORE IN (emp1,emp2,emp3,emp4,emp5,emp6,emp7,emp8);  
hash分區最主要的機制是根據hash算法來計算具體某條紀錄應該插入到哪個分區中,hash算法中最重要的是hash函數,Oracle中如果你要使用hash分區,只需指定分區的數量即可。建議分區的數量采用2的n次方,這樣可以使得各個分區間數據分布更加均勻。

4.組合分區(RANGE-LIST 和 RANGE-HASH)

基於範圍分區和列表分區,表首先按某列進行範圍分區,然後再按某列進行列表分區,分區之中的分區被稱為子分區。
CREATE TABLE SALES 
(
PRODUCT_ID VARCHAR2(5),
SALES_DATE DATE,
SALES_COST NUMBER(10),
STATUS VARCHAR2(20)
)
PARTITION BY RANGE(SALES_DATE) SUBPARTITION BY LIST (STATUS)
(
   PARTITION P1 VALUES LESS THAN(TO_DATE(2003-01-01,YYYY-MM-DD))TABLESPACE rptfact2009 
  ( 
      SUBPARTITION P1SUB1 VALUES (ACTIVE) TABLESPACE rptfact2009, 
      SUBPARTITION P1SUB2 VALUES (INACTIVE) TABLESPACE rptfact2009 
  ), 
   PARTITION P2 VALUES LESS THAN (TO_DATE(2003-03-01,YYYY-MM-DD)) TABLESPACE rptfact2009 
  ( 
      SUBPARTITION P2SUB1 VALUES (ACTIVE) TABLESPACE rptfact2009, 
      SUBPARTITION P2SUB2 VALUES (INACTIVE) TABLESPACE rptfact2009 
  ) 
)

2)基於範圍分區和散列分區,表首先按某列進行範圍分區,然後再按某列進行散列分區。

create table dinya_test   
 (   
 transaction_id number primary key,   
 item_id number(8) not null,   
 item_description varchar2(300),   
 transaction_date date   
 )   
 partition by range(transaction_date)  
 subpartition by hash(transaction_id) subpartitions 3 store in (dinya_space01,dinya_space02,dinya_space03)   
 (   
     partition part_01 values less than(to_date(‘2006-01-01,yyyy-mm-dd)),   
     partition part_02 values less than(to_date(‘2010-01-01,yyyy-mm-dd)),   
     partition part_03 values less than(maxvalue)   
 );  
CREATE TABLE range_hash_example(
 range_column_key int,
 hash_column_key  INT,
 DATA <span style="white-space:pre">    </span>VARCHAR2(20)
)
PARTITION BY RANGE(range_column_key)
SUBPARTITION BY HASH(hash_column_key) SUBPARTITIONS 2
(
  PARTITION part_1 VALUES LESS THAN (100000000)
  (
     SUBPARTITION part_1_sub_1,
     SUBPARTITION part_1_sub_2,
     SUBPARTITION part_1_sub_3
  ),
  PARTITION part_2 VALUES LESS THAN (200000000)
  (
     SUBPARTITION part_2_sub_1,
     SUBPARTITION part_2_sub_2
  )
);

--註: subpartitions 2 並不是指定subpartition的個數一定為2,實際上每個分區的子分區個數可以不同。如果不指定subpartition的具體明細,則系統按照subpartitions的值指定subpartition的個數生成子分區,名稱由系統定義 。

二 有關分區表的維護操作

1.添加分區

以下代碼給SALES表添加了一個P3分區
ALTER TABLE SALES ADD PARTITION P3 VALUES LESS THAN(TO_DATE(2003-06-01,YYYY-MM-DD));  
-- range partitioned table
ALTER TABLE range_example ADD PARTITION part04 VALUES LESS THAN (TO_DATE(2008-10-1 00:00:00,yyyy-mm-ddhh24:mi:ss));

--list partitioned table
ALTER TABLE list_example ADD PARTITION part04 VALUES(TE);

--Adding Values for a List Partition
ALTER TABLE list_example MODIFY PARTITION part04 ADD VALUES(MIS);

--Dropping Values from a List Partition
ALTER TABLE list_example MODIFY PARTITION part04 DROP VALUES(MIS);

--hash partitioned table
ALTER TABLE hash_example ADD PARTITION part03;

--增加subpartition
ALTER TABLE range_hash_example MODIFY PARTITION part_1 ADD SUBPARTITION part_1_sub_4;

註:hash partitioned table新增partition時,現有表的中所有data都有重新計算hash值,然後重新分配到分區中,所以被重新分配的分區的indexes需要rebuild 。

2.刪除分區

ALTER TABLE SALES DROP PARTITION P3;  
  
ALTER TABLE SALES DROP SUBPARTITION P4SUB1;  

註意:如果刪除的分區是表中唯一的分區,那麽此分區將不能被刪除,要想刪除此分區,必須刪除表。

3.截斷分區

截斷某個分區是指刪除某個分區中的數據,並不會刪除分區,也不會刪除其它分區中的數據。當表中即使只有一個分區時,也可以截斷該分區。通過以下代碼截斷分區:
ALTER TABLE SALES TRUNCATE PARTITION P2;  
通過以下代碼截斷子分區:
ALTER TABLE SALES TRUNCATE SUBPARTITION P2SUB2;  

4.合並分區

合並分區是將相鄰的分區合並成一個分區,結果分區將采用較高分區的界限,值得註意的是,不能將分區合並到界限較低的分區。
ALTER TABLE SALES MERGE PARTITIONS P1,P2 INTO PARTITION P2 UPDATE INDEXES;  
--如果省略update indexes子句的話,必須重建受影響的分區的index;
ALTER TABLE range_example MODIFY PARTITION part02 REBUILD UNUSABLE LOCAL INDEXES;  

5.拆分分區

拆分分區將一個分區拆分兩個新分區,拆分後原來分區不再存在。註意不能對HASH類型的分區進行拆分。
ALTER TABLE SALES SBLIT PARTITION P2 AT(TO_DATE(2003-02-01,YYYY-MM-DD)) INTO (PARTITION P21,PARTITION P22);  
註意:如果是RANGE類型的,使用at,LIST類型的使用values。

6.接合分區(coalesce)

分區接合是針對散列分區或者*-散列子分區的,目的是減少分區數。當某個散列分區接合後,Oracle將其分區的數據分散到其它分區中。被接合的分區是由數據庫選擇的,接合完成後該分區會被刪除,且如果沒有使用UPDATE INDEX子句,本地索引和全局索引均將變成不可用,一般需要重建索引。
--散列分區表的散列分區接合  
ALTER TABLE table_name COALESCE PARTITION;  
--散列分區表的散列子分區接合  
ALTER TABLE table_name MODIFY PARTITION partition_name COALESCE SUBPARTITION;  

7.重命名表分區

ALTER TABLE table_name RENAME PARTITION old_name TO new_name;  
ALTER TABLE table_name RENAME SUBPARTITION old_name TO new_name;  

8.交換分區

可以將一個分區(子分區)和非分區表進行數據交換,oracle交換的方法是其實是對邏輯存儲段進行交換。同樣,散列|範圍|列表分區可以與復合*-散列|*-範圍|*-列表分區間也可以進行數據交換。當應用中需要將非分區表的數據轉換進入分區表的分區時非常高效實用。使用INCLUDEING INDEXES子句可以同步將本地索引也進行交換,使用WITH VALIDATATION子句還可以實現行數據的驗證。 交換分區時如果不帶UPDATE INDEXES子句,則全局索引或全局索引基於的分區將變為不可用。 1)三種單級分區與非分區表的交換 [sql] view plain copy
ALTER TABLE table_name EXCHANGE PARTITION partition_name WITH TABLE nonpartition_name;  
2)單級散列分區表與復合*-散列分區的交換 此時要求單級散列分區表的分區鍵與復合*-散列分區表的子分區鍵相同,且兩個交換的散列分區數也得相同,此外也不能指定單級散列分區表的某一個分區進行交換。 3)復合*-散列分區中的散列子分區交換 使用ALTER TABLE ... EXCHANGE SUBPARTITION與非分區表進行交換,且只能跟非分區表進行交換。 4)單級列表分區表與復合*-列表分區的交換 此時要求List分區表的分區鍵和*-List表的子分區鍵相匹配,前者的List分區數與後者的List子分區相同。 復合*-列表分區中的列表子分區交換 同樣也是使用ALTER TABLE ... EXCHANGE SUBPARTITION與非分區表進行交換,且只能跟非分區表進行交換。 6)單級範圍分區表與復合*-範圍分區表的交換 此時要求Range分區表的分區鍵和*-Range表的子分區鍵相匹配,前者的Range分區數與後者的Range子分區相同。 7)復合*-範圍分區中的範圍子分區交換 同樣也是使用ALTER TABLE ... EXCHANGE SUBPARTITION與非分區表進行交換,且只能跟非分區表進行交換。

9.移動分區

[sql] view plain copy
alter table custaddr move partition P_OTHER tablespace system;  
alter table custaddr move partition P_OTHER tablespace icd_service;  
分區移動會自動維護局部分區索引,oracle不會自動維護全局索引,所以需要我們重新rebuild分區索引,具體需要rebuild哪些索引,可以通過dba_part_indexes,dba_ind_partitions去判斷。 [sql] view plain copy
Select index_name,status From user_indexes Where table_name=CUSTADDR;  

10.關於分區表和索引

1)本地分區索引 本地分區索引是使用了LOCAL屬性創建的分區索引,其特征是索引分區的所有鍵均指向其基表某個 唯一分區中存儲的相應行。Oracle創建本地分區索引的目的就是要確保索引也是分區管理的,而且索引的分區與表的分區是均衡的,也就是本地分區索引具有與其基表相同的分區、子分區,即分區鍵等同於表的分區鍵、分區數等同於表的分區數。 任何基表分區的增加、刪除、合並、分割操作,或者散列分區增加或合並操作,Oracle會通過其自身的機制自動維護本地分區索引相應的分區,此即本地分區索引與基表的均衡性原則。 如果分區列能夠形成索引列的一個子集,則本地分區索引可以是唯一索引。該限制能確保具有相同索引鍵的行始終映射到同一個分區,在該分區中,違反唯一性的行為能被檢測到。 本地索引的優勢有: l在基表上執行除SPLIT PARTITION或ADD PARTITION 外的維護命令僅僅只有一個分區會被影響 l當分區表只有一個本地分區索引時,對分區進行維護操作的時間是與分區的大小成正比的 l本地分區索引支持分區的獨立性 l只能本地分區索引支持單一分區數據的裝入和卸出 l本地索引與基表的均衡性會給Oracle執行計劃帶來更好的性能 l表分區和各自的本地索引可以同時恢復 l分區表中的位圖索引必須是本地索引,非分區表上不能建立分區位圖索引 ①本地前綴索引 本地前綴索引是指以索引列的左前綴來分區的,如果存在子分區則要求其子分區的分區鍵包含在索引鍵中。本地前綴索引可以是唯一索引,也可以是非唯一索引。 ②本地非前綴索引 本地非前綴索引是指沒有以索引列的左前綴來分區的,或者是以索引列的左前綴來分區,但子分區的分區鍵不在索引鍵中。本地非前綴索引不可以是唯一索引,除非分區鍵是索引鍵的子集(此時是前綴索引)。 2)全局分區索引 全局分區索引是指某個特定索引分區中的鍵可能指向存儲在基表中的多個分區或子分區中的行,其創建需要使用GLOBAL屬性。無論分區表是那種類型的分區,全局索引只支持按範圍和散列分區兩種分區方式。 全局索引往往與基表是不均衡的,如果要追求二者的均衡性,只能使用本地分區索引。全局分區的索引類型只能是b-tree索引,不能是bitmap索引。正是因為其是b-tree索引,所以無論其指向多少個分區抑或多少行,也只有一個b-tree入口,每個索引分區中會再包含指向具體表分區或子分區中的行的鍵。 全局分區索引必須是前綴的,不支持非前綴的。其中,前綴的意思和本地分區索引的前綴的含義相同,即“前綴索引是指以索引列的左前綴來分區的”。 管理全局分區索引 l當基表分區移動和刪除(TRUNCATE、DROP、MOVE、SPLIT)時,全局索引的所有分區都受影響,也不支持分區依賴 l當基表分區或子分區恢復到某個時間點時,全局索引中所有相應入口也要恢復到相同的時間點。由於索引的分區或子分區的入口可能離散分布,其它分區或子分區混合型入口不恢復,除了重建索引之外沒有辦法完成 以表range_example為例: 1)建立普通的索引
create index com_index_range_example_id on range_example(id);  
2)建立本地分區索引
create index  local_index_range_example_id on range_example(id) local;  
3)建立全局分區索引 [sql] view plain copy
create index gidx_range_example_id on range_example(id)  
GLOBAL partition by  range(id)  
(  
 part_01 values less than(1000),  
 part_02 values less than(MAXVALUE)  
);  

對於分區索引的刪除,local index 不能指定分區名稱,單獨的刪除分區索引。local index 對應的分區會伴隨著data分區的刪除而一起被刪除。

global partition index 可以指定分區名稱,刪除某一分區。但是有一點要註意,如果該分區不為空,則會導致更高一級的索引分區被置為UNUSABLE 。

ALTER INDEX gidx_range_exampel_id drop partition part_01 ;  
此句將導致part_02 狀態為UNUSABLE 註意:對於表分區的各種操作,一定要註意更新索引

三 相關查詢

1.跨分區查詢

select sum( *) from  
(select count(*) cn from t_table_SS PARTITION (P200709_1)  
union all  
select count(*) cn from t_table_SS PARTITION (P200709_2)  
);  

2.查詢表上有多少分區

SELECT * FROM USER_TAB_PARTITIONS WHERE TABLE_NAME=tableName;  

3.查詢索引信息

select object_name,object_type,tablespace_name,sum(value)  
from v$segment_statistics  
where statistic_name IN (physical reads,physical write,logical reads)and object_type=INDEX  
group by object_name,object_type,tablespace_name  
order by 4 desc  
  
--顯示數據庫所有分區表的信息:  
select * from DBA_PART_TABLES  
  
--顯示當前用戶可訪問的所有分區表信息:  
select * from ALL_PART_TABLES  
  
--顯示當前用戶所有分區表的信息:  
select * from USER_PART_TABLES  
  
--顯示表分區信息 顯示數據庫所有分區表的詳細分區信息:  
select * from DBA_TAB_PARTITIONS  
  
--顯示當前用戶可訪問的所有分區表的詳細分區信息:  
select * from ALL_TAB_PARTITIONS  
  
--顯示當前用戶所有分區表的詳細分區信息:  
select * from USER_TAB_PARTITIONS  
  
--顯示子分區信息 顯示數據庫所有組合分區表的子分區信息:  
select * from DBA_TAB_SUBPARTITIONS  
  
--顯示當前用戶可訪問的所有組合分區表的子分區信息:  
select * from ALL_TAB_SUBPARTITIONS  
  
--顯示當前用戶所有組合分區表的子分區信息:  
select * from USER_TAB_SUBPARTITIONS  
  
--顯示分區列 顯示數據庫所有分區表的分區列信息:  
select * from DBA_PART_KEY_COLUMNS  
  
--顯示當前用戶可訪問的所有分區表的分區列信息:  
select * from ALL_PART_KEY_COLUMNS  
  
--顯示當前用戶所有分區表的分區列信息:  
select * from USER_PART_KEY_COLUMNS  
  
--顯示子分區列 顯示數據庫所有分區表的子分區列信息:  
select * from DBA_SUBPART_KEY_COLUMNS  
  
--顯示當前用戶可訪問的所有分區表的子分區列信息:  
select * from ALL_SUBPART_KEY_COLUMNS  
  
--顯示當前用戶所有分區表的子分區列信息:  
select * from USER_SUBPART_KEY_COLUMNS  
  
--怎樣查詢出oracle數據庫中所有的的分區表  
select * from user_tables a where a.partitioned=YES  
  
--刪除一個表的數據是  
truncate table table_name;  
  
--刪除分區表一個分區的數據是  
alter table table_name truncate partition p5;  
本文摘自:https://blog.csdn.net/mzglzzc/article/details/46300645 原創作者:mzglzzc

oracle分區表的使用和查詢