2014年8月25日 星期一

Oracle 12c - Row-Archival



現在12C 有個新功能 In-Database Archiving 它允許在Row 上標記為不活躍的狀態,在進行操作時Oracle能自動略過不活躍的ROW,功能可以在session上個別控制


以下進行簡單的測試



--先建立測試的Table


SQL> create table row_archive_Test as select * from dba_objects;

已建立表格.

SQL> insert into row_archive_test select * from dba_objects;

已建立 90980 個資料列.

SQL> /

已建立 90980 個資料列.

SQL> /

已建立 90980 個資料列.

.......


--full table scan 看一下執行計畫如何




--把Table的標記功能開啟



SQL> alter table row_archive_test row archival;

已更改表格.

SQL>

--可以看到Table多了兩個隱藏的欄位, 其中ORA_ARCHIVE_STATE欄位,預設是0, 在官方的解釋裡只要設大於0表示是不活躍的資料

SQL>  SELECT COLUMN_NAME,DATA_TYPE,HIDDEN_COLUMN FROM DBA_TAB_COLS WHERE TABLE_N
AME='ROW_ARCHIVE_TEST';

COLUMN_NAME                    DATA_TYPE            HID
-------------------------     ------------------    -------
SYS_NC00019$                   RAW                   YES
ORA_ARCHIVE_STATE              VARCHAR2              YES
ORACLE_MAINTAINED              VARCHAR2              NO
EDITIONABLE                    VARCHAR2              NO
SHARING                        VARCHAR2              NO
EDITION_NAME                   VARCHAR2              NO
NAMESPACE                      NUMBER                NO


--在Session開啟功能


SQL> ALTER SESSION SET ROW ARCHIVAL VISIBILITY = ACTIVE;

已更改階段作業.

SQL>


此參數有兩個值一個是ALL 表示顯示出所有資料, 另外一個是ACTIVE 表示遮蔽不活躍的資料



--把資料進行標記為不活躍, 這邊全標記1


SQL>  UPDATE ROW_ARCHIVE_TEST SET ORA_ARCHIVE_STATE = '1' WHERE OWNER = 'SYS';

已更新 418150 個資料列.

SQL> COMMIT;

確認完成.


SQL>


--full table scan 看一下執行計畫如何



可以看到不活躍的資料都不被顯示出來


--更改參數為 ALL ,資料又可以全部看到

SQL> ALTER SESSION SET ROW ARCHIVAL VISIBILITY = ALL;

已更改階段作業.

SQL> select count(*) from ROW_ARCHIVE_TEST;

  COUNT(*)
----------
    908880




延伸閱讀


看到測試中的執行計畫可以發現,原來Oracle是利用ORA_ARCHIVE_STATE欄位進行篩選


那我們利用此欄位來讓 full table scan 的操作效能提升



--建立 bitmap index (因為只有1,0 建bitmap最適合)

SQL>  CREATE BITMAP INDEX index_row ON ROW_ARCHIVE_TEST(ORA_ARCHIVE_STATE);

已建立索引.

目前歷時: 00:00:01.32
SQL>


--full table scan 看一下執行計畫如何



這邊可以看到效能大幅的提升, 不過也僅止於 full table scan及某些特定的狀況下











2014年8月22日 星期五

Oracle 12c - Temporal Validity


Temporal Validity 在12C當中還算有趣的新功能,它可以自訂資料的時效性,只讓使用者看到時效內的資料

在Table開啟功能後Table中會自動新增兩個date類型欄位,一個是有效的起始,一個是有效期的結束,欄位可以由User指定也可以由Oracle自動配置,利用這兩個欄位與設定,讓使用者看到在時效內資料,過期的資料就不被看到,就很像是超商店員都會定時檢查飯團,不會讓你買到過期品


--先建立測試用Table 

SQL>  CREATE TABLE test_Redaction
  2      (
  3        t_id     NUMBER,
  4        t_name   VARCHAR2(50),
  5        t_add    VARCHAR2(50),
  6        t_phone  VARCHAR2(50),
  7        t_time   DATE
  8      )
  9      ;

已建立表格.

SQL>

--Insert into 資料

SQL> INSERT INTO TEST_REDACTION VALUES (101,'jimmy','senior program','7458-9658-3256',sysdate);

已建立 1 個資料列.

