Sunday, June 14, 2009

PARTITION VE SUBPARTITION

Bu yazımda Partition’lar hakkın da bildiklerimi sizin ile paylaşmaya çalışacağım. Öncelik ile ön bilgi olması açısından Partition’lar ile ilgili olan Oracle View’leri size aktarayım. Bunlar DBA, ALL, & USERS olmak üzere 3 farklı aşamada olabilirler.

DBA

USER

ALL

dba_tab_cols

user_tab_cols

all_tab_cols

dba_ind_partitions

user_ind_partitions

all_ind_partitions

dba_ind_subpartitions

user_ind_subpartitions

all_ind_subpartitions

dba_lob_partitions

user_lob_partitions

all_lob_partitions

dba_lob_subpartitions

user_lob_subpartitions

all_lob_subpartitions

dba_subpartition_templates

user_subpartition_templates

all_subpartition_templates

dba_subpart_col_statistics

user_subpart_col_statistics

all_subpart_col_statistics

dba_subpart_histograms

user_subpart_histograms

all_subpart_histograms

dba_subpart_key_columns

user_subpart_key_columns

all_subpart_key_columns

dba_tab_partitions

user_tab_partitions

all_tab_partitions

dba_tab_subpartitions

user_tab_subpartitions

all_tab_subpartitions

Partitionlar ile ilgili Dictionary Object’lerin nerede olacağını gösterdikten sonra partition türlerini belirleyelim.

· Range partition (belirli bir limit aralığı)

· Hash partition (Hash fonksiyonunun ürettiği sonuca göre)

· List partition (belirli bir liste yapılarak o lste bazlı partition)

· Range-hash partition (partition range subpartition hash )

· Range-list partition (partition range subpartition list)

Partitionların Tableapaceler üzerindeki dağılıma bakacak olursak. Oracle bu konuda bize çok büyük esneklikler sağlıyor. İstediğimiz Partition’u istediğimiz Tablespace’ye taşımamıza yada istediğimiz yerde yaratmamıza izin veriyor. Aslında böylede olması gerekiyor çünkü partition ve subpartition yapısını kullanmak zorunda isek bunun sebebi tablolarımızın çok büyük boyutlu olması. Tabloyu tek bir tablespace’ye hapsetmek bu durumda mantıklı değil zaten. Tablespace’de yer kalmadığı zaman partition yada tabloları başka tablespace’lere taşıyarak geçici olarak da olsa yer sorununa bir çözüm getirebiliriz.

Partition’lu tablo yaratırken örnek tabloları ALL_OBJECTS ile dolduracağım. Nede olsa herkesin database’sinde mevcut. :))

RANGE PARTITION

create table range_part

(OWNER VARCHAR2(30 BYTE) NOT NULL,

OBJECT_NAME VARCHAR2(30 BYTE) NOT NULL,

SUBOBJECT_NAME VARCHAR2(30 BYTE),

OBJECT_ID NUMBER NOT NULL,

DATA_OBJECT_ID NUMBER,

OBJECT_TYPE VARCHAR2(19 BYTE),

CREATED DATE NOT NULL,

LAST_DDL_TIME DATE NOT NULL,

TIMESTAMP VARCHAR2(19 BYTE),

STATUS VARCHAR2(7 BYTE),

TEMPORARY VARCHAR2(1 BYTE),

GENERATED VARCHAR2(1 BYTE),

SECONDARY VARCHAR2(1 BYTE)

)

partition by range (object_id)

(partition part_01 values less than (20000) tablespace users,

partition part_02 values less than (40000) tablespace example,

partition part_03 values less than (60000) tablespace users,

partition part_04 values less than (maxvalue) tablespace users)

Burada partition yaratırken hata almamak için bu yöntemi kullanıyorum. Böylece gelen her kayıt mutlaka bir partition ile eşleşecektir.

Tablomu aşağıda sorgu ile dolduruyorum.

insert into range_part select * from all_objects

Bakalım partitionlarda kaçar kayıt var. Ayrıca aşağıdaki sorgu örneğinde partition bazlı tablo erişimine örnek var.

select count(*) from range_part partition (part_01) --15432

