Interval Partitioning …

Partitioning ile ilgili olarak tablo ve indexlerin nasıl partitionlanması gerektiğinden ( http://www.kamilturkyilmaz.com/2012/04/28/oracle-partitioning/ ) bir önceki yazımda bahsetmiştim. Şimdi partitioning kavramının biraz daha detayından ve 11g yeni gelen bir başka özelliğinden bahsedeceğiz. İnterval partitioning, çok yalın bir ifadeyle tabloyu create ederken oluşturmuş olduğunuz partition aralıklarının dışında bir kayıt geldiğinde sizin öncesinde belirlemiş olduğunuz kritere göre oracle’ ın otomatik olarak sizin adınıza yeni bir partition açmasıdır şeklinde özetleyebiliriz. Peki bundan önceki versiyonlarda nasıldı bu durum aslında sürekli bir takip gerektiriyordu. Ve tablonun hata almaması için yeni partitionları öncesinde create etmeniz gerekiyordu. Bu özellik dba’ lere ciddi bir kolaylık getirdi. Düşünsenize production ortamınızda çok kritik bir tablonuz var ve yıllık dönemler bazında partitionlı, yılbaşı gecesi yeni yıla ait gelen tüm kayıtlar adreslendiği bir partition olmadığı için sürekli olarak hata alıyor. Bir sonraki gün şirkete geldiğiniz de alınan bu hataların neden kaynaklandığını açıklamak zorunda kalıyor olabilirsiniz.

Bu arada ne bir önceki yazımda nede bu yazımda henüz partitioning nesnelerimi manage ederken kullanacağımız scriptlerimizden hiç bahsetmedim. Çünkü bu konuyu ayrıca ele alıp bu konuyla ilgili özel bir yazmayı planlıyorum. Dolayısıyla detay scriptleri burada görmemenizin nedeni budur.

Yukarıda belirttiğimiz bu tarz problemlerin önüne geçmek için tabloları partition yaparken interval opsiyonunu da artık kullanabilirsiniz. Öncelikle partition table create ederken interval opsiyonunun nasıl kullanıldığına bakalım. Syntaxı nasıl ve interval aralığı ne kadar opsiyonel bunlar üzerinde duralım.

Interval partitioning kullanmasaydık ve aylık bazda tablomuzu partitionlamaya çalışsaydık, tablomuz aşağıdaki şekilde olacaktı. Nisan ayı bitmek üzere ve Mayıs partitionınıda henüz eklemediğimizi sonrasında da atladığımızı varsayalım ve ne tarz hatalar alacağız başımıza neler gelecek bir bakalım.

CREATE TABLE interval_test_table (
no NUMBER,
name VARCHAR2(30),
aciklama VARCHAR2(60),
insert_date DATE
) partition by range (insert_date)
(partition part_date1 values less than (TO_DATE(’01/01/2012′, ‘DD/MM/YYYY’)) tablespace tbs1,
partition part_date2 values less than (TO_DATE(’01/02/2012′, ‘DD/MM/YYYY’)) tablespace tbs2,
partition part_date3 values less than (TO_DATE(’01/03/2012′, ‘DD/MM/YYYY’)) tablespace tbs3,
partition part_date4 values less than (TO_DATE(’01/04/2012′, ‘DD/MM/YYYY’)) tablespace tbs4,
partition part_date5 values less than (TO_DATE(’01/05/2012′, ‘DD/MM/YYYY’)) tablespace tbs5)
Table created.

İnsertlerimizde hata almamak için sessionımın nls_date_format’ ını set ediyorum;

alter session set nls_date_format = ‘DD/MM/YYYY’ ;

sample dataları insert ediyorum;

SQL> insert into interval_test_table values (1,’deneme’,’aciklama kolonu icin’, ’10/01/2012′)
1 row created.

SQL> insert into interval_test_table values (1,’deneme’,’aciklama kolonu icin’, ’15/02/2012′)
1 row created.

SQL> insert into interval_test_table values (1,’deneme’,’aciklama kolonu icin’, ’20/03/2012′)
1 row created.

SQL> insert into interval_test_table values (1,’deneme’,’aciklama kolonu icin’, ’25/04/2012′)
1 row created.

SQL> commit
Commit complete.

Ilk 4 ayın verisinde hiçbir problem yaşanmadı, mayıs ayına ait bir kayıt insert etmeye çalışalım ;

SQL> insert into interval_test_table values (1,’deneme’,’aciklama kolonu icin’, ’01/05/2012′)
insert into interval_test_table values (1,’deneme’,’aciklama kolonu icin’, ’01/05/2012′)
Error at line 1
ORA-14400: inserted partition key does not map to any partition

Hatamızı aldık. Neden hata aldığımızdan bahsetmiştik, son kaydın tablo içerisinde nereye, hangi partition içerisine insert edileceği tariflenmediği için insert işlemine devam edilemiyor. Işte 10g ve öncesindeki partitioning lerdeki en büyük zorluk bu idi. Sırf bu takip işine girmemek için partitioning kullanmayanlar olduğunu biliyorum. 11g ile bu değişikliğin nasıl olduğuna bakalım ve aynı işlemleri interval opsiyonunu kullanarak test edelim ;

Tablomuzu aşağıdaki create ediyoruz;

CREATE TABLE interval_test_table2 (
no NUMBER,
name VARCHAR2(30),
aciklama VARCHAR2(60),
insert_date DATE
) partition by range (insert_date)
INTERVAL (NUMTOYMINTERVAL(1,’MONTH’))
(partition part_date1 values less than (TO_DATE(’01/01/2012′, ‘DD/MM/YYYY’)) tablespace tbs1,
partition part_date2 values less than (TO_DATE(’01/02/2012′, ‘DD/MM/YYYY’)) tablespace tbs2,
partition part_date3 values less than (TO_DATE(’01/03/2012′, ‘DD/MM/YYYY’)) tablespace tbs3,
partition part_date4 values less than (TO_DATE(’01/04/2012′, ‘DD/MM/YYYY’)) tablespace tbs4,
partition part_date5 values less than (TO_DATE(’01/05/2012′, ‘DD/MM/YYYY’)) tablespace tbs5 )
Table created.

İnsertleri tekrar deneyelim, bu sefer mayıs ayı datasında hata almamız gerekiyor ;

SQL> alter session set nls_date_format = ‘DD/MM/YYYY’
Session altered.

SQL> insert into interval_test_table2 values (1,’deneme’,’aciklama kolonu icin’, ’10/01/2012′)
1 row created.

SQL> insert into interval_test_table2 values (1,’deneme’,’aciklama kolonu icin’, ’15/02/2012′)
1 row created.

SQL> insert into interval_test_table2 values (1,’deneme’,’aciklama kolonu icin’, ’20/03/2012′)
1 row created.

SQL> insert into interval_test_table2 values (1,’deneme’,’aciklama kolonu icin’, ’25/04/2012′)
1 row created.

SQL> insert into interval_test_table2 values (1,’deneme’,’aciklama kolonu icin’, ’01/05/2012′)
1 row created.

SQL> commit
Commit complete.

Peki burada şu sorulabilir, mayıs ayına ait data nereye gitti, hangi partition içerisinde saklanıyor buna bakalım. Interval partitionlı tablomuz ile ilk olarak create ettiğimiz tablo isimlerimiz birbirinden farklı ve sonrasında karşılaştırma yapabilmek adına diğerinide drop etmemiştik. Bakalım ;

SQL> select table_name,partition_name
from user_tab_partitions
where table_name=’INTERVAL_TEST_TABLE2′

TABLE_NAME PARTITION_NAME
—————————— ——————————
INTERVAL_TEST_TABLE2 PART_DATE1
INTERVAL_TEST_TABLE2 PART_DATE2
INTERVAL_TEST_TABLE2 PART_DATE3
INTERVAL_TEST_TABLE2 PART_DATE4
INTERVAL_TEST_TABLE2 PART_DATE5

5 rows selected.

Ilk tablomuzda 5 tane partitionımız varken, yeni tablomuzda ;

SQL> select table_name,partition_name
from user_tab_partitions
where table_name=’INTERVAL_TEST_TABLE2′

TABLE_NAME PARTITION_NAME
—————————— ——————————
INTERVAL_TEST_TABLE2 PART_DATE1
INTERVAL_TEST_TABLE2 PART_DATE2
INTERVAL_TEST_TABLE2 PART_DATE3
INTERVAL_TEST_TABLE2 PART_DATE4
INTERVAL_TEST_TABLE2 PART_DATE5
INTERVAL_TEST_TABLE2 SYS_P41

6 rows selected.

6 tane partitionımız oldu. Datamızı select etmek istersek;

SQL> select * from interval_test_table2 partition (SYS_P41)

NO NAME ACIKLAMA INSERT_DATE
— —— ——————— ———–
1 deneme aciklama kolonu icin 01/05/2012
1 row selected.

Select etmiş olduk.

Aslında interval kullanımının, sadece partition key olarak tarih kriteri kullanıldığında kullanılmaz, farklı bir kullanım şekli ile ilgili bir örnek daha yapalım ;

create table INTERVAL_TEST_TABLE3
(ad varchar2(10),
soyad varchar2(30),
maas number(6))
partition by range(maas)
Interval (5000)
(
partition part1 values less than (5000),
partition part2 values less than (10000),
partition part3 values less than (15000),
partition part4 values less than (20000));
Table created.

Bu örneğimizde maaş aralığına göre bir gruplama görüyosunuz. Buarada 20000 tl maaşa kadar partitioning tariflenmiş durumda, ancak 21000 tl alan birisi işe başladığında 20000 – 25000 arasını kapsayan yeni bir partitioning’ in otomatik olarak create edilmesini bekliyoruz;

SQL> insert into INTERVAL_TEST_TABLE3 values (‘test’,’user’,21000)
1 row created.

Tablomuzun partitionlarına baktığımızda ;

SQL> select table_name,partition_name
from user_tab_partitions
where table_name=’INTERVAL_TEST_TABLE3′

TABLE_NAME PARTITION_NAME
—————————— ——————————
INTERVAL_TEST_TABLE3 PART1
INTERVAL_TEST_TABLE3 PART2
INTERVAL_TEST_TABLE3 PART3
INTERVAL_TEST_TABLE3 PART4
INTERVAL_TEST_TABLE3 SYS_P42

5 rows selected.

Yeni eklenen partitionımızı görebiliyoruz.

Partition table create ederken oracle tarafından oluşturulacak olan partitionların hangi tablespace’ ler altına oluşturması gerektiğini önceden belirtebiliyoruz. Bunun Store In komutunu tablonun create scriptinde aşağıdaki gibi kullanmamız yeterli olacaktır.

create table INTERVAL_TEST_TABLE4
(ad varchar2(10),
soyad varchar2(30),
maas number(6))
partition by range(maas)
Interval (5000) store in (tbs1,tbs2,tbs3,tbs4,tbs5)
(
partition part1 values less than (5000),
partition part2 values less than (10000),
partition part3 values less than (15000),
partition part4 values less than (20000));
Table created.

Şimdi composite partitiong yaparken aynı zamanda interval partitioning’ ide kullanmak istersek nasıl kullanabiliriz birer örnek scriptle bakalım ;

Range-list partitioning yaparken Interval Partitioning özelliğini kullanmak istersek, örnek bir syntax ;

CREATE TABLE call_detail_records
( id NUMBER
, from_number VARCHAR2(20)
, to_number VARCHAR2(20)
, date_of_call DATE
, distance VARCHAR2(1)
, call_duration_in_s NUMBER(4)
) PARTITION BY RANGE(date_of_call)
INTERVAL (NUMTODSINTERVAL(1,’DAY’))
SUBPARTITION BY LIST(distance)
SUBPARTITION TEMPLATE
( SUBPARTITION local VALUES(‘L’) TABLESPACE tbs1,
SUBPARTITION medium_long VALUES (‘M’) TABLESPACE tbs2,
SUBPARTITION long_distance VALUES (‘D’) TABLESPACE tbs3,
SUBPARTITION international VALUES (‘I’) TABLESPACE tbs4
)
(PARTITION p0 VALUES LESS THAN (TO_DATE(’01-JAN-2005′,’dd-MON-yyyy’)))
PARALLEL;
Table created.

Range-range partitioning yaparken Interval Partitioning özelliğini kullanmak istersek, örnek bir syntax ;

CREATE TABLE account_balance_history
( id NUMBER NOT NULL,
account_number NUMBER NOT NULL,
customer_id NUMBER NOT NULL,
transaction_date DATE NOT NULL,
amount_credited NUMBER,
amount_debited NUMBER,
end_of_day_balance NUMBER NOT NULL
) PARTITION BY RANGE(transaction_date)
INTERVAL (NUMTODSINTERVAL(7,’DAY’))
SUBPARTITION BY RANGE(end_of_day_balance)
SUBPARTITION TEMPLATE
( SUBPARTITION credit VALUES LESS THAN (0),
SUBPARTITION low VALUES LESS THAN (500),
SUBPARTITION normal VALUES LESS THAN (5000),
SUBPARTITION high VALUES LESS THAN (20000),
SUBPARTITION extraordinary VALUES LESS THAN (MAXVALUE)
)
(PARTITION p0 VALUES LESS THAN (TO_DATE(’01-JAN-2007′,’dd-MON-yyyy’)));
Table created.

Range-Hash partitioning yaparken Interval Partitioning özelliğini kullanmak istersek, örnek bir syntax ;

CREATE TABLE sales
( prod_id NUMBER(6),
cust_id NUMBER,
time_id DATE,
channel_id CHAR(1),
promo_id NUMBER(6),
quantity_sold NUMBER(3),
amount_sold NUMBER(10,2)
)
PARTITION BY RANGE (time_id) INTERVAL (NUMTOYMINTERVAL(1,’MONTH’))
SUBPARTITION BY HASH (cust_id) SUBPARTITIONS 4
( PARTITION before_2000 VALUES LESS THAN (TO_DATE(’01-JAN-2000′,’dd-MON-yyyy’)))
PARALLEL;
Table created.

Peki interval partitioning’ i tüm partition tablolarımızda kullanabilirmiyiz ? Hayır kullanamazsınız, diğerlerinde olduğu gibi burada da uymamız gereken bir takım kurallar mevcut, şimdi bu kurallardan/kısıtlarımızdan bahsedelim biraz;

• Interval partitioning sadece tek bir kolon üzerine konulabilir ve bu kolonun type’ da mutlaka Number veya Date olmalıdır. Yani sizin partitionlu tablonuz için partition key’ iniz bir den fazla kolondan oluşuyor ise Interval partitioning’ i kullanamazsınız demektir.
• Index-organized tabloları partitionlarken Interval partitioning’ı kullanamazsınız. Çünkü Interval partitioning index-organized tabloları desteklememektedir.
• Interval Partition kullanılarak oluşturulmuş olan tabloların üzerine domain index oluşturamazsınız.
• Interval partitioning opsiyonunun kullanılabilmesi için, partitionlu tablo create edilirken mutlaka en az bir tane partition tanımlanmış olmalıdır.
• Interval Partitioning, composite partitioning’ lerde kullanılabilir ancak composite partitionlarda sadece birinci levelde kullanılabilir yani subpartition seviyesinde interval partitioning kullanamazsınız.
• Interval paritition kullanılacak yerde Maxvalue paritition tanımlanamaz.
• Partition kolonlar içerisinde Null değerlerin kullanılmasına izin verilmez.

Bunlarda interval partitioning kullanacaksak öncesinde bilmemiz gerekenler diye düşünebiliriz.

İnterval Partitioning kullanımı ile oracle tarafından otomatik olarak partition eklendiğinde, alertlog da aşağıdaki satırlara benzer satırlar görüyor olursunuz;

Sun Apr 29 15:08:05 2012
TABLE KAMIL.INTERVAL_TEST_TABLE2: ADDED INTERVAL PARTITION SYS_P41 (5) VALUES LESS THAN (TO_DATE(‘ 2012-06-01 00:00:00’, ‘SYYYY-MM-DD HH24:MI:SS’, ‘NLS_CALENDAR=GREGORIAN’))
Sun Apr 29 15:24:59 2012
TABLE KAMIL.INTERVAL_TEST_TABLE3: ADDED INTERVAL PARTITION SYS_P42 (4) VALUES LESS THAN (25000)

Interval partitioningı nasıl manage edebiliriz kısmına burada girmiyorum, bu konuya toplu olarak sonrasında değiniyor olacağım.

Be Sociable, Share!

2 comments

  1. Merhaba Mustafa,

    Interval partitioning range partitioning kullanıldığında anlamlı olmaktadır. Id bazlı yapılan partitioninglerde yeni bir grup eklense bile bunu hash partitioning algoritmasına göre bir partitioning’ e ekleyecektir. Ancak sen bunu özellikle yeni bir partitioning yapmak istersen tabloyu alter ederek yeni bir part daha ekleyebilirsin.

    Umarım açıklayıcı olmuştur …

  2. Merhabalar,
    Bir sorum olucaktı.
    Burada hep aslında periyodik yada belli bir formulle bilinen datalara interval uygulayabiliyoruz sanırım.
    Mesela yeni tanımlanan bir grup_id miz var.Bu grup id yi yeni partion olarak nasıl ekleyebiliriz?

    Tşkler.

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir


5 × = onbeş