SQL> INSERT INTO TEST_REDACTION VALUES (102,'mike','general man','1236-6541-3214',sysdate);

已建立 1 個資料列.

SQL> INSERT INTO TEST_REDACTION VALUES (103,'eva','assistant','3574-1596-9856',sysdate);

已建立 1 個資料列.

SQL>

SQL> select * from test_redaction;

      T_ID T_NAME     T_ADD           T_PHONE         T_TIME
---------- ---------- --------------- --------------- -------------------
       101 jimmy      senior program  7458-9658-3256  2014-08-21 02:15:52
       102 mike       general man     1236-6541-3214  2014-08-21 02:17:12 
       103 eva        assistant       3574-1596-9856  2014-08-21 02:17:13


--授權

 GRANT EXECUTE ON dbms_flashback_archive TO test;

--對此session開啟 Temporal Validity


SQL> EXECUTE DBMS_FLASHBACK_ARCHIVE.enable_at_valid_time('CURRENT');



已順利完成 PL/SQL 程序.



--對Table新增功能欄位,這個部份可以手動指定欄位或者Oracle自己新增

自動新增
SQL> alter table test.test_redaction add period for track_time;

已更改表格.

手動指定新增(用此方法指定的欄位並不會被隱藏)
SQL>alter table test.TEST_re3 add period for track_time (t_time1_start,t_time2_end);
已更改表格.

SQL>

--這時候Table 會多3個隱藏欄位


SQL> SELECT COLUMN_NAME,DATA_TYPE,HIDDEN_COLUMN FROM DBA_TAB_COLS WHERE TABLE_NAME='TEST_REDACTION';



COLUMN_NAME          DATA_TYPE                           HID

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

TRACK_TIME           NUMBER                              YES

TRACK_TIME_END       TIMESTAMP(6) WITH TIME ZONE         YES
TRACK_TIME_START     TIMESTAMP(6) WITH TIME ZONE         YES
T_TIME               DATE                                NO
T_PHONE              VARCHAR2                            NO
T_ADD                VARCHAR2                            NO
T_NAME               VARCHAR2                            NO
T_ID                 NUMBER                              NO

已選取 8 個資料列.

SQL>

--設定資料有效的開始與結束


SQL> update test.test_redaction set track_time_start=sysdate ;



已更新 3 個資料列.

--在一分鐘後過期


SQL> update test.test_redaction set track_time_end=sysdate-1/1440 ;



已更新 3 個資料列.



SQL>



在資料過期後,用戶就被遮蔽搜尋不到資料了,不過實際上資料還在



SQL> select * from test_redaction;



沒有任何資料列被選取



SQL>

此功能似乎還不太健全,有時候在開啟功能後過期資料還會被搜尋到, 但過一陣子在搜尋一次過期的資料就搜尋不到了




--我們來看看執行計畫, Oracle 到底做了什麼

SQL> select * from test_redaction;



沒有任何資料列被選取



執行計畫
----------------------------------------------------------
Plan hash value: 3890191689
------------------------------------------------------------------------------------
| Id  | Operation         | Name           | Rows  | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |                |     1 |   133 |     3   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| TEST_REDACTION |     1 |   133 |     3   (0)| 00:00:01 |
------------------------------------------------------------------------------------


Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter(("T"."TRACK_TIME_START" IS NULL OR SYS_EXTRACT_UTC("T"."TRACK_TIME_START")<=SYS_EXTRACT_UTC(SYSTIMESTAMP(6))) AND ("T"."TRACK_TIME_END" IS NULL OR SYS_EXTRACT_UTC("T"."TRACK_TIME_END")>SYS_EXTRACT_UTC(SYSTIMESTAMP(6))))

Note
-----
   - dynamic statistics used: dynamic sampling (level=2)


統計資料
----------------------------------------------------------
         45  recursive calls
          0  db block gets
         37  consistent gets
          0  physical reads
          0  redo size
        609  bytes sent via SQL*Net to client
        532  bytes received via SQL*Net from client
          1  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          0  rows processed

SQL>

再執行計劃裡紅字的部份,原來 Oracle 在過程中加入了一個條件過濾



不過這功能玩起來算是新鮮有趣,在某些有時效性的場合,不用設計複雜的程式,直接就可以有此效果




2014年8月21日 星期四

Oracle 12c - Data Redaction