select count(*) from range_part partition (part_02) --19977

select count(*) from range_part partition (part_03) --8356

select count(*) from range_part partition (part_04) --0

Tablodaki toplam kayıta bakarsak partitionların toplamını bize verecektir.

select count(*) from range_part –43765

HASH PARTITION

create table hash_part

(OWNER VARCHAR2(30 BYTE) NOT NULL,

OBJECT_NAME VARCHAR2(30 BYTE) NOT NULL,

SUBOBJECT_NAME VARCHAR2(30 BYTE),

OBJECT_ID NUMBER NOT NULL,

DATA_OBJECT_ID NUMBER,

OBJECT_TYPE VARCHAR2(19 BYTE),

CREATED DATE NOT NULL,

LAST_DDL_TIME DATE NOT NULL,

TIMESTAMP VARCHAR2(19 BYTE),

STATUS VARCHAR2(7 BYTE),

TEMPORARY VARCHAR2(1 BYTE),

GENERATED VARCHAR2(1 BYTE),

SECONDARY VARCHAR2(1 BYTE)

)

partition by hash (object_id)

partitions 4

store in (users,users,example,users);

yaratmış olduğumuz bu partitionların isimlerini öğrenmek için

select * from user_tab_partitions

sorgusunun sonucuna bakmak gerekir. Bu sorgu sonucunda user’a ait partition’ların hepsini bulabiliriz. Hatta hangi tabloya ait olduklarını ve hangi tablespace’de yer aldıklarını görebiliriz.

Sorgumuzu biraz güzelleştirelim

select * from user_tab_partitions where lower(table_name)='hash_part'

LIST PARTITION

create table list_part

(OWNER VARCHAR2(30 BYTE) NOT NULL,

OBJECT_NAME VARCHAR2(30 BYTE) NOT NULL,

SUBOBJECT_NAME VARCHAR2(30 BYTE),

OBJECT_ID NUMBER NOT NULL,

DATA_OBJECT_ID NUMBER,

OBJECT_TYPE VARCHAR2(19 BYTE),

CREATED DATE NOT NULL,

LAST_DDL_TIME DATE NOT NULL,

TIMESTAMP VARCHAR2(19 BYTE),

STATUS VARCHAR2(7 BYTE),

TEMPORARY VARCHAR2(1 BYTE),

GENERATED VARCHAR2(1 BYTE),

SECONDARY VARCHAR2(1 BYTE)

)

partition by list (object_type)

(partition list_01 values ('CONSUMER GROUP','TABLE SUBPARTITION','SEQUENCE','SCHEDULE','JAVA DATA','TABLE PARTITION'),

partition list_02 values ('PROCEDURE','OPERATOR','WINDOW','PACKAGE','PACKAGE BODY','LIBRARY'),

partition list_03 values ('PROGRAM','TYPE BODY','JAVA RESOURCE','XML SCHEMA','TRIGGER','JOB CLASS'),

partition list_04 values ('TABLE','SYNONYM','VIEW','FUNCTION','WINDOW GROUP','INDEXTYPE'),

partition list_05 values ('INDEX','TYPE','EVALUATION CONTEXT','JAVA CLASS'));

insert into list_part select * from all_objects

select distinct object_type from all_objects

Listede olması gerekenleri ekledim ama oracle bir şeye kızdı neden acaba??

ORA-14400: inserted partition key does not map to any partition

ORA-14400: eklenen bölüm anahtarI hiçbir bölümle eşleşmiyor

Aslinda bu hatayı almaması gerekir bütün olasılıkları tek tek denedim oluyor ama tabloyu bir seferde almadı.

Düzeltme : aynı işlemi scriptte herhangibi bir değişiklik yapmadan denedim çalıştı. Benim TOAD kafayı yedi herhalde.

insert into list_part select * from all_objects where object_type='CONSUMER

GROUP'

Madem * ile yemiyorsun bende tek tek veririm sana buda çalışmasın göreyim seni :))

insert into list_part select * from all_objects

