Oracle中分區表的使用

前提:sql

   查詢分區:Select *From user_extents WHERE partition_name='分區名';數據庫

1)建立表空間 oracle

create tablespace HRPM0less

datafile '/oradata/misdb/HRPM0.DBF' size 5m autoextend on next 10m maxsize unlimited性能

2)刪除表空間(同時把數據文件也刪除) 測試

DROP TABLESPACE data01 INCLUDING CONTENTS AND DATAFILES;spa

   若是不想刪除數據文件:對象

           Drop tablespace tablespace_name;索引

3) 修改表空間大小 ip

alter database datafile '/path/NADDate05.dbf' resize 100M

4)添加數據文件(在創建表空間時,如果約束了表空間的大小,那麼一段時間後,這個表空間就會被裝滿,沒法再添加其餘對象。則須要給表空間添加數據文件):

Alter  tablespace tablespace_name add datafile’ '/path/NADDate06.dbf’ size 100M;

4) 備註:

4.1).--.禁止undo tablespace自動增加

alter database datafile 'full_path\undotbs01.dbf' autoextend off;

4.2).-- 建立一個新的小空間的undo tablespace

create undo tablespace undotBS2 datafile 'full_path\UNDOTBS02.DBF' size 100m;

4.3).-- 設置新的表空間爲系統undo_tablespace

alter system set undo_tablespace=undotBS2;

4.4).-- Drop 舊的表空間

drop tablespace undotbs1 including contents;

4.5).--查看全部表空間的狀況

select * from dba_tablespaces

5)查到一個最好用的表:dict

5.1)select *from dict where table_name like '%PART%'

5.2)ALL_TAB_PARTITIONS:能夠查出表所對應的分區內容;

5.3)dab_tab_partitons :與上2);

5.4)dba_ind_partitons:查詢分區的索引;

5.5)子分區也是同樣的(dba_tab_subpartitons,dba_ind_partitons)

1、使用分區的優勢:

    1、加強可用性:若是表的某個分區出現故障,表在其餘分區的數據仍然可用;

    2、維護方便:若是表的某個分區出現故障,須要修復數據,只修復該分區便可;

    3、均衡I/O:能夠把不一樣的分區映射到磁盤以平衡I/O,改善整個系統性能;

4、改善查詢性能:對分區對象的查詢能夠僅搜索本身關心的分區,提升檢索速度。

2、Oracle數據庫提供對錶或索引的分區方法有幾種(收集到四種):

        1、範圍分區

        2、列表分區

        3Hash分區(散列分區)

        4、複合分區

3、詳描述分區實例:

    1)下面將以實例的方式分別對這三種分區方法來講明分區表的使用。爲了測試方便,咱們先建三個表空間。

create tablespace dinya_space01 datafile 'C:\表空間\dinya01.dbf' size 5M; create tablespace dinya_space02 datafile 'C:\表空間\dinya02.dbf'SIZE 5M; create tablespace dinya_space03 datafile 'C:\表空間\dinya03.dbf' SIZE 5M;

select * from user_tablespaces

                   <表空間->三個>

1.1)範圍分區

    範圍分區就是對數據表中的某個值的範圍進行分區,根據某個值的範圍,決定將該數據存儲在哪一個分區上。如根據序號分區,根據業務記錄的建立日期進行分區等。

    需求描述:有一個物料交易表,表名:material_transactions。該表未來可能有千萬級的數據記錄數。要求在建該表的時候使用分區表。這時候咱們可使用序號分區三個區,每一個區中預計存儲三千萬的數據,也可使用日期分區,如每五年的數據存儲在一個分區上。

根據交易記錄的序號分區建表:----爲了測試須要作如下修改;

