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
Table partitioning is a feature of Oracle Enterprise Edition. To my knowledge, there is no such functionality in Standard Edition.
Would be happy to be proved wrong, mind you...
Only thing that comes to mind is to have a real table for each 'partition', and then a view than unions them all together. But you'd have to rebuild the view every time you added or removed a 'partition', and there might be performance issues, as well as potential complication with anything except selects - which you could get around with procedures to do insert/update/delete on the relevant underlying table. Probably wouldn't be very easy to create or maintain, or very robust. There's a reason Oracle charge extra for this.
Handmade Partitioning
- a working example for Oracle XE/SECreate 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));
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'));
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
Create a PK sequence
create sequence DOCS_MASTER_PK_SEQ
minvalue 1
maxvalue 1000000000
start with 1
increment by 1
cache 10;
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;
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));
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;
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;
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