在11G要遮蔽 Table 欄位時,需要建立 View 來讓 User 無法看到某些欄位的機密資料,現在12C有個新功能叫" Data Redaction ",無須建立View只要下指令就可以達到遮蔽的效果,這個功能只在用戶端進行資料遮蔽並不會引響原來的資料。

就像以下這樣

原本

新增限制後

這樣具有隱私性的資料就會被遮蔽起來,只顯示後面的數字

*要注意的是User 擁有 EXP_FULL_DATABASE 以及 DBA 權限時,遮蔽則無效 


這個功能是使用 DBMS_REDACT 包來做管理
ADD_POLICY: Add a redaction policy to a table.
DROP_POLICY: Remove a redaction policy from a table.
ALTER_POLICY: Change a redaction policy.
ENABLE_POLICY: Enable a redaction policy after it is disabled.
DISABLE_POLICY: Disable a redaction policy.


對於資料遮蔽,Oracle 提供了很多種遮蔽效果,以下來一一做示範


先建立測試Table 

SQL> CREATE TABLE test.test_Redaction
  2  (
  3    t_id     NUMBER,
  4    t_name   VARCHAR2(50),
  5    t_add    VARCHAR2(50),
  6    t_phone  VARCHAR2(50),
  7    t_time   DATE
  8  )
  9  ;

已建立表格.

SQL> INSERT INTO TEST_REDACTION VALUES (101,'jimmy','senior program','7458-9658-3256',sysdate);

已建立 1 個資料列.

SQL> INSERT INTO TEST_REDACTION VALUES (102,'mike','general man','1236-6541-3214',sysdate);

已建立 1 個資料列.

SQL> INSERT INTO TEST_REDACTION VALUES (103,'eva','assistant','3574-1596-9856',sysdate);

已建立 1 個資料列.

SQL>

SQL> select * from test_redaction;

      T_ID T_NAME     T_ADD           T_PHONE         T_TIME
---------- ---------- --------------- --------------- -------------------
       101 jimmy      senior program  7458-9658-3256  2014-08-21 02:15:52
       102 mike       general man     1236-6541-3214  2014-08-21 02:17:12 
       103 eva        assistant       3574-1596-9856  2014-08-21 02:17:13





進行第一個遮蔽效果 "full",對於文字類型欄位顯示出來為空白,對於日期類型欄位顯示為2001-01-01,對於數字類型欄位顯式為0

BEGIN
DBMS_REDACT.ADD_POLICY (
   object_schema          => 'TEST',
   object_name            => 'TEST_REDACTION',
   policy_name            => 'TEST_POLICY',
   column_name            => 'T_ADD',
   function_type          => DBMS_REDACT.FULL,
   expression             => '1=1',
   enable                 => TRUE
   );
END;
/


SQL> select * from test.test_redaction;

      T_ID T_NAME     T_ADD           T_PHONE         T_TIME
---------- ---------- --------------- --------------- -------------------
       101 jimmy                      7458-9658-3256  2014-08-21 02:15:52
       102 mike                       1236-6541-3214  2014-08-21 02:17:12
       103 eva                        3574-1596-9856  2014-08-21 02:17:13



第二個效果是"PARTIAL",可以自訂function_parameters參數來顯示出我們指定的樣式



BEGIN
DBMS_REDACT.ALTER_POLICY (
   object_schema          => 'TEST',
   object_name            => 'TEST_REDACTION',
   policy_name            => 'TEST_POLICY',
   column_name            => 'T_PHONE',
   action                 => DBMS_REDACT.MODIFY_COLUMN,
   function_type          => DBMS_REDACT.PARTIAL,
   function_parameters    => 'VVVVFVVVVFVVVV,VVVV-VVVV-VVVV,*,1,6'   --*為替代得文字,從第1個文字開始到第6個文字都遮蔽
   );
END;
/


SQL> select * from test.test_redaction;

      T_ID T_NAME     T_ADD           T_PHONE         T_TIME
---------- ---------- --------------- --------------- -------------------
       101 jimmy                      ****-**58-3256  2014-08-21 02:15:52
       102 mike                       ****-**41-3214  2014-08-21 02:17:12
       103 eva                        ****-**96-9856  2014-08-21 02:17:13

SQL>

要為數字類型遮蔽時,替代符號只能使用1-9

