what feature to use in oracle standard edition like that of partitioning in oracle enterprise edition

前端 未结 3 752
[愿得一人]
[愿得一人] 2021-01-23 21:31

I only have access to oracle standard edition, which feature of oracle standard edition provides the functionality like that of partitioning is there any concept of logically me

3条回答
  •  不思量自难忘°
    2021-01-23 22:03

    Handmade Partitioning - a working example for Oracle XE/SE

    1. Choose a partitioning key, for example: DOC_DATE - partition for every year.
    2. Create a row type and tables for partitions.

      create type DOCS_ROW_TYPE as object (
          doc_id   NUMBER,
          doc_name VARCHAR2(100),
          doc_date DATE
      );
      
      -- Create partition YOLD table (data from OLD years)
      create table DOCS_YOLD OF DOCS_ROW_TYPE;
      alter table DOCS_YOLD modify doc_id not null;
      alter table DOCS_YOLD modify doc_date not null;
      -- Create primary key
      alter table DOCS_YOLD add constraint DOCS_YOLD_PK primary key (DOC_ID) using index;
      -- Create indexes 
      create index DOCS_YOLD_DATE_IDX on DOCS_YOLD (DOC_DATE);
      create index DOCS_YOLD_NAME_UPCASE_IDX on DOCS_YOLD (UPPER(DOC_NAME));
      
      -- Create partition Y2014 table (data from 2014 years)
      create table DOCS_Y2014 OF DOCS_ROW_TYPE;
      alter table DOCS_Y2014 modify doc_id not null;
      alter table DOCS_Y2014 modify doc_date not null;
      -- Create primary key
      alter table DOCS_Y2014 add constraint DOCS_Y2014_PK primary key (DOC_ID) using index;
      -- Create indexes 
      create index DOCS_Y2014_DATE_IDX on DOCS_Y2014 (DOC_DATE);
      create index DOCS_Y2014_NAME_UPCASE_IDX on DOCS_Y2014 (UPPER(DOC_NAME));
      
      -- Create partition Y2015 table (data from 2015 years)
      create table DOCS_Y2015 OF DOCS_ROW_TYPE;
      alter table DOCS_Y2015 modify doc_id not null;
      alter table DOCS_Y2015 modify doc_date not null;
      -- Create primary key
      alter table DOCS_Y2015 add constraint DOCS_Y2015_PK primary key (DOC_ID) using index;
      -- Create indexes 
      create index DOCS_Y2015_DATE_IDX on DOCS_Y2015 (DOC_DATE);
      create index DOCS_Y2015_NAME_UPCASE_IDX on DOCS_Y2015 (UPPER(DOC_NAME));
      
      -- Create partition Y2016 table (data from 2016 years)
      create table DOCS_Y2016 OF DOCS_ROW_TYPE;
      alter table DOCS_Y2016 modify doc_id not null;
      alter table DOCS_Y2016 modify doc_date not null;
      -- Create primary key
      alter table DOCS_Y2016 add constraint DOCS_Y2016_PK primary key (DOC_ID) using index;
      -- Create indexes 
      create index DOCS_Y2016_DATE_IDX on DOCS_Y2016 (DOC_DATE);
      create index DOCS_Y2016_NAME_UPCASE_IDX on DOCS_Y2016 (UPPER(DOC_NAME));
      
      -- Create partition YNEW table (data from NEW years)
      create table DOCS_YNEW OF DOCS_ROW_TYPE;
      alter table DOCS_YNEW modify doc_id not null;
      alter table DOCS_YNEW modify doc_date not null;
      -- Create primary key
      alter table DOCS_YNEW add constraint DOCS_YNEW_PK primary key (DOC_ID) using index;
      -- Create indexes 
      create index DOCS_YNEW_DATE_IDX on DOCS_YNEW (DOC_DATE);
      create index DOCS_YNEW_NAME_UPCASE_IDX on DOCS_YNEW (UPPER(DOC_NAME));
      
    3. You have to define correct constraints then Oracle will use filters in query execution plan!

      alter table DOCS_YOLD
        add constraint DOCS_YOLD_KEY_CHECK
        check (DOC_DATE < to_date('2014-01-01','yyyy-mm-dd'));
      
      alter table DOCS_Y2014
        add constraint DOCS_Y2014_KEY_CHECK
        check (DOC_DATE >= to_date('2014-01-01','yyyy-mm-dd') and DOC_DATE < to_date('2015-01-01','yyyy-mm-dd'));
      
      alter table DOCS_Y2015
        add constraint DOCS_Y2015_KEY_CHECK
        check (DOC_DATE >= to_date('2015-01-01','yyyy-mm-dd') and DOC_DATE < to_date('2016-01-01','yyyy-mm-dd'));
      
      alter table DOCS_Y2016
        add constraint DOCS_Y2016_KEY_CHECK
        check (DOC_DATE >= to_date('2016-01-01','yyyy-mm-dd') and DOC_DATE < to_date('2017-01-01','yyyy-mm-dd'));
      
      alter table DOCS_YNEW
        add constraint DOCS_YNEW_KEY_CHECK
        check (DOC_DATE >= to_date('2017-01-01','yyyy-mm-dd'));
      
    4. Create a view DOCS_PARTITIONS as all partitions union

      create or replace view docs_partitions as
      select * from docs_yold
      union all
      select * from docs_y2014
      union all
      select * from docs_y2015
      union all
      select * from docs_y2016
      union all
      select * from docs_ynew
      
    5. Create a PK sequence

      create sequence DOCS_MASTER_PK_SEQ
      minvalue 1
      maxvalue 1000000000
      start with 1
      increment by 1
      cache 10;
      
    6. Create a "INSTEAD OF" trigger on the DOCS_PARTITIONS view to redistributing data

      create or replace trigger docs_partitions_insert
        INSTEAD OF insert on docs_partitions  
        for each row
      declare
        v_year number(4);
        v_doc_id docs_partitions.DOC_ID%type;
      begin
        v_doc_id := docs_master_pk_seq.nextval;
        v_year := to_number(to_char(:new.doc_date,'yyyy'));
        if (v_year < 2014) then
          insert into docs_yold (doc_id, doc_name, doc_date)
          values (v_doc_id, :new.doc_name, :new.doc_date);
        elsif (v_year = 2014) then
          insert into docs_y2014 (doc_id, doc_name, doc_date)
          values (v_doc_id, :new.doc_name, :new.doc_date);
        elsif (v_year = 2015) then
          insert into docs_y2015 (doc_id, doc_name, doc_date)
          values (v_doc_id, :new.doc_name, :new.doc_date);
        elsif (v_year = 2016) then
          insert into docs_y2016 (doc_id, doc_name, doc_date)
          values (v_doc_id, :new.doc_name, :new.doc_date);
        else
          insert into docs_ynew (doc_id, doc_name, doc_date)
          values (v_doc_id, :new.doc_name, :new.doc_date);
        end if;  
      end docs_partitions_insert;
      
    7. You can also distributing data via a master table - DOCS_MASTER

      -- Create partition MASTER table (all data)
      create table DOCS_MASTER OF DOCS_ROW_TYPE;
      alter table DOCS_MASTER modify doc_id not null;
      alter table DOCS_MASTER modify doc_date not null;
      -- Create primary key
      alter table DOCS_MASTER add constraint DOCS_MASTER_PK primary key (DOC_ID) using index;
      -- Create indexes 
      create index DOCS_MASTER_DATE_IDX on DOCS_MASTER (DOC_DATE);
      create index DOCS_MASTER_NAME_UPCASE_IDX on DOCS_MASTER (UPPER(DOC_NAME));
      
    8. Create a trigger on the DOCS_MASTER table to redistributing data

      create or replace trigger docs_master_insert
        before insert on docs_master  
        for each row
      declare
        v_year number(4);
      begin
        :new.doc_id := docs_master_pk_seq.nextval;
        v_year := to_number(to_char(:new.doc_date,'yyyy'));
        if (v_year < 2014) then
          insert into docs_yold (doc_id, doc_name, doc_date)
          values (:new.doc_id, :new.doc_name, :new.doc_date);
        elsif (v_year = 2014) then
          insert into docs_y2014 (doc_id, doc_name, doc_date)
          values (:new.doc_id, :new.doc_name, :new.doc_date);
        elsif (v_year = 2015) then
          insert into docs_y2015 (doc_id, doc_name, doc_date)
          values (:new.doc_id, :new.doc_name, :new.doc_date);
        elsif (v_year = 2016) then
          insert into docs_y2016 (doc_id, doc_name, doc_date)
          values (:new.doc_id, :new.doc_name, :new.doc_date);
        else
          insert into docs_ynew (doc_id, doc_name, doc_date)
          values (:new.doc_id, :new.doc_name, :new.doc_date);
        end if;  
      end docs_master_insert;
      
    9. Generate data for test

      declare
        v_i integer;
        v_count integer := 1000000;
      begin
        -- insert docs through the master table
        for v_i in 1..v_count
        loop
              insert into docs_master (doc_name, doc_date)
              values (
                     'DOC-M-'||v_i, 
                     to_date(trunc(DBMS_RANDOM.VALUE(to_char(TO_DATE('2000-01-01','yyyy-mm-dd'),'J'),to_char(TO_DATE('2100-01-01','yyyy-mm-dd'),'J'))),'J')
              );
              if mod(v_i,10000)=0 then
                commit;
                dbms_output.put_line('rows M inserted: '||v_i||', '||(round(100*v_i/v_count))||'%');
              end if;
        end loop;
        commit;
        -- insert docs through the partitions view
        /*
        for v_i in 1..2
        loop
              insert into docs_partitions (doc_name, doc_date)
              values (
                     'DOC-P-'||v_i, 
                     to_date(trunc(DBMS_RANDOM.VALUE(to_char(TO_DATE('2000-01-01','yyyy-mm-dd'),'J'),to_char(TO_DATE('2100-01-01','yyyy-mm-dd'),'J'))),'J')
              );
              if mod(v_i,1000)=0 then
                commit;
                dbms_output.put_line('rows P inserted: '||v_i);
              end if;
        end loop;
        commit;
        */
      end;
      
    10. Select data from the DOCS_PARTITIONS view

      select dp.* 
      from DOCS_PARTITIONS dp 
      where 
        dp.DOC_DATE between to_date('2014-02','yyyy-mm') and to_date('2014-03','yyyy-mm')
      
      -- SQL execution plan with filters!!!
      SELECT STATEMENT, GOAL = ALL_ROWS           0   1   78
       VIEW   PART_TEST   DOCS_PARTITIONS 0   1   78
        UNION-ALL                 
         FILTER                   
          TABLE ACCESS BY INDEX ROWID PART_TEST   DOCS_YOLD   3   11  814
           INDEX RANGE SCAN   PART_TEST   DOCS_YOLD_DATE_IDX  3   833 
         TABLE ACCESS BY INDEX ROWID  PART_TEST   DOCS_Y2014  1   750 55500
          INDEX RANGE SCAN    PART_TEST   DOCS_Y2014_DATE_IDX 1   45  
         FILTER                   
          TABLE ACCESS BY INDEX ROWID PART_TEST   DOCS_Y2015  1   1   74
           INDEX RANGE SCAN   PART_TEST   DOCS_Y2015_DATE_IDX 1   44  
         FILTER                   
          TABLE ACCESS BY INDEX ROWID PART_TEST   DOCS_Y2016  1   1   74
           INDEX RANGE SCAN   PART_TEST   DOCS_Y2016_DATE_IDX 1   47  
         FILTER                   
          TABLE ACCESS BY INDEX ROWID PART_TEST   DOCS_YNEW   14  61  4514
           INDEX RANGE SCAN   PART_TEST   DOCS_YNEW_DATE_IDX  14  5565    
      

提交回复
热议问题