Oracle DBMS_REDEFINITION ile Table Partitioning

Merhaba Arkadaşlar,

Bu yazımda sizlere Partition yapıda olmayan bir tabloyu  DBMS_REDEFINITION paketini kullanarak Online olarak Partitionlı yapıya dönüştürmeyi anlatacağım. Bu yazımı okumadan önce Partitioning ile ilgili genel kavramları anlatan şu yazımı okumanızı tavsiye ederim.

oracle partition

 

Kurumların Çalışan production sistemlerinde kritik bir çalışma yapılırken kesinti ( downtime ) almamak yada minimum kesinti almak çok önemlidir. Bu kritik durumlara karşı Oracle kesinti süresini minimize etmeye yada yok etmeye çalışan teknolojiler sunmaktadır. İşte bunlardan biriside Oracle 9i ile Oracle dünyasına tanıtılan DBMS_REDEFINITION paketidir. Bu paket ile Tablolar üzerinde kesinti almadan ( Online bir şekilde ) eskiden kesinti alarak yaptığımız bir çok operasyonu bu paketi kullanarak Online olarak yapabiliyoruz. Kesinti almadan bu paketi kullanarak Tablolar üzerinde yaptığımız operasyonlardan bazıları aşağıdaki gibidir.

  • Partition Yapıda olmayan bir Tabloyu Partitionlı yapıya dönüştürme
  • Index i olmayan bir Tabloyu (Heap Table) İndexli yapıya dönüştürme
  • Tabloya Kolon ekleme,Çıkarma ve Kolon ismini değiştirme
  • Tablonun Storage ( Depolama ) parametrelerini değiştirme
  • Bir tabloyu Reorganize etme

Production sistemlerde büyük tablolar için çok sıklıkla kullanılan yukardaki işlemleri Online olarak yapma çok önemli ve hayatidir. Bu yüzden yukardaki işlemleri yaparken DBMS_REDEFINITION paketinin bizlere sunduğu güzelliklerden mutlaka faydalanın derim.

Peki DBMS_REDEFINITION ile  Online Table Partitioning yaparken Oracle arka planda ne yapıyor ? DBMS_REDEFINITION paketi ile Table Partitioning olayını aşağıdaki resim özetlemektedir.

redefinition

Peki Oracle bu Paketi kullanarak Redefinition Partitioning işlemini arka plandaki nasıl yapıyor ? İlgili işlemin çalışma adımları aşağıdaki gibidir.

  1. Oracle ilgili ana tabloyu Materalized View e dönüştürüp ana tablonun datalarını bu view e aktarır.
  2. Aynı anda Ana tabloda Materalized view log u oluşturup tabloya online gelen transactionları buraya yönlendirir.
  3. Ana Tablo üzerindeki Tüm değişiklikler gerçekleştirildikten sonra bu değişiklikler Ara tablo dediğimiz interim table a aktarılır. Bu tablo partitionlı yapıda olduğu için ilgili veriler tabloya insert edilirken her satır uygun olduğu partition a gider.
  4. Son olarak Data dictionary de Ana tablo ( Fatura ) ile Ara tablonun ( Fatura_old )isimleri birbirleriyle değiştirilir. Böylece Ana tablo ilk durumda oluşturulan partitionlı yapıdaki tabloya dönüşmüş olur.

Şimdi Partitionlı yapıda olmayan bir tabloyu bu yöntemi kullanarak Partitionlı yapıya dönüştürmeyi önceki yazıda örnek verdiğim Belediyenin Fatura tablosu üzerinden örnekle ilgili kodları vererek anlatacağım. Örnek Fatura tablosunun scripti ve bazı dataları aşağıdaki gibidir.

SQL> CREATE TABLE MSDEVECI.FATURA
 (
 MUSTERI_ID NUMBER PRIMARY KEY,
 ADI VARCHAR2(50 BYTE),
 BORC NUMBER,
 FATURA_TARIHI DATE
 )

SQL> select * from msdeveci.fatura;

data

Öncellikle veritabanı üzerinden fatura tablosunun partitionlı yapıda olup olmadığını aşağıdaki gibi sorguluyorum. Sorguyu çalıştırdığım zaman boş cevap geliyor. Yani tablo partitionlı yapıda değildir.

select * from dba_tab_partitions where table_name='FATURA';

Redefinition ile Table partitioning örneğini yapmaya başlamadan önce Orjinal Tabloyla (Fatura adlı tablo) aynı kolon yapısına sahip ve partition lı yapıda ara ( interim table ) bir tablo ( Fatura_old adında ) oluşturmamız gerekiyor. ( Son adımda bu ara tablo isim değiştirerek Ana tablonun yerini alacak. )  Yukarda belirttiğim interim table dediğimiz Range Partitionyapısına uygun ara tabloyu fatura_old adıyla oluşturuyoruz. Fatura_old tablosunun scripti aşağıdaki gibidir.

