Oracle Database üzerinde bir tablo büyüdükçe açıkcası çileside aynı oranda büyümeye başlıyor. Küçük tablolarda çok önemli olmayabilir fakat tablo boyutu 50GB ve üstüne çıktığı zaman artık performans çanlarıda çalıyor demektir.
Bugünkü yazımızda Oracle Database için lisans gerektiren Partition Table özelliğinin kesinti olmaksızın klasik bir tabloyu online olarak nasıl partition hale getireceğimizi alacağımızı anlatacağım. Çalışmalarımızda her zamanki gibi ” HR ” kullanıcısından yardım alacağız. Paket kısaca partition olarak hazırladığımız tabloyu materialized view olarak ayarlayacak ve içindeki veriyi buraya aktaracak. Hali hazırda bulunan tablo içinde materialized view log oluşacak ve gelen veriler burada dml olarak tutlacak. Sonrasında tablolar değişerek işlem bitecek.
Senaryomuzda HR kullanıcısı altında olan PERSONEL ( bu tabloyu CTAS yardımıyla hr.employees kopyası olarak ben oluşturdum ) tablosundan yararlanacağım. Partiton olarak açacağım tablo ise PERSONEL_PT olacak. Partition çeşidi olarak ” Interval Partitioning ” partition kullanıyorum.
Interval Partitioning Nedir ?
Interval Partitioning hayatımıza Oracle Database 11G ile birlikte giren ve Range partitioning ile paralel kullanılan bir partition çeşidi.Arasındaki fark Range partitioning ile bir tablo oluşturduğunuz veriler sizin belirlediğiniz partitionlara aktarılıyordu. Interval Partitioning ile eğer örneğin tarih olarak açtığınız partitionlar içinde yoksa sistem otomatik yeni bir partition ekliyor. Eskiden hata döndürüyordu 🙁
Orjinal tablo olan PERSONEL elimde olduğu için sadece Partition Tablomu ( HR.PERSONEL_PT ) .oluşturuyorum.
İşlem yapacağımız tablo eğer büyükse paralellik kulanabilirsiniz
SQL> alter session force parallel dml parallel 8;
SQL> alter session force parallel query parallel 8;
CREATE TABLE HR.PERSONEL_PT
(
EMPLOYEE_ID NUMBER(6),
FIRST_NAME VARCHAR2(20 BYTE),
LAST_NAME VARCHAR2(25 BYTE),
EMAIL VARCHAR2(25 BYTE),
PHONE_NUMBER VARCHAR2(20 BYTE),
HIRE_DATE DATE,
JOB_ID VARCHAR2(10 BYTE),
SALARY NUMBER(8,2),
COMMISSION_PCT NUMBER(2,2),
MANAGER_ID NUMBER(6),
DEPARTMENT_ID NUMBER(4)
)
PARTITION BY RANGE (HIRE_DATE)
INTERVAL ( NUMTOYMINTERVAL (1, 'MONTH') )
(PARTITION part_date1 VALUES LESS THAN (TO_DATE ('01/01/2020', 'DD/MM/YYYY')) TABLESPACE USERS,
PARTITION part_date2 VALUES LESS THAN (TO_DATE ('01/02/2020', 'DD/MM/YYYY')) TABLESPACE USERS,
PARTITION part_date3 VALUES LESS THAN (TO_DATE ('01/03/2020', 'DD/MM/YYYY')) TABLESPACE USERS,
PARTITION part_date4 VALUES LESS THAN (TO_DATE ('01/04/2020', 'DD/MM/YYYY')) TABLESPACE USERS,
PARTITION part_date5 VALUES LESS THAN (TO_DATE ('01/05/2020', 'DD/MM/YYYY')) TABLESPACE USERS);
Tablomuz oluştuğuna göre artık DBMS_REDEFINITION paketinden ayarlanmaya başlayabiliriz. Şimdi tablomuzda bir problem varmı bakalım.
BEGIN
SYS.DBMS_REDEFINITION.can_redef_table (
uname => 'HR',
tname => 'PERSONEL_PT',
options_flag => DBMS_REDEFINITION.CONS_USE_ROWID);
END;
/
Tabloda bir problem görünmediğine göre DBMS_REDEFINITION yardımı ile ikinci adım olan start işlemini yapabiliriz.
Önemli : Burada tablo isimlerini ters yazarsanız veri kaybı yaşayabilirsiniz.
BEGIN
SYS.DBMS_REDEFINITION.start_redef_table (uname => 'HR',
orig_table => 'PERSONEL',
int_table => 'PERSONEL_PT');
END;
/
Şimdi tablonun duruma bakarsanız partition olduğunu göreceksiniz fakat iş bitmedi. Büyük tablolarda SYNC işlemi son adım olan Finish_Redef den önce işlemin uzun sürmemesi için önemlidir. Mevcut verileri mv ile senkron edelim.
BEGIN
DBMS_REDEFINITION.sync_interim_table (uname => 'HR',
orig_table => 'PERSONEL',
int_table => 'PERSONEL_PT');
END;
/
Son olarak işlemleri bitirelim.
BEGIN
DBMS_REDEFINITION.finish_redef_table (uname => 'HR',
orig_table => 'PERSONEL',
int_table => 'PERSONEL_PT');
END;
/
Görüldüğü gibi gayet basit bir işlem ve kesinti olmadan yapılabiliyor. Hızlı ve güzel.
Herhangi bir sebepten işlemi son adımdan önce geri almak isterseniz.
EXEC DBMS_REDEFINITION.ABORT_REDEF_TABLE('HR', 'PERSONEL_PT', 'PERSONEL')
Diğer yazılarda görüşmek dileğiyle.