2017-08-01 3 views
0

私は日と時間(サブパーティション)に基づいてパーティション化されたテーブルを持っています。テーブルパーティションクリーンアップ

いつでも10時間のデータを保持し、以前のパーティションを削除したいと考えています。日付が変わるとこれをどう管理するのですか?たとえば、8月2日の最初の時間に1つのパーティションを保持し、8月1日に9つのパーティションを保持するには?

いずれの入力も大きな助けになります。この手順を最初に実行するとき

表の定義は、

CREATE TABLE "MY_SCHEMA"."MY_TABLE" 
    ( "TARGET_TIME" TIMESTAMP (6), 
    "TARGET_DATE" DATE, 
    "TARGET_HOUR" NUMBER GENERATED ALWAYS AS (EXTRACT(HOUR FROM "TARGET_TIME")) VIRTUAL , 
    "MY_ID" NUMBER(10,0), 
    "MY_INDEX" NUMBER(10,0), 
    "MY_STATUS" NUMBER(10,0) 
    ) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOLOGGING 
    STORAGE(
    BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) 
    TABLESPACE "MYTABLESPACE" 
    PARTITION BY RANGE ("TARGET_DATE") INTERVAL (INTERVAL '1' DAY) 
    SUBPARTITION BY LIST ("TARGET_HOUR") 
    SUBPARTITION TEMPLATE ( 
    SUBPARTITION "HOUR00" VALUES (0), 
    SUBPARTITION "HOUR01" VALUES (1), 
    SUBPARTITION "HOUR02" VALUES (2), 
    SUBPARTITION "HOUR03" VALUES (3), 
    SUBPARTITION "HOUR04" VALUES (4), 
    SUBPARTITION "HOUR05" VALUES (5), 
    SUBPARTITION "HOUR06" VALUES (6), 
    SUBPARTITION "HOUR07" VALUES (7), 
    SUBPARTITION "HOUR08" VALUES (8), 
    SUBPARTITION "HOUR09" VALUES (9), 
    SUBPARTITION "HOUR10" VALUES (10), 
    SUBPARTITION "HOUR11" VALUES (11), 
    SUBPARTITION "HOUR12" VALUES (12), 
    SUBPARTITION "HOUR13" VALUES (13), 
    SUBPARTITION "HOUR14" VALUES (14), 
    SUBPARTITION "HOUR15" VALUES (15), 
    SUBPARTITION "HOUR16" VALUES (16), 
    SUBPARTITION "HOUR17" VALUES (17), 
    SUBPARTITION "HOUR18" VALUES (18), 
    SUBPARTITION "HOUR19" VALUES (19), 
    SUBPARTITION "HOUR20" VALUES (20), 
    SUBPARTITION "HOUR21" VALUES (21), 
    SUBPARTITION "HOUR22" VALUES (22), 
    SUBPARTITION "HOUR23" VALUES (23)) 
