Blog

Oracle Database Online Partition Table DBMS_REDEFINITION

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.

Buğra PARLAYAN

Çok sevdiği mesleği Oracle Veritabanı Yöneticiliğinde bulunmayan Türkçe kaynakları yazan hayırsever genco

İlgili Makaleler

Bir Yorum

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Başa dön tuşu