2016-12-09 28 views
1

我有此表爲我主要表(100M行):交換/移動分區

create table prova_log(
     id_dispositive  number, 
     type     number, 
     date_verification date, 
     status    number 
) 
partition by range (date_verification) interval (NUMTODSINTERVAL(3,'DAY')) 
subpartition by list (type) 
subpartition TEMPLATE (
    SUBPARTITION type1 VALUES (1), 
    SUBPARTITION type2 VALUES (2), 
    SUBPARTITION type3 VALUES (3), 
    SUBPARTITION type4 VALUES (4) 
)       
(
    partition p0816 values less than (to_date('01/09/2016','dd/mm/yyyy')) 
); 

我想使某種與舊值的備份,所以我創造了這個(0行):

create table prova_log_old (
     id_dispositive  number, 
     type     number, 
     date_verification date, 
     status    number 
) 
partition by range (date_verification) interval (NUMTODSINTERVAL(3,'DAY')) 
subpartition by list (type) 
subpartition TEMPLATE (
    SUBPARTITION type1 VALUES (1), 
    SUBPARTITION type2 VALUES (2), 
    SUBPARTITION type3 VALUES (3), 
    SUBPARTITION type4 VALUES (4) 
)       
(
    partition p_old values less than (to_date('01/09/2016','dd/mm/yyyy')) 
); 

所以我想移動/複製/交換(無論長期)舊的分區(15天+),以prova_log_old

要做到這一點,我創建了這個工作:

PROCEDURE move_data_from_huge_table 
    IS 
     -- This will move all data after 'vcountdaystokeepdata' days 
     vcountdaystokeepdata  NUMBER := 15; 
     vcountdatainsidepartition NUMBER := 0; 
    BEGIN 
     FOR item IN 
     (SELECT * 
      FROM (SELECT partition_name, 
         TO_DATE 
          (TRIM 
           ('''' FROM REGEXP_SUBSTR 
              (EXTRACTVALUE 
               (DBMS_XMLGEN.getxmltype 
                ( 'select high_value from all_tab_partitions where table_name=''' 
                 || table_name 
                 || ''' and table_owner = ''' 
                 || table_owner 
                 || ''' and partition_name = ''' 
                 || partition_name 
                 || '''' 
                ), 
                '//text()' 
               ), 
               '''.*?''' 
              ) 
           ), 
          'syyyy-mm-dd hh24:mi:ss' 
          ) high_value 
        FROM all_tab_partitions 
        WHERE table_name = 'PROVA_LOG') 
      WHERE high_value < SYSDATE - vcountdaystokeepdata) 
     LOOP     
     EXECUTE IMMEDIATE 'alter table PROVA_LOG EXCHANGE PARTITION ' 
          || item.partition_name 
          || ' with table PROVA_LOG_OLD'; 

     EXECUTE IMMEDIATE 'select count(*) from PROVA_LOG partition (' 
          || item.partition_name 
          || ')' 
         INTO vcountdatainsidepartition; 

     IF vcountdatainsidepartition = 0 
     THEN 
      EXECUTE IMMEDIATE 'ALTER TABLE PROVA_LOG DROP PARTITION ' 
           || item.partition_name 
           || ''; 
     END IF; 

     END LOOP; 
    END; 

但是,當我跑我

ORA-14292表的分區類型必須複合分割

的子分區類型匹配的程序

我假設我的備份表中必須有一個與我的主分區表同名的分區吧?

我該如何做這項工作?

我試圖add分區到我的備份表,但沒有成功..重要的是要提到,所有分區的名稱是隨機的(甲骨文生成它)。

+0

你爲什麼要/移動數據複製到另一個表?這是分區表的主要優點之一,您不需要這些東西。 –

+0

@WernfriedDomscheit因爲我有另一項工作來計算這些數百萬行的日期範圍。即使劃分了這個過程需要很長的時間,當表是500M +行......反正......我想「下降」(而不會丟失)更老的瓦,因爲我不再需要它們了。 –

回答

2

我還是不明白你爲什麼要移動分區,無論如何我有一個解決方案。

首先,你可以解決一個分區要麼喜歡

SELECT COUNT(*) FROM PROVA_LOG PARTITION (SYS_P7138); 

,或者你可以做到這一點作爲

SELECT COUNT(*) FROM PROVA_LOG PARTITION FOR (TO_DATE('2016-10-01', 'YYYY-MM-DD')); 

或者如果你喜歡DATE文字

SELECT COUNT(*) FROM PROVA_LOG PARTITION FOR (DATE '2016-10-01'); 

自動解決方案爲您的問題可能是這樣的:

DECLARE 

    CURSOR TabPartitions IS 
    SELECT TABLE_NAME, PARTITION_NAME, HIGH_VALUE 
    FROM USER_TAB_PARTITIONS 
    WHERE TABLE_NAME = 'PROVA_LOG' 
    ORDER BY 1,2; 

    ts DATE; 

BEGIN 
    FOR aPart IN TabPartitions LOOP 
     EXECUTE IMMEDIATE 'BEGIN :ret := '||aPart.HIGH_VALUE||'; END;' USING OUT ts; 
     IF ts <> DATE '2016-09-10' AND ts < SYSDATE - 15 THEN 
      --EXECUTE IMMEDIATE 'INSERT INTO PROVA_LOG_OLD SELECT * FROM PROVA_LOG PARTITION FOR (DATE '''||TO_CHAR(ts, 'yyyy-mm-dd')||''')'; 
      --EXECUTE IMMEDIATE 'ALTER TABLE PROVA_LOG DROP PARTITION FOR (DATE '''||TO_CHAR(ts, 'yyyy-mm-dd')||''') UPDATE GLOBAL INDEXES'; 
      EXECUTE IMMEDIATE 'ALTER TABLE PROVA_LOG EXCHANGE PARTITION FOR (DATE '''||TO_CHAR(ts, 'yyyy-mm-dd')||''') WITH TABLE PROVA_LOG_OLD INCLUDING INDEXES'; 
     END IF; 
    END LOOP; 

END; 

您的備份表必須是這樣的:

CREATE TABLE prova_log_old (
     id_dispositive  NUMBER, 
     TYPE     NUMBER, 
     date_verification DATE, 
     status    NUMBER 
) 
PARTITION BY LIST (TYPE) 
(
    PARTITION type1 VALUES (1), 
    PARTITION type2 VALUES (2), 
    PARTITION type3 VALUES (3), 
    PARTITION type4 VALUES (4) 
); 

或不分區都

CREATE TABLE prova_log_old (
     id_dispositive  NUMBER, 
     TYPE     NUMBER, 
     date_verification DATE, 
     status    NUMBER 
); 
+0

嘿隊友感謝您的答案..但我認爲這是昂貴的..我的意思是每個分區至少有10M行......這將需要很長時間才能正確執行? –

+0

看看我更新的答案。 –

+0

現在我得到了一個'ORA-14128外鍵約束不匹配在alter table exchange分區中' –

1

你做錯了。你所有的分區表交換分區不能與它劃分,只是看多了一個你的代碼

EXECUTE IMMEDIATE 'alter table PROVA_LOG EXCHANGE PARTITION ' 
          || item.partition_name 
          || ' with table PROVA_LOG_OLD'; 

在交換分區,你應該做如下

  1. 不具有相同的分區上創建空表的情況下,結構像PROVA_LOG,但沒有分區。

  2. 交換分區在生產表NEW_TABLE

  3. 交換分區HIST表NEW_TABLE

+0

對不起......我不明白。我必須創建一個沒有分區的空表,並用它做什麼? –

+0

@MarllonNasser Tom kyte已經解決了這個問題。請參閱https://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:1238800184155,%7Bpartitions%7D。 (來自2006年4月2日的消息)我應該首先添加此鏈接。 –