create table dinya_test

   (

        transaction_id number primary key,

        item_id number(8) not null,

        item_description varchar2(300),

        transaction_date date  not null

    )

    partition by range (transaction_id)

    (

       partition part_01 values less than(2) tablespace dinya_space01,-----2條如下的交易在此分區上:part_01

      partition part_02 values less than(3) tablespace dinya_space02,-----等於+大於2而小於3的交易在此分區:part_02

      partition part_03 values less than(maxvalue) tablespace dinya_space03----大於3的交易在此分區:part_03

-----------------以上在pl/sql測試成功;

---------------- 如下沒有在pl/sql測試!

根據交易日期分區建表:

 

SQL> create table dinya_test

   (

        transaction_id number primary key,

        item_id number(8) not null,

       item_description varchar2(300),

       transaction_date date not null  

  )

    partition by range (transaction_date)

    (

   partition part_01 values less than(to_date('2006-01-01','yyyy-mm-dd')) tablespace dinya_space01,

   partition part_02 values less than(to_date('2010-01-01','yyyy-mm-dd')) tablespace dinya_space02,

  partition part_03 values less than(maxvalue) tablespace dinya_space03

  );

這樣咱們就分別建了以交易序號和交易日期來分區的分區表。每次插入數據的時候,系統將根據指定的字段的值來自動將記錄存儲到制定的分區(表空間)中。

固然,咱們還能夠根據需求,使用兩個字段的範圍分佈來分區,如partition by range ( transaction_id ,transaction_date),分區條件中的值也作相應的改變,請讀者自行測試。

---------------------------------以上沒有在pl/sql測試!

1.2) 範圍分區建立成功以後的相關操做測試;

 a)向表添加測試數據:

insert into dinya_test values(1,12,'BOOKS',sysdate);

insert into dinya_test values(2,12, 'BOOKS',sysdate+30);

insert into dinya_test values(3,12, 'BOOKS',to_date('2006-05-30','yyyy-mm-dd'));

insert into dinya_test values(4,12, 'BOOKS',to_date('2007-06-23','yyyy-mm-dd'));

insert into dinya_test values(5,12, 'BOOKS',to_date('2011-02-26','yyyy-mm-dd'));

insert into dinya_test values(6,12, 'BOOKS',to_date('2011-04-30','yyyy-mm-dd'));

b)查詢

   b.1)若是查詢全表數據

select * from dinya_test;以下圖:

                                < 全表數據>

select * from dinya_test partition(part_01);以下圖:

                              <Part_01分區的數據>

select * from dinya_test partition(part_02);以下圖:

                               <Part_02分區的數據>

select * from dinya_test partition(part_03);以下圖:

                               <Part_03分區的數據>

update dinya_test partition(part_01) t set t.item_description='DESK' where t.transaction_id=1;

select * from dinya_test partition(part_01);BOOKS->DESK(發生變化)

                  

select * from dinya_test(此結果就不用查看了,確定變了);

---刪除part_03分區中transaction_id=4的記錄:

delete from dinya_test partition(part_03) t where t.transaction_id=4;

select * from dinya_test partition(part_03)

             少了transaction_id=4的記錄(與上圖對比)

c)索引的建立:

   c.1)局部索引的建立:

create index dinya_idx_t on dinya_test(item_id)

  local

   (

     partition idx_1 tablespace dinya_space01,---分區名爲:idx_1

     partition idx_2 tablespace dinya_space02, ---分區名爲:idx_2

     partition idx_3 tablespace dinya_space03---分區名爲:idx_3

 );  ---pl/sql測試成功

注:

select *from ALL_TAB_PARTITIONS where table_name ='DINYA_TEST'

    select *From dba_ind_partitions where partition_name='IDX_1'

   c.2)全局索引的建立:

全局索引創建時global 子句容許指定索引的範圍值,這個範圍值爲索引字段的範圍值:

create index dinya_idx_t on dinya_test(item_id)

   global partition by range(item_id)

  (

     partition idx_1 values less than (1000) tablespace dinya_space01,

     partition idx_2 values less than (10000) tablespace dinya_space02,

     partition idx_3 values less than (maxvalue) tablespace dinya_space03

  );----PL/SQL末測試[參照以上local]

整個表建立索引:

   Create index dinya_idx_t on dinya_test(item_id);

備註: select *from all_indexes(dba_indexesall_ind_columns user_ind_columns dba_ind_columns)

1.3) Hash分區(散列分區)

