какую функцию использовать в стандартной версии oracle, например, функцию разделения в корпоративной версии oracle - PullRequest
1 голос
/ 27 апреля 2011

У меня есть доступ только к стандартной версии oracle, функция которой стандартной версии oracle обеспечивает такую ​​же функциональность, как и функция разбиения, есть ли какая-либо концепция логического объединения таблиц, подобная той, что есть в MYSQL.

Ответы [ 3 ]

5 голосов
/ 27 апреля 2011

Единственное, что приходит на ум, - это иметь реальную таблицу для каждого «раздела», а затем посмотреть, что объединяет их всех вместе. Но вам придется перестраивать представление каждый раз, когда вы добавляете или удаляете «раздел», и могут возникнуть проблемы с производительностью, а также возможное осложнение с чем-либо, кроме выбора, - что вы можете обойти с помощью процедур, выполняющих вставку / обновление / удалить на соответствующей базовой таблице. Вероятно, было бы не очень легко создавать или поддерживать, или быть очень надежным. Есть причина, по которой Oracle взимает за это дополнительную плату.

3 голосов
/ 18 августа 2015

Handmade Partitioning - рабочий пример для Oracle XE / SE

  1. Выберите ключ разделения, например: DOC_DATE - раздел для каждого года.
  2. СоздатьТип строки и таблицы для разделов.

    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. Вы должны определить правильные ограничения, тогда Oracle будет использовать фильтры в плане выполнения запроса!

    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. Создать представление DOCS_PARTITIONS как объединение всех разделов

    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. Создать последовательность PK

    create sequence DOCS_MASTER_PK_SEQ
    minvalue 1
    maxvalue 1000000000
    start with 1
    increment by 1
    cache 10;
    
  6. Создать "INSTEAD OF"триггер в представлении DOCS_PARTITIONS для перераспределения данных

    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. Вы также можете распространять данные через основную таблицу - 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. Создайте триггер в таблице DOCS_MASTER для перераспределения данных

    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. Создание данных для теста

    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. Выбор данных из представления DOCS_PARTITIONS

    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    
    
2 голосов
/ 27 апреля 2011

Разделение таблиц является функцией Oracle Enterprise Edition. Насколько мне известно, в Standard Edition такой функциональности нет.

Был бы рад, если бы ошибался, заметьте ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...