(PARTITION "DEFAULT_20170101" VALUES LESS THAN (TO_DATE(' 2017-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) 
PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 
    STORAGE(
    BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) 
    TABLESPACE "MYTABLESPACE") ; 

よろしく

+0

は、テーブル定義を提供してください、私はあなたに答えを提供することができます。 –

+0

元の質問にテーブル定義を追加しました。 –

+0

「今から10時間以上経過したものを落とす」という意味ですか? –

答えて

0
PROCEDURE MaintainPartitions(givenTime IN TIMESTAMP DEFAULT LOCALTIMESTAMP) IS 

    CURSOR SubParts IS 
    SELECT TABLE_NAME, PARTITION_NAME, SUBPARTITION_NAME, 
     part.HIGH_VALUE AS PART_HIGH_VALUE, 
     subpart.HIGH_VALUE as SUB_HIGH_VALUE 
    FROM ALL_TAB_PARTITIONS part 
     JOIN ALL_TAB_SUBPARTITIONS subpart USING (OWNER, TABLE_NAME, PARTITION_NAME) 
    WHERE OWNER = 'MY_SCHEMA' 
     AND TABLE_NAME = 'MY_TABLE' 
    ORDER BY PARTITION_POSITION, SUBPARTITION_POSITION; 

    CURSOR TabParts IS 
    SELECT TABLE_NAME, PARTITION_NAME 
    FROM ALL_TAB_PARTITIONS part 
    WHERE OWNER = 'MY_SCHEMA' 
     AND TABLE_NAME = 'MY_TABLE' 
    ORDER BY PARTITION_POSITION; 

    cur SYS_REFCURSOR; 
    r INTEGER; 
    highValue TIMESTAMP; 

BEGIN 
    -- Truncate old subpartitions 
    FOR aSubPart IN SubParts LOOP 
     EXECUTE IMMEDIATE 'BEGIN :ret := '||aSubPart.PART_HIGH_VALUE||' + INTERVAL '''||aSubPart.SUB_HIGH_VALUE||''' HOUR; END;' 
      USING OUT highValue; 
     IF highValue < givenTime - INTERVAL '10' HOUR THEN 
      EXECUTE IMMEDIATE 'ALTER TABLE '||aSubPart.TABLE_NAME||' TRUNCATE SUBPARTITION '||aSubPart.SUBPARTITION_NAME||' UPDATE INDEXES'; 
     END IF; 
    END LOOP; 

    -- Drop empty partitions 
    FOR aPart IN TabParts LOOP 
     OPEN cur FOR 'SELECT ROWNUM FROM '||aPart.TABLE_NAME||' PARTITION ('||aPart.PARTITION_NAME||') WHERE ROWNUM <= 1'; 
     FETCH cur INTO r; 
     IF cur%NOTFOUND THEN 
      EXECUTE IMMEDIATE 'ALTER TABLE '||aPart.TABLE_NAME||' DROP PARTITION '||aPart.PARTITION_NAME||' UPDATE INDEXES'; 
     END IF; 
     CLOSE cur;  
    END LOOP; 
END; 

であるあなたは、この場合ORA-14758: Last partition in the range section cannot be dropped を得ることができ、ところで

alter table MY_TABLE set interval(); 
alter table MY_TABLE DROP PARTITION ...; 
alter table MY_TABLE set INTERVAL(INTERVAL '1' DAY); 

を行いますなぜ時間単位でサブパーティションを作っていますか?私はそれに理由がないと思う。 TARGET_TIMETARGET_DATE、およびTARGET_HOURを誤用する恐れがあります。注:すべてDATEまたはTIMESTAMPの値には、日付がおよびのタイムコンポーネントが含まれています。シンプルなパーティションを使用してください。技術的には同じですが、メンテナンスは簡単です。このようにテーブルを定義します。

CREATE TABLE MY_SCHEMA.MY_TABLE 
    ( TARGET_TIME TIMESTAMP (6), 
    MY_ID NUMBER(10,0), 
    MY_INDEX NUMBER(10,0), 
    MY_STATUS NUMBER(10,0) 
    ) 
    TABLESPACE MYTABLESPACE 
    PARTITION BY RANGE (TARGET_TIME) INTERVAL (INTERVAL '1' HOUR) 
(PARTITION "DEFAULT_20170101" VALUES LESS THAN (TIMESTAMP '2017-01-01 00:00:00'); 

を、このような場合の手順では、上からはるかに簡単になります:

PROCEDURE MaintainPartitions(givenTime IN TIMESTAMP DEFAULT LOCALTIMESTAMP) IS 

    CURSOR TabParts IS 
    SELECT TABLE_NAME, PARTITION_NAME, HIGH_VALUE 
    FROM ALL_TAB_PARTITIONS part 
    WHERE OWNER = 'MY_SCHEMA' 
     AND TABLE_NAME = 'MY_TABLE' 
    ORDER BY PARTITION_POSITION; 

    highValue TIMESTAMP; 

BEGIN 
    FOR aPart IN TabParts LOOP 
     EXECUTE IMMEDIATE 'BEGIN :ret := '||aPart.HIGH_VALUE||'; END;' 
      USING OUT highValue; 
     IF highValue < givenTime - INTERVAL '10' HOUR THEN 
      EXECUTE IMMEDIATE 'ALTER TABLE '||aPart.TABLE_NAME||' DROP PARTITION '||aPart.PARTITION_NAME||' UPDATE INDEXES'; 
     END IF; 
    END LOOP; 
END;