——————————如下沒有在機器上測試

    散列分區爲經過指定分區編號來均勻分佈數據的一種分區類型,由於經過在I/O設備上進行散列分區,使得這些分區大小一致。如將物料交易表的數據根據交易ID散列地存放在指定的三個表空間中:

create table dinya_test

    (

        transaction_id number primary key,

        item_id number(8) not null,

        item_description varchar2(300),

        transaction_date date

   )

   partition by hash(transaction_id)

   (

       partition part_01 tablespace dinya_space01,

       partition part_02 tablespace dinya_space02,

       partition part_03 tablespace dinya_space03

  );

建表成功,此時插入數據,系統將按transaction_id將記錄散列地插入三個分區中,這裏也就是三個不一樣的表空間中。

——————————以上沒有在機器上測試;

 

1.4) 列表分區:該分區的特色是某列的值只有幾個,基於這樣的特色咱們能夠採用列表分區。

示例1

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

)     

備註:activeinactive是列status的值!謹記與rangehash分區的區別;

1.4.1)測試以下:

   insert into PROBLEM_TICKETS values(1,'BOOKS',1,sysdate,'ACTIVE');

insert into PROBLEM_TICKETS values(2,'son',2,sysdate+30,'INACTIVE');

insert into PROBLEM_TICKETS values(3,'son',3,to_date('2006-05-30','yyyy-mm-dd'),'INACTIVE');

insert into PROBLEM_TICKETS values(4,'BOOKS',4,to_date('2007-06-23','yyyy-mm-dd'),'INACTIVE');

insert into PROBLEM_TICKETS values(5,'old',5,to_date('2011-02-26','yyyy-mm-dd'),'ACTIVE');

insert intoPROBLEM_TICKETSvalues(6,'test',6,to_date('2011-04-30','yyyy-mm-dd'),'INACTIVE');

select * from PROBLEM_TICKETS

                                     <查詢全表>

1.4.2)

   select * from PROBLEM_TICKETS partition(PROB_ACTIVE)

1.4.2)

   select * from PROBLEM_TICKETS partition(PROB_INACTIVE)

  在測試中遇到這樣的狀況。若是表建立了分區,若是要刪除數據文件(表空間文件),則要先刪除分區,而後才能刪除數據文件(可是在刪除數據文件時,必需要保留一個分區才能最終刪除數據文件>表空間文件,)

固然,也能夠直接就刪除表也行,剛全部的全刪除,可是表空間文件還在!

 

1.5) 複合分區

 有時候咱們須要根據範圍分區後,每一個分區內的數據再散列地分佈在幾個表空間中,這樣咱們就要使用複合分區。複合分區是先使用範圍分區,而後在每一個分區內再使用散列分區的一種分區方法,如將物料交易的記錄按時間分區,而後每一個分區中的數據分三個子分區,將數據散列地存儲在三個指定的表空間中:

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_space07,dinya_space08,dinya_space09)

  (

      partition part_07 values less than(to_date('2006-01-01','yyyy-mm-dd')),

      partition part_08 values less than(to_date('2010-01-01','yyyy-mm-dd')),

      partition part_09 values less than(maxvalue)

  );

  ---測試以下:

   select *From user_tab_partitions where table_name=upper('dinya_test')

            selec *From user_tab_subpartitions where table_name=upper('dinya_test')

  

                            《圖1

 

   插入以下數據:

 insert into dinya_test values(1,12,'BOOKS',sysdate);

insert into dinya_test values(2,12, 'BOOKS',sysdate+30);

insert into dinya_test values(3,12, 'BOOKS',to_date('2006-05-30','yyyy-mm-dd'));

insert into dinya_test values(7,12, 'BOOKS',to_date('2005-05-30','yyyy-mm-dd'));

insert into dinya_test values(4,12, 'BOOKS',to_date('2007-06-23','yyyy-mm-dd'));

insert into dinya_test values(5,12, 'BOOKS',to_date('2011-02-26','yyyy-mm-dd'));

insert into dinya_test values(6,12, 'BOOKS',to_date('2011-04-30','yyyy-mm-dd'));

  select *From dinya_test:以下圖