數字範例
BEGIN
DBMS_REDACT.ALTER_POLICY (
   object_schema          => 'TEST',
   object_name            => 'TEST_REDACTION',
   policy_name            => 'TEST_POLICY',
   column_name            => 'T_ID',
   action                 => DBMS_REDACT.ADD_COLUMN,
   function_type          => DBMS_REDACT.PARTIAL,
   function_parameters    => '1,1,5'   
   );
END;

/

日期範例
BEGIN
dbms_redact.alter_policy (
   object_schema          => 'TEST',
   object_name            => 'TEST_REDACTION',
   policy_name            => 'TEST_POLICY',                         
   column_name           => 'T_TIME',
   action                => dbms_redact.MODIFY_COLUMN,
   function_type          => DBMS_REDACT.PARTIAL,
   function_parameters   => 'Md15y2010HMS',                          
   expression            => '1=1');
END;

/

Md15y2010HMS > 顯示出來的日期一率為15 ,年一率為2010 ,前面的英文小寫才有效果

MDYHMS > 月日年時分秒 , 此為固定格式



第三個效果是"RANDOM",對於文字與數字會變成具有相同長度的隨機文字與數字,對於日期會變成隨機日期,上述說的隨機都不會與原來的相同

BEGIN
DBMS_REDACT.ALTER_POLICY (
   object_schema          => 'TEST',
   object_name            => 'TEST_REDACTION',
   policy_name            => 'TEST_POLICY',
   column_name            => 'T_PHONE',
   action                 => DBMS_REDACT.MODIFY_COLUMN,
   function_type          => DBMS_REDACT.RANDOM
   );
END;
/


SQL> select * from test.test_redaction;

      T_ID T_NAME     T_ADD           T_PHONE         T_TIME