CREATE TABLE MSDEVECI.FATURA_OLD
 (
 MUSTERI_ID NUMBER PRIMARY KEY,
 ADI VARCHAR2(50 BYTE),
 BORC NUMBER,
 FATURA_TARIHI DATE
 )
 PARTITION BY RANGE(FATURA_TARIHI)(
 PARTITION Fatura201301 VALUES LESS THAN(TO_DATE('01/01/2013','DD/MM/YYYY')),
 PARTITION Fatura201302 VALUES LESS THAN(TO_DATE('01/02/2013','DD/MM/YYYY')),
 PARTITION Fatura201303 VALUES LESS THAN(TO_DATE('01/03/2013','DD/MM/YYYY')),
 PARTITION Fatura201304 VALUES LESS THAN(TO_DATE('01/04/2013','DD/MM/YYYY')),
 PARTITION Fatura201305 VALUES LESS THAN(TO_DATE('01/05/2013','DD/MM/YYYY')),
 PARTITION Fatura201306 VALUES LESS THAN(TO_DATE('01/06/2013','DD/MM/YYYY')),
 PARTITION Fatura201307 VALUES LESS THAN(TO_DATE('01/07/2013','DD/MM/YYYY')));

Yukardaki scripti çalıştırıp fatura_old adlı interim table ı oluşturdum. Redefinition işlemine başlamadan önce  Ana tablomuzun ve ara tablomuzun bu işlem için uygun olup olmadığını DBMS_REDEFINITION paketinin CAN_REDEF_TABLE procedure unu çalıştırarak kontrol ediyoruz.

— Primary key li olan tablonun kontrolü için aşağıdaki script çalıştırılır. Benim tablomda primary key olduğu için aşağıdaki scripti çalıştırdım.

SQL> EXEC DBMS_REDEFINITION.CAN_REDEF_TABLE('MSDEVECI', 'fatura',1);

— Primary key yoksa ROWNUM ile kontrol etmek için aşağıdaki script çalıştırılır.

SQL> EXEC DBMS_REDEFINITION.CAN_REDEF_TABLE('MSDEVECI', 'fatura',2);

Yukardaki scriptlerden uygun olanı çalıştırıp tablonun redefinition işlemi için uygun olduğunu teyit ettikten sonra Redefinition işlemine başlayabiliriz. Aşağıdaki scriptde 1.kısımda Redefinition işlemini DBMS_REDEFINITION paketinin START_REDEF_TABLE procedure unu Primary key üzerinden çalıştırdığımızda tablonun datalarını taşırız.

2. kısımda tabloya ait Indexler,Triggerler, Constraintler, Grant leride DBMS_REDEFINITION  paketinin COPY_TABLE_DEPENDENTS procedure uyle taşınan script bulunmaktadır. Burada script çalıştırıldığında önce ilk kısım taşınır ve Tablonun dataları taşınır daha sonra 2.kısım çalışır ve tablonun geriye kalan yukardaki gereksinimleri taşınır.

DECLARE
 redefinition_errors PLS_INTEGER := 0;
 BEGIN
-- 1.Kısım

DBMS_REDEFINITION.START_REDEF_TABLE (
 uname => 'MSDEVECI'
 ,orig_table => 'fatura'
 ,int_table => 'fatura_old'
 ,col_mapping => NULL
 ,options_flag => DBMS_REDEFINITION.CONS_USE_PK
 );

-- 2.kısım

DBMS_REDEFINITION.COPY_TABLE_DEPENDENTS (
 uname => 'MSDEVECI'
 ,orig_table => 'fatura'
 ,int_table => 'fatura_old'
 ,copy_indexes => 0
 ,copy_triggers => TRUE
 ,copy_constraints => TRUE
 ,copy_privileges => TRUE
 ,ignore_errors => TRUE
 ,num_errors => redefinition_errors
 ,copy_statistics => FALSE
 ,copy_mvlog => FALSE);
IF (redefinition_errors > 0) THEN
 DBMS_OUTPUT.PUT_LINE('>>> AUDIT_COUNTER_RD to AUDIT_COUNTER failed: ' || TO_CHAR(redefinition_errors));
 END IF;
END;
 /

Yukardaki scripti çalıştırdıktan sonra Redefinition işlemini bitirmek için DBMS_REDEFINITION paketinin  FINISH_REDEF_TABLE procedure u nu aşağıdaki gibi çalıştırıyoruz.

begin
DBMS_REDEFINITION.FINISH_REDEF_TABLE (
 uname => 'MSDEVECI'
 ,orig_table => 'fatura'
 ,int_table => 'fatura_old'
 );
 END;

Yukardaki scripti çalıştırdıktan sonra Redefinition işlemini bitiriyoruz. FINISH_REDEF_TABLE procedure u ile  Data dictionary de Ana tablo ( Fatura ) ile interim table ın ( Fatura_old )isimlerini değiştirilir. Böylece Ana tablo ilk durumda oluşturulan partitionlı yapıdaki tabloya dönüşmüş olur.