select *From dinya_test partition(part_07)以下圖:

select *From dinya_test partition(part_09)

參照下圖,按所顯的子分區名,看可否查出數據:

select*Fromuser_tab_subpartitions where table_name=upper('dinya_test')

select *From dinya_test subpartition(SYS_SUBP62):以下圖:

其它的查詢同樣。-----測試成功;

   備註: 該例中,先是根據交易日期進行範圍分區,而後根據交易的ID將記錄散列地存儲在三個表空間中。

 

1.6) 複合範圍列表分區:這種分區是基於範圍分區和列表分區,表首先按某列進行範圍分區,而後再按某列進行列表分區,分區之中的分區被稱爲子分區。

示例1

Create table sales

(

Product_id varchar2(5),

Sales_date date,

Sales_cost number(10),

Status varchar2(20)

)

Partition by range(Sales_cost)

Subpartition by list(status)

(

Partition p1 values less than (1) tablespace  dinya_space01

(

Subpartition p1sub1 values('ACTIVE') tablespace   dinya_space03,

Subpartition p1sub2 values('INACTIVE') tablespace dinya_space04

),

Partition p2 values less than (3) tablespace  dinya_space02

 (

Subpartition p1sub3 values('ACTIVE') tablespace    dinya_space05,

Subpartition p1sub4 values('INACTIVE') tablespace dinya_space06

)

)測試以下:

insert into sales values(1,sysdate,0.1,'ACTIVE');

insert into sales values(2,sysdate+30,1,'INACTIVE');

insert into sales

values(3,to_date('2006-05-30','yyyy-mm-dd'),2,'INACTIVE');

select *From sales

        Select *from sales partition(p2)

       SELECT * FROM SALES SUBPARTITION(p1sub4)

SELECT * FROM SALES SUBPARTITION(p1sub3)

                           沒有數據!!

select *From dba_tab_subpartitions where table_name='SALES'

 

 有關表分區的一些維護性操做:

1、添加分區

如下代碼給SALES表添加了一個P3分區

ALTER TABLE SALES ADD PARTITION P3 VALUES LESS THAN(TO_DATE('2003-06-01','YYYY-MM-DD'));

注意:以上添加的分區界限應該高於最後一個分區界限。

如下代碼給SALES表的P3分區添加了一個P3SUB1子分區

ALTER TABLE SALES MODIFY PARTITION P3 ADD SUBPARTITION P3SUB1 VALUES('COMPLETE');

 

2、刪除分區

如下代碼刪除了P3表分區:

ALTER TABLE SALES DROP PARTITION P3;

  在測試中遇到這樣的狀況。若是表建立了分區,若是要刪除數據文件(表空間文件),則要先刪除分區,而後才能刪除數據文件(可是在刪除數據文件時,必需要保留一個分區才能最終刪除數據文件>表空間文件,)

固然,也能夠直接就刪除表也行,剛全部的全刪除,可是表空間文件還在!

 

在如下代碼刪除了P4SUB1子分區:

ALTER TABLE SALES DROP SUBPARTITION P4SUB1;

注意:若是刪除的分區是表中惟一的分區,那麼此分區將不能被刪除,要想刪除此分區,必須刪除表。

 

3、截斷分區

截斷某個分區是指刪除某個分區中的數據,並不會刪除分區,也不會刪除其它分區中的數據。當表中即便只有一個分區時,也能夠截斷該分區。經過如下代碼截斷分區:

ALTER TABLE SALES TRUNCATE PARTITION P2;

經過如下代碼截斷子分區:

ALTER TABLE SALES TRUNCATE SUBPARTITION P2SUB2;

 

4、合併分區

合併分區是將相鄰的分區合併成一個分區,結果分區將採用較高分區的界限,值得注意的是,不能將分區合併到界限較低的分區。如下代碼實現了P1 P2分區的合併:

ALTER TABLE SALES MERGE PARTITIONS P1,P2 INTO PARTITION P2;

 

5、拆分分區