where object_type in ('CONSUMER GROUP','TABLE SUBPARTITION','SEQUENCE','SCHEDULE','JAVA DATA','TABLE PARTITION','PROCEDURE','OPERATOR','WINDOW','PACKAGE','PACKAGE BODY','LIBRARY','PROGRAM','TYPE BODY','JAVA RESOURCE','XML SCHEMA','TRIGGER','JOB CLASS','TABLE','SYNONYM','VIEW','FUNCTION','WINDOW GROUP','INDEXTYPE','INDEX','TYPE','EVALUATION CONTEXT','JAVA CLASS')

RANGE HASH PARTITION

Bu yapıda ise partitionlarımız range subpartitionlarımız ise hash şeklinde olacaktır.

create table range_hash_part

(OWNER VARCHAR2(30 BYTE) NOT NULL,

OBJECT_NAME VARCHAR2(30 BYTE) NOT NULL,

SUBOBJECT_NAME VARCHAR2(30 BYTE),

OBJECT_ID NUMBER NOT NULL,

DATA_OBJECT_ID NUMBER,

OBJECT_TYPE VARCHAR2(19 BYTE),

CREATED DATE NOT NULL,

LAST_DDL_TIME DATE NOT NULL,

TIMESTAMP VARCHAR2(19 BYTE),

STATUS VARCHAR2(7 BYTE),

TEMPORARY VARCHAR2(1 BYTE),

GENERATED VARCHAR2(1 BYTE),

SECONDARY VARCHAR2(1 BYTE)

)

partition by range (object_id)

subpartition by hash (object_name)

--tek tek her partition için yazmaktan ise aşağıdaki gibi bir template oluşturarak

--hepsinde yaratılmasını sağlarız

subpartition template(

subpartition sp1 tablespace users,

subpartition sp2 tablespace users,

subpartition sp3 tablespace users,

subpartition sp4 tablespace example)

(partition part_001 values less than (20000),

partition part_002 values less than (40000),

partition part_003 values less than (60000),

partition part_004 values less than (maxvalue));

insert into range_hash_part select * from all_objects

--Oluşturduğumuz subpartition’ları aşağıdaki sorgu ile görebiliriz.

select * from user_tab_SUBpartitions where table_name='RANGE_HASH_PART'

RANGE LIST PARTITION

Buradaki yapıda da partition’ları range şeklinde oluşturuyorum. Subpartition’lar ise list şeklinde.

create table range_list_part

(OWNER VARCHAR2(30 BYTE) NOT NULL,

OBJECT_NAME VARCHAR2(30 BYTE) NOT NULL,

SUBOBJECT_NAME VARCHAR2(30 BYTE),

OBJECT_ID NUMBER NOT NULL,

DATA_OBJECT_ID NUMBER,

OBJECT_TYPE VARCHAR2(19 BYTE),

CREATED DATE NOT NULL,

LAST_DDL_TIME DATE NOT NULL,

TIMESTAMP VARCHAR2(19 BYTE),

STATUS VARCHAR2(7 BYTE),

TEMPORARY VARCHAR2(1 BYTE),

GENERATED VARCHAR2(1 BYTE),

SECONDARY VARCHAR2(1 BYTE)

)

partition by range (object_id)

subpartition by list (object_type)

(partition part_01 values less than (20000)

(

subpartition sub01_part_01 values ('TABLE','VIEW','INDEX'),

subpartition sub01_part_02 values ('SEQUENCE','PROCEDURE','PACKAGE')

),

partition part_02 values less than (40000)

(

subpartition sub02_part_01 values ('TABLE','VIEW','INDEX'),

subpartition sub02_part_02 values ('SEQUENCE','PROCEDURE','PACKAGE')

),

partition part_03 values less than (maxvalue)

(

subpartition sub03_part_01 values ('TABLE','VIEW','INDEX'),

subpartition sub03_part_02 values ('SEQUENCE','PROCEDURE','PACKAGE')

)

);

Bu tablo’yu doldurmak için aşağıdaki sorguyu kullanabiliriz. Gönül isterdi bütün object_type’ları almak ama yazma işi biraz ameliliğe döneceği için işin kolayına kaçtım :)).

insert into range_list_part select * from all_objects

where object_type in ('SEQUENCE','PROCEDURE','PACKAGE','TABLE','VIEW','INDEX')

No comments: