Oracle間隔(interval)分區

(一)什麼是間隔分區html

間隔分區是Oracle 11.1引入的新功能,經過該功能,能夠在輸入相應分區的數據時自動建立相應的分區。在沒有間隔分區技術以前,DBA一般會建立一個maxvalue分區以免ORA-14400:插入的分區鍵值不能映射到任何分區("inserted partition key does not map to any partition") 錯誤。數據庫

做爲範圍分區(range partition)的擴展,間隔分區命令數據庫在插入表中的數據超過全部現有範圍分區時自動建立指定間隔的分區。DBA必須至少指定一個範圍分區的較高值,稱爲過渡點,數據庫會自動的爲超出該過渡點的數據建立間隔分區,每一個間隔分區的下邊界是先前範圍或間隔分區的上邊界。express

 

(二)建立間隔分區oracle

(2.1)間隔分區建立語法運維

CREATE TABLE table_name
(
  ...
)
PARTITION BY RANGE(column1)
INTERVAL expr [STORE IN (tablespace1,[tablespace2,...])]
(
  PARTITION partition_name1 VALUES LESS THAN(literal | MAXVALUE) [TABLESPACE tablespace1],
  PARTITION partition_name2 VALUES LESS THAN(literal | MAXVALUE) [TABLESPACE tablespace2]
);

--PARTITION BY RANGE(column1):指定一個分區範圍列函數

--INTERVAL:指定分區間隔學習

--STORE IN:指定分區存儲的表空間測試

 

(2.2)間隔分區建立限制ui

間隔分區是範圍分區的擴展,其支持範圍有限,在Oracle 11g中,間隔分區只能指定一個分區鍵列,而且數據類型必須爲NUMBER或者DATE類型。由於TIMESTAMP數據類型是DATE類型的擴展,可在分區鍵中使用。總結來講,間隔分區只支持NUMBER和TIME類型。this

 

(2.3)INTERVAL關鍵字解讀

image

在建立自動間隔分區的時候,最爲核心的就是」INTERVAL「關鍵字了。對於按照時間進行自動分區,INTERVAL後面能夠跟隨NUMTOYMINTERVAL和NUMTODSINTERVAL。兩個關鍵字用法以下:

(2.3.1)NUMTOYMINTERVAL(x,c)

用法:x是一個數據,c是一個字符串,該函數是將x轉爲interval year to month類型。經常使用單位有:」year「、」month「。

例子:當前時間加3年,當前時間加3個月

SELECT   SYSDATE,
         SYSDATE + NUMTOYMINTERVAL(3,'year')  AS "3年後" ,
         SYSDATE + NUMTOYMINTERVAL(3,'month') AS "3個月後"
  FROM   dual;

image

 

(2.3.2)NUMTODSINTERVAL(x,c)

用法:x是一個數據,c是一個字符串,該函數是將x轉爲interval day to second類型。經常使用單位有:」day「、」hour「、」minute「、」second「。

例子:當前時間加1天、1小時、1分鐘、1秒鐘。

image

 

(三)按時間(年、月、日、周)建立間隔分區

(3.1)按」年「自動建立分區(關鍵字:NUMTOYMINTERVAL)

例子:建立按年自動分區表,按照員工生日(birthday字段),每一年一個分區。

--建立按年分區表

CREATE TABLE interval_year_table01
(
  employee_id         NUMBER,
  employee_name       VARCHAR2(20),
  birthday            DATE    
)
PARTITION BY RANGE(birthday)
INTERVAL (NUMTOYMINTERVAL(1,'year')) STORE IN (tbs01,tbs02,tbs03)
(
  PARTITION partition2014 VALUES LESS THAN(to_date('2015-01-01:00:00:00','yyyy-mm-dd hh24:mi:ss')),
  PARTITION partition2015 VALUES LESS THAN(to_date('2016-01-01:00:00:00','yyyy-mm-dd hh24:mi:ss'))
);

 

(3.2)按」月「自動建立分區(關鍵字:NUMTOYMINTERVAL)

例子:建立按月自動分區表,按照員工生日(birthday字段),每個月一個分區。

-- 建立按月分區表

CREATE TABLE interval_month_table01
(
  employee_id         NUMBER,
  employee_name       VARCHAR2(20),
  birthday            DATE    
)
PARTITION BY RANGE(birthday)
INTERVAL (NUMTOYMINTERVAL(1,'month')) STORE IN (tbs01,tbs02,tbs03)
(
  PARTITION partition201401 VALUES LESS THAN(to_date('2014-02-01:00:00:00','yyyy-mm-dd hh24:mi:ss'))
);

 

(3.3)按」天(日)「自動建立分區(關鍵字:NUMTODSINTERVAL)

例子:建立按天自動分區表,按照員工生日(birthday字段),天天一個分區。

-- 按天(日)建立分區
CREATE TABLE interval_day_table01
(
  employee_id         NUMBER,
  employee_name       VARCHAR2(20),
  birthday            DATE    
)
PARTITION BY RANGE(birthday)
INTERVAL (NUMTODSINTERVAL(1,'day')) STORE IN (tbs01,tbs02,tbs03)
(
  PARTITION partition20140101 VALUES LESS THAN(to_date('2014-01-01 00:00:00','yyyy-mm-dd hh24:mi:ss'))
);

 

(3.4)按」周「自動建立分區(關鍵字:NUMTODSINTERVAL)

例子:建立按周自動分區表,按照員工生日(birthday字段),每週一個分區。須要注意的是,這裏使用的關鍵字與「天」分區同樣,都是「day」,只是改成了7天。

-- 按周建立分區

CREATE TABLE interval_week_table01
(
  employee_id         NUMBER,
  employee_name       VARCHAR2(20),
  birthday            DATE    
)
PARTITION BY RANGE(birthday)
INTERVAL (NUMTODSINTERVAL(7,'day')) STORE IN (tbs01,tbs02,tbs03)
(
  PARTITION partition201401w VALUES LESS THAN(to_date('2014-01-07 00:00:00','yyyy-mm-dd hh24:mi:ss'))
);

 

(3.4)按」小時「自動建立分區(關鍵字:NUMTODSINTERVAL)

-- 按」小時」進行分區
CREATE TABLE interval_hour_table01
(
  employee_id         NUMBER,
  employee_name       VARCHAR2(20),
  birthday            DATE    
)
PARTITION BY RANGE(birthday)
INTERVAL (NUMTODSINTERVAL(1,'hour')) STORE IN (tbs01,tbs02,tbs03)
(
  PARTITION partition20140100 VALUES LESS THAN(to_date('2014-01-01 01:00:00','yyyy-mm-dd hh24:mi:ss'))
);

除此以外,還能夠按」分鐘「、」秒「進行自動分區。

 

(四)按數字(number)建立間隔分區

例子:按數字進行分區相對簡單,這裏相近的10個數字進入同一個分區

CREATE TABLE interval_number_table01
(
  employee_id         NUMBER,
  employee_name       VARCHAR2(20),
  birthday            DATE    
)
PARTITION BY RANGE(employee_id)
INTERVAL (10) STORE IN (tbs01,tbs02,tbs03)
(
  PARTITION partition10 VALUES LESS THAN(10)
);

 

(五)關於間隔分區的常見問題

(5.1)如何將現有普通錶轉換爲間隔分區

可使用以下命令將現有的範圍分區錶轉換爲間隔分區表,注意,僅僅支持範圍分區表:

ALTER TABLE <table_name> SET INTERVAL <number or interval expression>;

 

(5.2)如何爲現有表設置新的間隔

可使用以下命令修改間隔,該操做不會使index不可用:

ALTER TABLE <table_name> SET INTERVAL(interval express);

例子見MOS文檔(1479115.1)。

 

(5.3)如何爲間隔分區指定/更改表空間

INTERVAL子句的STORE IN用於指定建立間隔分區的表空間。若是指定了表空間列表,將以循環方式在這些表空間上建立間隔分區。

INTERVAL expr [STORE IN (tablespace1,[tablespace2,...])]

須要注意的是,在INTERVAL子句中使用」PARTITION「建立的範圍分區須要指出表空間,不然會將範圍分區建立到用戶默認的表空間中,而不是[STORE IN]的表空間中。

 

對於已經建立的分區,可使用如下命令將其移動到特定的表空間:

--移動分區到特定表空間
ALTER TABLE <table_name> MOVE PARTITION <partition_name> TABLESPACE <tablespace_name>;

--注:移動分區會致使全局索引失效,需謹慎

 

(5.4)自動建立的間隔分區的名稱是什麼

數據庫建立的間隔分區的名稱是系統自動生成的,能夠經過dba_tab_partition視圖查看。目前沒法爲分區指定建立模板,可是能夠重命名分區。

例子:自動建立的表空間的名稱

insert into INTERVAL_NUMBER_TABLE01 values (201209, 'name09');
insert into INTERVAL_NUMBER_TABLE01 values (201210, 'name10');
insert into INTERVAL_NUMBER_TABLE01 values (201211, 'name11');
insert into INTERVAL_NUMBER_TABLE01 values (201212, 'name12');
insert into INTERVAL_NUMBER_TABLE01 values (201301, 'name01');
insert into INTERVAL_NUMBER_TABLE01 values (201402, 'name02');
insert into INTERVAL_NUMBER_TABLE01 values (201503, 'name03');

SQL> select  table_owner,table_name,partition_name,high_value,tablespace_name,interval
  2  from    dba_tab_partitions
  3  where   table_name = 'INTERVAL_NUMBER_TABLE01';

TABLE_OWNER    TABLE_NAME                     PARTITION_NAME     HIGH_VALUE    TABLESPACE_NAME   INTERVAL
-------------- ------------------------------ -----------------  ------------ ----------------- --------
LIJIAMAN       INTERVAL_NUMBER_TABLE01        PARTITION10        10            USERS             NO
LIJIAMAN       INTERVAL_NUMBER_TABLE01        SYS_P54            20            TBS02             YES
LIJIAMAN       INTERVAL_NUMBER_TABLE01        SYS_P55            110           TBS02             YES
LIJIAMAN       INTERVAL_NUMBER_TABLE01        SYS_P56            120           TBS03             YES
LIJIAMAN       INTERVAL_NUMBER_TABLE01        SYS_P57            130           TBS01             YES


--備註:INTERVAL = 'YES'表明自動建立的分區

 

(5.5)使用DBMS_METADATA.GET_DDL檢索表時,爲何缺乏系統生成的間隔分區?

"DBMS_METADATA.GET_DDL"只提供用戶手段建立的分區,而不提供系統自動生成的分區。如下爲測試例子:

SQL> SELECT DBMS_METADATA.GET_DDL('TABLE','INTERVAL_NUMBER_TABLE01','LIJIAMAN') FROM DUAL;

DBMS_METADATA.GET_DDL('TABLE',
--------------------------------------------------------------------------------
  CREATE TABLE "LIJIAMAN"."INTERVAL_NUMBER_TABLE01" 
   (  "EMPLOYEE_ID" NUMBER, 
      "EMPLOYEE_NAME" VARCHAR2(20), 
      "BIRTHDAY" DATE
   ) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 
  STORAGE(
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "USERS" 
  PARTITION BY RANGE ("EMPLOYEE_ID") INTERVAL (10) STORE IN ("TBS01", "TBS02", "TBS03") 
 (PARTITION "PARTITION10"  VALUES LESS THAN (10) SEGMENT CREATION IMMEDIATE 
  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 
  NOCOMPRESS LOGGING 
  STORAGE(INITIAL 8388608 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "USERS" )

若是要輸出系統自動建立的分區的腳本,需將DBMS_METDATA的EXPORT參數設置爲true

exec dbms_metadata.set_transform_param(dbms_metadata.SESSION_TRANSFORM,'EXPORT',true);

 

(六)關於間隔分區的bug

之前在使用分區表時,遇到過由延遲段建立(deferred_segment_creation)引發的段分配異常問題。間隔分區也有相似的bug,使用須要謹慎。


Bug 16042673 - Database hang when system trying to add interval partition to the table (Doc ID 16042673.8)

Symptoms:
Related To:
Description
This bug is only relevant when using Partitioned Tables
Concurrent   insert   statements   issued   against  an   interval 
partitioned  table resulting  in the  creation of a new partition 
blocks remaining inserts into the same table.
 
Rediscovery Notes
 If  concurrent  insert  statements  are issued  against  an  interval 
 partitioned  table  and the  insert  statement which  results  in the 
 creation of  a new partition  blocks all  the other  inserts into the 
 table, then we might be encountering this bug.

 

(七)間隔分區的利弊思考

好處:間隔分區經過系統自動建立分區,減小了DBA的平常運維工做,避免了ORA-14400這類錯誤,每一年年終不須要爲下一年手動建立分區,想一想仍是挺開心的;

壞處:由於系統自動建立分區名稱,咱們沒法經過分區名稱來判斷數據的存放位置,增長了後期的維護難度。舉個例子,若是是DBA手動維護,假設表的分區」part_201901「存儲的就是2019年1月的數據,假如咱們想要刪除1月份的數據,直接刪除該分區便可,若是數據庫裏面有500個相似的表,直接寫批量腳本」ALTER TABLE <table_name> DROP PARTITION part_201901「就將所有表的1月份的數據刪除了,可是對於系統自動建立的分區,在不一樣的表裏面,2019年1月的數據對應的分區名不一樣,天然沒法使用腳本批量刪除,即便有腳本,也很是麻煩。

 

 

-------------------------------------------------------------------------------------------------------

我的分區(partition)技術相關文檔:

1. [oracle]分區表學習    
2. [Oracle]分區索引     
3. Oracle分區表刪除分區引起錯誤ORA-01502: 索引或這類索引的分區處於不可用狀態    
4. Oracle split分區表引發ORA-01502錯誤
5. Oracle在線重定義(online redefinition)--將普通表改成分區表

參考文檔:

1. Interval Partitioning Essentials - Common Questions - Top Issues (Doc ID 1479115.1)
2. How to Build an INTERVAL PARTIONED Table using a NUMBER datatype for the INTERVAL Partition. (Doc ID 1514047.1)
3. Bug 16042673 - Database hang when system trying to add interval partition to the table (Doc ID 16042673.8)

-------------------------------------------------------------------------------------------------------

相關文章
相關標籤/搜索