---------- ---------- --------------- --------------- -------------------
      101 jimmy      senior program  >*}$Y5n_F2&,a=  2014-08-21 02:15:52
      102 mike       general man     x.eIMi:A!6mQUq  2014-08-21 02:17:12
    103 eva        assistant       *`"*PE#g2h*2XM  2014-08-21 02:17:13


SQL>


第四種是"REGEXP"使用 正規表達式是來規範


Data Redaction 功能還可以設定只對哪些 User 進行遮蔽

BEGIN
DBMS_REDACT.ALTER_POLICY (
   object_schema          => 'TEST',
   object_name            => 'TEST_REDACTION',
   policy_name            => 'TEST_POLICY',
   column_name            => 'T_PHONE',
   action                 => DBMS_REDACT.MODIFY_EXPRESSION,
   expression             => 'SYS_CONTEXT ( ''USERENV'',''SESSION_USER'' ) = ''jimmy''');
END;
/

對於jimmy這個User進行遮蔽,其他User則可以看到全部內容



取消欄位的遮蔽

BEGIN
DBMS_REDACT.ALTER_POLICY (
   object_schema          => 'TEST',
   object_name            => 'TEST_REDACTION',
   policy_name            => 'TEST_POLICY',
   column_name            => 'T_ADD',
   action                 => DBMS_REDACT.MODIFY_COLUMN,
   function_type          => DBMS_REDACT.NONE
   );
END;
/


新增其他欄位的遮蔽

BEGIN
DBMS_REDACT.ALTER_POLICY (
   object_schema          => 'TEST',
   object_name            => 'TEST_REDACTION',
   policy_name            => 'TEST_POLICY',
   column_name            => 'T_NAME',
   action                 => DBMS_REDACT.ADD_COLUMN,
   function_type          => DBMS_REDACT.FULL
);
END;
/


刪除Table的遮蔽

BEGIN
   DBMS_REDACT.DROP_POLICY (
   object_schema          => 'CHECK_DB',
   object_name            => 'TEST_REDACTION',
   policy_name            => 'TEST_POLICY');
END;
/




資料的遮蔽對於 where 的條件有無影響?!

原始資料
SQL> select * from test.test_redaction;

      T_ID T_NAME          T_ADD           T_PHONE         T_TIME
---------- --------------- --------------- --------------- -------------------
       101 jimmy           senior program  7458-9658-3256  2014-08-21 02:15:52
       102 mike            general man     1236-6541-3214  2014-08-21 02:17:12
       103 eva             assistant       3574-1596-9856  2014-08-21 02:17:13


對遮蔽後的資料進行select


SQL> select * from test.test_redaction where t_id =101;


      T_ID T_NAME     T_ADD           T_PHONE         T_TIME
---------- ---------- --------------- --------------- -------------------
       111 jimmy      senior program  7458-9658-3256  2014-08-21 02:15:52


SQL> select * from test.test_redaction where t_id =102;

      T_ID T_NAME     T_ADD           T_PHONE         T_TIME
---------- ---------- --------------- --------------- -------------------
       111 mike       general man     1236-6541-3214  2014-08-21 02:17:12


由此可以判斷資料在處理後,在客戶端這邊才進行遮蔽。



可以對利用create table select * from  方式把資料複製出去?!

SQL> create table test100 as select * from test.test_redaction;
create table test100 as select * from test.test_redaction
                               *
 ERROR 在行 1:
ORA-28081: 權限不足 - 命令參照隱匿的物件.


--刪除遮蔽policy

BEGIN
   DBMS_REDACT.DROP_POLICY (
   object_schema          => 'TEST',
   object_name            => 'TEST_REDACTION',
   policy_name            => 'TEST_POLICY');
END;
/


SQL> create table test100 as select * from  test.test_redaction;

已建立表格.

SQL>


在我們刪除policy後才能複製表格,很顯然的並不能用這種方式把資料複製出去。









2014年8月20日 星期三

Oracle 12c - Online Statistics Gathering for Bulk-Load 資料批量新增的在線資訊收集


在12C 提出來的新功能 資料批量新增自動收集資訊 Online Statistics Gathering for Bulk-Load
通過這個功能, 在進行某項操作例如:create table as select 或是 insert into .. select * from table,統計資訊會自動的收集


這個功能可以節省一次手動執行analyze的步驟,也可能的減少前面幾次 full table scan,對於Table經常性大量新增資料的資料庫是有不錯的幫助

在對Table進行 Online Statistics Gathering for Bulk-Load 時,Oacle 是不會自動對 index 收集資訊以及直方圖,要是有這個需求,必須還要再進行 DBMS_STATS.GATHER_TABLE_STATS 一次





這個功能還是有所限制的,根據官方的文件說明限制有


It is in an Oracle-owned schema such as SYS.
It is a nested table.
It is an index-organized table (IOT).
It is an external table.
It is a global temporary table defined as ON COMMIT DELETE ROWS.
It has virtual columns.
It has a PUBLISH preference set to FALSE.
Its statistics are locked.
It is partitioned, INCREMENTAL is set to true, and extended syntax is not used.
It is loaded using a multitable insert statement.


PS:12C預設是把這個功能開啟的


以下是做的簡單測試

SQL>  create table test_online as select * from dba_objects ;

已建立表格.

目前歷時: 00:00:01.68

SQL> select num_rows,blocks,last_analyzed 
 2 from dba_tables where table_name ='TEST_ONLINE';


  NUM_ROWS     BLOCKS LAST_ANALYZED
---------- ---------- --------------
     90855       1560 20-8月 -14

目前歷時: 00:00:00.12



SQL> alter session set "_optimizer_gather_stats_on_load"=false;

已更改階段作業.

目前歷時: 00:00:00.00

SQL> create table test_online2 as select * from dba_objects ;

已建立表格.

目前歷時: 00:00:01.17

SQL> select num_rows,blocks,last_analyzed 
 2 from dba_tables where table_name ='TEST_ONLINE2';

  NUM_ROWS     BLOCKS LAST_ANALYZED
---------- ---------- --------------


目前歷時: 00:00:00.28
SQL>


這邊可以看到開啟參數後 create table 速度降低, 為了能自動收集資訊看來還是有所犧牲的  



在官方的說明文件裡還有提到, insert 要使用Online Statistics Gathering for Bulk-Load 時 必須使用加上 /*+APPEND */ hint.

以下是簡單的測試


SQL> create table test_online3 (t1 number, t2 varchar2(200));

已建立表格.

目前歷時: 00:00:00.04
SQL> insert  into test_online3 select 11,'123' 
 2 from dual connect by level<=9000;


已建立 9000 個資料列.

目前歷時: 00:00:00.11
SQL> select num_rows,blocks,last_analyzed 
 2 from dba_tables where table_name ='TEST_ONLINE3';

  NUM_ROWS     BLOCKS LAST_ANALYZED
---------- ---------- -------------------


目前歷時: 00:00:00.03

SQL>


SQL> create table test_online4 (t1 number, t2 varchar2(200));

已建立表格.

目前歷時: 00:00:00.01
SQL> insert /*+ append */  into test_online4 select 11,'123' 
 2 from dual connect by level<=9000;

已建立 9000 個資料列.

目前歷時: 00:00:00.11
SQL> select num_rows,blocks,last_analyzed 
 2 from dba_tables where table_name ='TEST_ONLINE4';

  NUM_ROWS     BLOCKS LAST_ANALYZED
---------- ---------- -------------------
      9000        100 2014-08-20 04:12:23

目前歷時: 00:00:00.04

SQL>










2014年8月19日 星期二

Oracle 12c - Table partition 指令功能增強





11G Table partition 要新增 partition 分區時或進行其他維護時,都要針對每個分區一個一個下 alter table add partition 指令

現在12C 只要一條指令就可以完成新增刪除分割 partition 的動作,就不用麻煩的下多條指令



以下是對新增 Partition 的簡單示範

先建立Partition
  1. create table test_par2 
  2.   (
  3.        seq_id  number,
  4.        txt     varchar2(4000 char),
  5.        t_time  date
  6.   )
  7. partition by range (t_time)
  8. (  
  9.   partition p_time_2014_06 values less than (to_date(' 2014-07-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')),  
  10.   partition p_time_2014_07 values less than (to_date(' 2014-08-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN'))
  11. );


  1. SQL>  select partition_name from dba_tab_partitions where table_name = 'TEST_PAR2';

  2. PARTITION_NAME
  3. ---------------
  4. P_TIME_2014_07
  5. P_TIME_2014_06

新增 Partition 分區
  1. ALTER TABLE  test_par2  ADD 
  2.   PARTITION P_TIME_2014_08 VALUES LESS THAN (TO_DATE(' 2014-09-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')),
  3.   PARTITION P_TIME_2014_09 VALUES LESS THAN (TO_DATE(' 2014-10-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')),
  4.   PARTITION P_TIME_2014_10 VALUES LESS THAN (TO_DATE(' 2014-11-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN'));


  1. SQL>  select partition_name from dba_tab_partitions where table_name = 'TEST_PAR2';

  2. PARTITION_NAME
  3. ---------------
  4. P_TIME_2014_07
  5. P_TIME_2014_06
  6. P_TIME_2014_08
  7. P_TIME_2014_09
  8. P_TIME_2014_10

新增成功,只要 Maxvalue 分區沒建立,你就可以新增多個 Partition 進去


對於刪除 Partition 的簡單示範
  1. SQL>     alter table check_db.test_par2 drop partitions p_time_2014_09,p_time_2014_10;

  2. 已更改表格.

  3. SQL>

  1. SQL>   alter table check_db.test_par2 truncate partitions p_time_2014_09,p_time_2014_10;

  2. 已更改表格.

  3. SQL>


對於分割 Partition 的簡單示範
  1. create table test_par2
  2. (
  3.    seq_id   number,
  4.    txt      varchar2 (4000 char),
  5.    nb       number
  6. )
  7. partition by range (nb)
  8.    (
  9.       partition p_01 values less than (1000),
  10.       partition p_02 values less than (2000),
  11.       partition p_max values less than (maxvalue)
  12. );


  1. alter table test_par2  split partition p_max
  2.       into (partition p3 values less than (2500),
  3.               partition p4 values less than (4000),
  4.               partition p_max);

查看是否成功

  1. SQL>  select partition_name, high_value from dba_tab_partitions
  2.   2      where table_name = 'TEST_PAR2';

  3.   PARTITION_NAME        HIGH_VALUE
  4. ------------------------ ------------------------------
  5. P_03                                          2500
  6. P_04                                          4000
  7. P_01                                          1000
  8. P_02                                          2000
  9. P_MAX                                     MAXVALUE

成功分割!!!


對於合併 Partition 的簡單示範

  1. alter table test_par2 merge partitions p2,p3,p4 into partition p_sum;


  1. SQL>  select partition_name, high_value from dba_tab_partitions
  2.   2      where table_name = 'TEST_PAR2';

  3. PARTITION_NAME            HIGH_VALUE
  4. -----------------------------         ------------------------
  5. P_SUM                                    4000
  6. P_01                                          1000
  7. P_MAX1                                  MAXVALUE

合併後的 HIGH_VALUE 會是指定 Partition 的最大值