拆分分區將一個分區拆分兩個新分區,拆分後原來分區再也不存在。注意不能對HASH類型的分區進行拆分。

ALTER TABLE SALES SBLIT PARTITION P2 AT(TO_DATE('2003-02-01','YYYY-MM-DD'))

INTO (PARTITION P21,PARTITION P22);

 

6、接合分區(coalesca)

結合分區是將散列分區中的數據接合到其它分區中,當散列分區中的數據比較大時,能夠增長散列分區,而後進行接合,值得注意的是,接合分區只能用於散列分區中。經過如下代碼進行接合分區:

ALTER TABLE SALES COALESCA PARTITION;

 

7、重命名錶分區

如下代碼將P21更改成P2

ALTER TABLE SALES RENAME PARTITION P21 TO P2;

 

9、跨分區查詢

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));

 

10、查詢表上有多少分區

SELECT * FROM useR_TAB_PARTITIONS WHERE TABLE_NAME='tableName'

 

 

--顯示數據庫全部分區表的信息:

select * from DBA_PART_TABLES where table_name=upper('dinya_test')

 

--顯示當前用戶可訪問的全部分區表信息:

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;

 

注:分區根據具體狀況選擇。

 

表分區有如下優勢:

1、數據查詢:數據被存儲到多個文件上,減小了I/O負載,查詢速度提升。

2、數據修剪:保存歷史數據很是的理想。

3、備份:將大表的數據分紅多個文件,方便備份和恢復。

4、並行性:能夠同時向表中進行DML操做,並行性性能提升。

================================================

 

索引:

1、通常索引:

create index index_name on table(col_name);

2Oracle 分區索引詳解

語法:Table Index

CREATE [UNIQUE|BITMAP] INDEX [schema.]index_name

ON [schema.]table_name [tbl_alias]

(col [ASC | DESC]) index_clause index_attribs

 

index_clauses:

分如下兩種狀況

 

1. Local Index

就是索引信息的存放位置依賴於父表的Partition信息,換句話說建立這樣的索引必須保證父表是Partition

1.1 索引信息存放在父表的分區所在的表空間。可是僅能夠建立在父表爲HashTable或者composite分區表的。

LOCAL STORE IN (tablespace)

1.2 僅能夠建立在父表爲HashTable或者composite分區表的。而且指定的分區數目要與父表的分區數目要一致

LOCAL STORE IN (tablespace) (PARTITION [partition [LOGGING|NOLOGGING] [TABLESPACE {tablespace|DEFAULT}] [PCTFREE int] [PCTUSED int] [INITRANS int] [MAXTRANS int] [STORAGE storage_clause] [STORE IN {tablespace_name|DEFAULT] [SUBPARTITION [subpartition [TABLESPACE tablespace]]]])

 

1.3 索引信息存放在父表的分區所在的表空間,這種語法最簡單,也是最經常使用的分區索引建立方式。

Local

1.4 而且指定的Partition 數目要與父表的Partition要一致

LOCAL (PARTITION [partition

[LOGGING|NOLOGGING]

[TABLESPACE {tablespace|DEFAULT}]

[PCTFREE int]

[PCTUSED int]

[INITRANS int]

[MAXTRANS int]

[STORAGE storage_clause]

[STORE IN {tablespace_name|DEFAULT]

[SUBPARTITION [subpartition [TABLESPACE tablespace]]]])

 

Global Index

索引信息的存放位置與父表的Partition信息徹底不相干。甚至父表是否是分區表都無所謂的。語法以下:

GLOBAL PARTITION BY RANGE (col_list)

( PARTITION partition VALUES LESS THAN (value_list)

[LOGGING|NOLOGGING]

[TABLESPACE {tablespace|DEFAULT}]

[PCTFREE int]

[PCTUSED int]

[INITRANS int]

[MAXTRANS int]

[STORAGE storage_clause] )

可是在這種狀況下,若是父表是分區表,要刪除父表的一個分區都必需要更新Global Index ,不然索引信息不正確

ALTER TABLE TableName DROP PARTITION PartitionName Update Global Indexes

 

 

--查詢索引

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

相關文章
相關標籤/搜索