Çok büyük tabloların taşınması sırasında FINISH_REDEF_TABLE  procedure unun çok çok uzun sürmemesi için Redefinition işlemini başlattığımız script tamamlandıktan sonra finish procedure unu çalıştırmadan önce DBMS_REDEFINITION paketinin SYNC_INTERIM_TABLE procedure unu çalıştırarak ara tablo dediğimiz fatura_old tablosuyla fatura tablosu arasında ki son senkronizasyon da gerçekleştirilir. Bu procedure u çalıştırıp tamamladıktan FINISH_REDEF_TABLE  procedure u daha kısa sürede tamamlanır. SYNC_INTERIM_TABLE procedure unun ilgili scripti aşağıdaki gibidir.

BEGIN
 DBMS_REDEFINITION.SYNC_INTERIM_TABLE('MSDEVECI', 'fatura', 'fatura_old');
 END;
 /

Ben genelde Redefinition ile partitioning yapılırken eğer tablom çok büyükse aşağıdaki sırada procedure lerimi çalıştırıyorum.

CAN_REDEF_TABLE —> START_REDEF_TABLE ->> COPY_TABLE_DEPENDENTS  ——>                                                  —–>  SYNC_INTERIM_TABLE —> FINISH_REDEF_TABLE

FINISH_REDEF_TABLE  procedure unu çalıştırdıktan sonra fatura tablom partitionlı hale gelmiş oldu. Bunun ispatı yukarda da verdiğim scripti tekrar çalıştırdığımda sonucu aşağıdaki gibi oluyor. Buradan da görüldüğü gibi fatura tablom partitionla yapıya dönüşmüş oldu.

select * from dba_tab_partitions where table_name='FATURA';

Data2

İlk yazımda bahsettiğim gibi mayıs ayına ait herhangi bir müşteriye ait veriyi sorguladığımızda Oracle tüm verileri değil sadece mayıs ayına ait partitiondan sorgular. Partitiona göre veri sorgulama aşağıdaki gibi yapılır.

 select * from fatura partition(Fatura201306) where musteri_id=57052;

data3

Yukardaki sorgunun execution planını çalıştırdığımızda ilgili veriye aşağıdaki gibi partitiondan eriştiğini görebiliyoruz.

data1

Böylece bu yazımın daha sonuna gelmiş bulunmaktayım bir sonraki yazıda görüşmek dileğiyle Esen kalın..

 

Oracle Exadata SQL Server Goldengate Weblogic EBS ve Linux konusunda aşağıdaki konularda 7×24 Uzman Danışmanlara yada Eğitimlere mi İhtiyacınız var mehmet.deveci@gridgroup.com.tr adresine mail atarak Bizimle iletişime geçebilirsiniz.

– Oracle Veritabanı Danışmanlığı
– Oracle Veritabanı Bakım ve Destek
– Exadata Danışmanlığı
– Exadata Bakım ve Destek
– SQL Server Veritabanı Danışmanlığı
– SQL Server Veritabanı Bakım ve Destek
– Goldengate Danışmanlığı
– Goldengate Bakım ve Destek
– Linux Danışmanlığı
– Linux Bakım ve Destek
– Oracle EBS Danışmanlığı
– Oracle EBS Bakım ve Destek
– Weblogic Danışmanlığı
– Weblogic Bakım ve Destek
– Oracle Veritabanı Eğitimleri
– Oracle VM Server Danışmanlığı
– Oracle VM Server Bakım ve Destek
– Oracle EPPM Danışmanlığı
– Oracle EPPM Bakım ve Destek
– Oracle Primavera Danışmanlığı
– Oracle Primavera Bakım ve Destek
– Oracle Eğitimleri
– SQL Server Eğitimleri
– Goldengate Eğitimleri
– Exadata Eğitimleri
– Linux Eğitimleri
– Oracle EBS Eğitimleri
– Oracle VM Server Eğitimleri
– Weblogic Eğitimleri
– Oracle EPPM Eğitimleri
– Oracle Primavera Eğitimleri

Mehmet Salih Deveci

I am Founder of IT Tutorial and Certified Expert about Oracle & SQL Server database, Goldengate, Exadata Machine, Oracle Database Appliance administrator with 10+years experience. I have OCA, OCP, OCE RAC Expert Certificates I have worked 100+ Banking, Insurance, Finance, Telco and etc. clients as a Consultant, Insource or Outsource. I have done 200+ Operations in this clients such as Exadata Installation & PoC & Migration & Upgrade, Oracle & SQL Server Database Upgrade, Oracle RAC Installation, SQL Server AlwaysOn Installation, Database Migration, Disaster Recovery, Backup Restore, Performance Tuning, Periodic Healthchecks. I have done 2000+ Table replication with Goldengate or SQL Server Replication tool for DWH Databases in many clients. If you need Oracle DBA, SQL Server DBA, APPS DBA,  Exadata, Goldengate, EBS Consultancy and Training you can send my email adress mehmetsalih.deveci@outlook.com. -                                                                                                                                                                                                                                                 - Oracle DBA, SQL Server DBA, APPS DBA,  Exadata, Goldengate, EBS ve linux Danışmanlık ve Eğitim için  mehmetsalih.deveci@outlook.com a mail atabilirsiniz.

One thought on “Oracle DBMS_REDEFINITION ile Table Partitioning