İçindekiler

Bu yazımda sizlere hemen hemen Tüm Veritabanı yönetim sistemlerinde var olan Partitioning gibi güzel bir teknolojiyi anlatacağım.

Partitioning teknolojisini genel olarak ifade edersek çok büyük tablolarımızı, indexlerimizi yada index-organized tablolarımızı ayrı ayrı segmentlerde oluşturabilmemize olanak sağlayan bir teknolojidir diyebiliriz. Yani mantıksal olarak bir bütün halinde görünen büyük tablo yada indexleri Partitionlı yapıya dönüştürdüğümüzde daha küçük farklı fiziksel bölümlere ayırabilmekteyiz.

Özellikle çok büyük veritabanı sistemlerinde(VLDB=Very Large DB) terabytelar seviyesinde datanın olması hem bu datanın bakımında hem de üzerinde gerekli işlemlerin yapılabilmesinde sıkıntılara yol açar. Bununla baş edebilmenin ilk akla gelen en etkin yolu bu büyük parçayı daha ufak parçalara ayırmaktır.Burada devreye “partitioning” kavramı girmektedir.”Partitioning” verilerin bir bütün içersinde parçalara ayrılması seklinde kabaca açıklanabilir.

Partitioning ile bir tablo ya da index kendi içinde daha küçük parçalara ayrıştırılıp kullanılabilir.İşin güzel yanı bu yapıldıgı takdirde yazılan DML sorgu vs. scriplerde herhangi bir değişiklik yapmanıza gerek yoktur. Oracle bunu kendisi halleder.(Tabi bazı durumlarda partition ismi vererekte işlem yapmak gerekebilir.) Ancak, partitionlar tanımlandıktan sonra,  DDL sorguları tabloların veya indexlerin tamamı yerine bireysel partitionlara erişebilir ve bunları işleyebilir. Bu, bölümlemenin büyük veritabanı nesnelerinin yönetilebilirliğini nasıl basitleştirebileceğidir.

Bir tablonun veya indexin her partitionı, sütun adları, veri türleri ve kısıtlamalar gibi aynı mantıksal niteliklere sahip olmalıdır, ancak her partition, sıkıştırmanın etkin veya devre dışı bırakılmısı fiziksel storage ayarları ve tablospace gibi ayrı fiziksel niteliklere sahip olabilir. Örneğin Bir tablonun en eski 10 yıllık verilerini SATA disklere yönlendirirken güncel verilerinin SAS üzerinde olacak Ģekilde konumlandırabiliriz.

Partitioning, özellikle büyük hacimli verileri yöneten uygulamalar olmak üzere birçok farklı türde uygulama için kullanışlıdır. OLTP sistemleri genellikle yönetilebilirlik ve kullanılabilirlikteki gelişmelerden yararlanırken, veri depolama sistemleri performans ve yönetilebilirlikten yararlanır.

Partitioning şu avantajları sunar:

  • Tüm tablo yerine index oluşturma ve rebuilding, partition düzeyinde yedekleme ve kurtarma gibi veri yönetimi işlemlerini sağlar. Bu, bu işlemler için önemli ölçüde azaltılmış zamanlarla sonuçlanır. (Örneğin partition metoduna bağlı olarak 5 farklı partition olan bir tabloda 2. partition ı drop edebilir, farklı bir index oluşturabilir ya da bu partition’ı tablodan bağımsız olarak truncate edebilirsiniz.)
  • Büyük parçalar ile uğraşmak yerine küçük parçalar ile uğraşıldığından özellikle sorgula işlemlerinde büyük kazanç sağlar.
  • Maintenance işlemleri için zamanlanmış downtime süresinin etkisini önemli ölçüde azaltır.
  • Paralel execution, kaynak kullanımını optimize etmek ve execution time’ı en aza indirmek için özel avantajlar sağlar. Parallel execution, sorgular ve DML ve DDL için desteklenir.


LONG veya LONG RAW veri türlerine sahip sütunlar içeren tablolar haricinde, herhangi bir tablo milyonlarca ayrı partitiona ayrılabilir. Bununla birlikte, CLOB veya BLOB veri türlerine sahip sütun içeren tablolarıda kullanabilirsiniz. Bunun yanısıra bir tabloda veya index’de ne zaman partition önerilir;

Tablo için;

  • 2 GB’den büyük tablolar. Bu tablolar her zaman partitioning için aday olarak düşünülmelidir.
  • En yeni partition yeni verilerin eklendiği geçmiş verileri içeren tablolar.Örneğin yalnızca geçerli ayın verilerinin güncellenebildiği ve diğer 11 ayın salt okunur olduğu tarihsel bir tablodur.
  • İçeriği farklı depolama aygıtlarına dağıtılması gereken tablolar.

Index için;

  • Veriler silindiğinde index maintenance’den kaçınmak için. Mesela ay bazlı 12 partition olduğunu düşünelim, sadece 3.ayın verileri silindiğinde normalde bütün index işlem görür ama index’de partition varsa sadece 3.aydaki index işlem görür.
  • Tüm indexi geçersiz kılmadan index verisinin bir kısmını erişime kapatma.

Partition Key

Partitioning yapmak için ilk adım, bir kaydın hangi partition’da yer alacağını belirleyen bir veya daha fazla kolondan oluşan bir KEY belirlenmesi adımıdır.  Parititioned bir tabloda her bir satır bilgi kesinlikle tek bir partition’da tutulmaktadır. Bunu sağlayan “partition key”dir. Bir kere tanımlanınca veri üzerinde yapılan sorgu , güncelleme, silme vs. İşlemler bu anahtar sayesinde ilgili partiton da yapılır.

Oracle Partitioning, verilerin bireysel partitionlara nasıl yerleştirildiğini kontrol eden temel bölümlendirme stratejileri olarak üç temel veri dağıtım yöntemi sunar:

  • Range
  • Hash
  • List

Bu veri dağıtım yöntemlerini kullanarak, single-level olarak veya composite-partitioned bir tablo olarak bölümlenebilir.

  • Single-Level Partitioning
  • Composite Partitioning

Single-Level Partitioning

Partition Key olarak bir veya daha fazla sütun kullanılarak, aşağıdaki veri dağıtım yöntemlerinden birinin belirlenmesi ile tanımlanan partitionlar:

  • Range Partitioning
  • Hash Partitioning
  • List Partitioning

Range Partitioning

En sık kullanılan partitioning yöntemlerinden birisidir. Bu yöntemde veriler belirli Tarih ve sayı aralığına göre ayrılır. Her partition ın alt ve üst sınırı var ve veriler bu aralıkta partitionlara depolanır.

CREATE TABLE sales_range
(
   salesman_id     NUMBER (5),
   salesman_name   VARCHAR2 (30),
   sales_amount    NUMBER (10),
   sales_date      DATE
)
PARTITION BY RANGE (sales_date)
   (PARTITION sales_jan2000 VALUES LESS THAN (TO_DATE ('02/01/2000', 'MM/DD/YYYY')),
    PARTITION sales_feb2000 VALUES LESS THAN (TO_DATE ('03/01/2000', 'MM/DD/YYYY')),
    PARTITION sales_mar2000 VALUES LESS THAN (TO_DATE ('04/01/2000', 'MM/DD/YYYY')),
    PARTITION sales_apr2000 VALUES LESS THAN (TO_DATE ('05/01/2000', 'MM/DD/YYYY')));

Örnekte partition key “sales_date” alanıdır. Bu alanın değeri esas alınarak “VALUES LESS THAN” anahtar kelimesi ile 4 farklı partition belirlenmiştir.

  • Her bir partition “VALUES LESS THAN” anahtar kelimesi ile oluşturulur.Bu değere eşit ya da büyük veriler bir yukarda tanımlı partiton’ a gider.
  • İlk partition hariç digerleri kendisinden sonra gelen partition key değeri ile sınırlandırılmıştır.
  • En yüksek partition’da “MAXVALUE” anahtar kelimesi kullanılabilir.Bu durumda en yüksek partition’a da giremeyen veriler buraya yönlenir.(NULL değerler dahil.)

Bunlara ek olarak aşağıdaki metod birden fazla kolonun partiton key olarak tanımlanmasına izin verir.

CREATE TABLE ORDERS
(
   ORDID         NUMBER (4) NOT NULL,
   ORDERDATE     DATE,
   COMMPLAN      VARCHAR2 (1),
   CUSTID        NUMBER (6) NOT NULL,
   SHIPDATE_MM   NUMBER (2) NOT NULL,
   SHIPDATE_YY   NUMBER (2) NOT NULL,
   TOTAL         NUMBER (8, 2)
)
PARTITION BY RANGE (SHIPDATE_YY, SHIPDATE_MM)
   (PARTITION Q197 VALUES LESS THAN (97, 04) TABLESPACE TS_Q197,
    PARTITION Q297 VALUES LESS THAN (97, 07) TABLESPACE TS_Q297
                ...
                )

NOT : Partiton bazında select yapmak istersek;

SELECT * FROM sales_range PARTITION (sales_feb2000);

List Partitioning

Range’te bir sınır değerler baz alınıyorken list yönteminde partiton key’in verilen bir listede var olup olmaması önemlidir. Örneğin tablonuzda şehir bilgisi tutan bir kolonunuz olsun.Siz bu kolon değerini partiton key seçtiğinizde “İstanbul,Ankara” olan verileri P1 partition’ına ,”İzmir,Antalya,Bursa” olan verileri  P2 partition’a gönder şeklinde bir tanımlama yapabilirsiniz. Örnek :

CREATE TABLE sales_list

(
   salesman_id     NUMBER (5),
   salesman_name   VARCHAR2 (30),
   sales_state     VARCHAR2 (20),
   sales_amount    NUMBER (10),
   sales_date      DATE
)
PARTITION BY LIST (sales_state)
   (PARTITION sales_west VALUES ('California', 'Hawaii'),
    PARTITION sales_east VALUES ('New York', 'Virginia', 'Florida'),
    PARTITION sales_central VALUES ('Texas', 'Illinois'),
    PARTITION sales_other VALUES (DEFAULT));

”DEFAULT” olarak belirtilen partition, Oracle tarafından, kullanıcının yaptığı tanımlar dışında veri geldiğinde kullanılır.

NOT : Birden fazla kolonun partition key olarak tanımlanamaz.

Hash Partitioning

Bu yöntemde, partition key kolonuna belli bir hash algorittması uygulanır ve çıkan sonuca göre veri paritionlara dağıtılır. Hash partitioning, verileri aygıtlar arasında eşit olarak dağıtmak için ideal yöntemdir. Hash partitioning, özellikle bölümlenecek veriler tarihsel olmadığında veya bariz bir partition key olmadığında, aralık bölümlendirmeye kolay kullanımlı bir alternatiftir. Partitioning tarafından kullanılan hash algoritmaları değiştiremezsiniz. Ancak bu metodda diğerleri gibi partiton’ı ayırma, düşürme(drop) ve birleştirme(merge) yapılamaz.Sadece yeni bir partiton eklenebilir ya da “COALESCE” dediğimiz partition’da (ya da subpartition’da) bulunan verileri diğer partition’lara (ya da subpartition’lara) dağıtma işlemi yapılabilir.(Düzenlenen partion(ya da subpartition) bu işlemden sonra silinir.) Örneğin, Vatandaşlık tablosundaki TC Kimlik Numarası kolonu yukardaki hiçbir yönteme uygun değildir bu durumda Hash partitioning kullanılır. Bunların yanında bu metodun bir avantajı pararel DML işlemlerine , partition-wise join …vs imkan vermesidir.

CREATE TABLE sales_hash
(
   salesman_id     NUMBER (5),
   salesman_name   VARCHAR2 (30),
   sales_amount    NUMBER (10),
   week_no         NUMBER (2)
)
PARTITION BY HASH (salesman_id)
   PARTITIONS 4 STORE IN (tablespace1, tablespace2, tablespace3, tablespace4);

Composite Partitioning

Bu partitioning yöntemi diğer partitioning yöntemlerinin birleştirilip beraber kullanılması şeklindedir. Composite partitioning, temel veri dağıtım yöntemlerinin bir birleşimidir; bir tablo bir veri dağıtım yöntemi ile partitionlanır ve daha sonra her partition ikinci bir veri dağıtım yöntemi kullanılarak alt bölümlere(subpartitions) ayrılır. Belirli bir partition için tüm subpartitionlar verilerin mantıksal bir alt kümesini temsil eder. Bu yöntemle belli bir mantığa göre ayırdığımız dataları ayırdığımız şekliyle tekrar bir kurala göre ayırmadır. Örneğin, Range yöntemine göre ayırdığımız partition verilerini aynı zamanda list ve hash yönteminide ekleyerek Range-List ve Range-Hash partition uygulanabilir.

  • Composite Range-Range Partitioning
  • Composite Range-Hash Partitioning
  • Composite Range-List Partitioning
  • Composite List-Range Partitioning
  • Composite List-Hash Partitioning
  • Composite List-List Partitioning
  • Composite Hash-Hash Partitioning
  • Composite Hash-List Partitioning
  • Composite Hash-Range Partitioning

Composite Range-Range Partitioning

Zamana bağlı verileri birden çok zaman boyutunda depolayan uygulamalar için kullanışlıdır. Genellikle, bu uygulamalar verilere erişmek için belirli bir zaman boyutu kullanmaz, bunun yerine başka bir zaman boyutunu veya bazen her ikisini de aynı anda kullanır. Örneğin, bir web satıcısı, satış verilerini siparişlerin ne zaman verildiğini ve siparişlerin ne zaman gönderildiğini dayalı olarak analiz etmek ister. Örnek aşağıdaki örnekde, bir range-range partition yapılmış account_balance_history tablosunu gösterir. Bir banka, düşük bakiye hatırlatmaları veya belirli bir müşteri kategorisine ilişkin belirli promosyonlar için müşterileriyle iletişim kurmak için ayrı subpartitionlara erişimi kullanabilir.

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 unacceptable VALUES LESS THAN (-1000),
         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')));

Composite Range-Hash Partitioning

Bu yöntemde Range yöntemiyle partitiona ayrılan veriler ayrıca birde hash lenerek sub partition lara ayrılabilir. Composite range-hash partitioning özellikle geçmişi depolayan, sonuç olarak çok büyük olan ve sık sık diğer büyük tablolarla birleştirilen tablolar için yaygındır.

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;

CREATE INDEX from_number_ix ON call_detail_records (from_number) LOCAL PARALLEL NOLOGGING;

CREATE INDEX to_number_ix ON call_detail_records (TO_NUMBER) LOCAL PARALLEL NOLOGGING;

Composite Range-List Partitioning

Bu yöntemde Range yöntemiyle partitiona ayrılan veriler ayrıca birde List sub partition lara ayrılabilir. eçmiş verileri depolayan ve genellikle birden çok boyutta erişilen büyük tablolar için kullanılır. Genellikle verinin tarihsel görünümü bir erişim yoludur, ancak bazı durumlarda erişim yoluna başka bir kategori ekler. Örneğin, bölgesel hesap yöneticileri belirli bir zaman diliminde kendi bölgelerinde kaç tane yeni müşteri kaydettikleri ile çok ilgileniyorlar.

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;

CREATE INDEX from_number_ix ON call_detail_records (from_number) LOCAL PARALLEL NOLOGGING;

CREATE INDEX to_number_ix ON call_detail_records (TO_NUMBER) LOCAL PARALLEL NOLOGGING;

Composite List-Range Partitioning

Bu yöntemde List yöntemiyle partitiona ayrılan veriler ayrıca birde range sub partition lara ayrılabilir.

CREATE TABLE donations
(
   id               NUMBER,
   name             VARCHAR2 (60),
   beneficiary      VARCHAR2 (80),
   payment_method   VARCHAR2 (30),
   currency         VARCHAR2 (3),
   amount           NUMBER
)
PARTITION BY LIST (currency)
   SUBPARTITION BY RANGE (amount)
   (PARTITION p_eur
       VALUES ('EUR') (
       SUBPARTITION p_eur_small VALUES LESS THAN (8),
       SUBPARTITION p_eur_medium VALUES LESS THAN (80),
       SUBPARTITION p_eur_high VALUES LESS THAN (MAXVALUE)),
    PARTITION p_inr
       VALUES ('INR') (
       SUBPARTITION p_inr_small VALUES LESS THAN (400),
       SUBPARTITION p_inr_medium VALUES LESS THAN (4000),
       SUBPARTITION p_inr_high VALUES LESS THAN (MAXVALUE)),
    PARTITION p_zar
       VALUES ('ZAR') (
       SUBPARTITION p_zar_small VALUES LESS THAN (70),
       SUBPARTITION p_zar_medium VALUES LESS THAN (700),
       SUBPARTITION p_zar_high VALUES LESS THAN (MAXVALUE)),
    PARTITION p_default
       VALUES (DEFAULT) (
       SUBPARTITION p_default_small VALUES LESS THAN (10),
       SUBPARTITION p_default_medium VALUES LESS THAN (100),
       SUBPARTITION p_default_high VALUES LESS THAN (MAXVALUE)))
ENABLE ROW MOVEMENT;

Composite List-Hash Partitioning

Bu yöntemde List yöntemiyle partitiona ayrılan veriler ayrıca birde hash sub partition lara ayrılabilir.

CREATE TABLE credit_card_accounts
(
   account_number    NUMBER (16) NOT NULL,
   customer_id       NUMBER NOT NULL,
   customer_region   VARCHAR2 (2) NOT NULL,
   is_active         VARCHAR2 (1) NOT NULL,
   date_opened       DATE NOT NULL
)
PARTITION BY LIST (customer_region)
   SUBPARTITION BY HASH (customer_id)
      SUBPARTITIONS 16
   (PARTITION emea VALUES ('EU', 'ME', 'AF'),
    PARTITION amer VALUES ('NA', 'LA'),
    PARTITION apac VALUES ('SA', 'AU', 'NZ', 'IN', 'CH')) PARALLEL;

CREATE BITMAP INDEX is_active_bix ON credit_card_accounts (is_active) LOCAL PARALLEL NOLOGGING;

Composite List-List Partitioning

Bu yöntemde List yöntemiyle partitiona ayrılan veriler ayrıca birde list sub partition lara ayrılabilir.

CREATE TABLE current_inventory
(
   warehouse_id        NUMBER,
   warehouse_region    VARCHAR2 (2),
   product_id          NUMBER,
   product_category    VARCHAR2 (12),
   amount_in_stock     NUMBER,
   unit_of_shipping    VARCHAR2 (20),
   products_per_unit   NUMBER,
   last_updated        DATE
)
PARTITION BY LIST (warehouse_region)
   SUBPARTITION BY LIST (product_category)
      SUBPARTITION TEMPLATE (
         SUBPARTITION perishable VALUES ('DAIRY', 'PRODUCE', 'MEAT', 'BREAD'),
         SUBPARTITION non_perishable VALUES ('CANNED', 'PACKAGED'),
         SUBPARTITION durable VALUES ('TOYS', 'KITCHENWARE'))
   (PARTITION p_northwest VALUES ('OR', 'WA'),
    PARTITION p_southwest VALUES ('AZ', 'UT', 'NM'),
    PARTITION p_northeast VALUES ('NY', 'VM', 'NJ'),
    PARTITION p_southeast VALUES ('FL', 'GA'),
    PARTITION p_northcentral VALUES ('SD', 'WI'),
    PARTITION p_southcentral VALUES ('OK', 'TX'));

CREATE INDEX warehouse_id_ix ON current_inventory (warehouse_id) LOCAL PARALLEL NOLOGGING;

CREATE INDEX product_id_ix ON current_inventory (product_id) LOCAL PARALLEL NOLOGGING;

Composite Hash-Hash Partitioning

Bu yöntemde hash yöntemiyle partitiona ayrılan veriler ayrıca birde hash sub partition lara ayrılabilir.

Composite Hash-List Partitioning

Bu yöntemde hash yöntemiyle partitiona ayrılan veriler ayrıca birde list sub partition lara ayrılabilir.

Composite Hash-Range Partitioning

Bu yöntemde hash yöntemiyle partitiona ayrılan veriler ayrıca birde range sub partition lara ayrılabilir.

Partitioning Extensions

Temel partitioning stratejilerine ek olarak, Oracle Database aşağıdaki partitioning eklentilerinide sağlar:

  • Manageability Extensions
    • Interval Partitioning
    • Partition Advisor : Partition Advisor, SQL Access Advisor’ın bir parçasıdır. Partition Advisor, SQL Cachetarafından tedarik edilebilen veya bir SQL Tuning seti tarafından sağlanan ya da kullanıcı tarafından tanımlanabilen, tedarik edilen SQL ifadelerinin iş yüküne dayanan bir tablo için bir partitioning stratejisi önerebilir.
  • Partitioning Key Extensions
    • Reference Partitioning
    • Virtual Column-Based Partitioning : Virtual column, tabloda bir veya daha fazla mevcut sütunu temel alan bir ifadedir. virtual bir column yalnızca meta veriler olarak depolanır ve fiziksel alan tüketmez, ancak indexe eklenebilir ve ayrıca optimizer istatistikleri ve histogramlar içerebilir. Oracle 11g, virtual bir sütunda bir partition key kullanarak bir tablonun partitioning  desteğini de içeriyor. 11g’den önce, bir partition key fiziksel sütunların kullanımıyla sınırlıydı. Örneğin, 10 basamaklı bir account ID sütununun, ilk 3 karakteri account şubesi bilgilerinini içersin. virtual column based partitioning ile, bir ACCOUNT_ID sütunu içeren bir ACCOUNTS tablosu, ACCOUNT_BRANCH virtual (türetilmiş) bir sütunla genişletilebilir. ACCOUNT_BRANCH, bu tablo için partitioning key haline gelen ACCOUNT_ID sütununun ilk üç hanesinden elde edilir.

Interval Partitioning

Bu partitioning yöntemi Oracle 11g ile beraber gelen Range partitioning ile beraber kullanılan yeni bir yöntemdir. Range partitioning yönteminde gelen veri uygun olan partititona ekleniyordu ancak uygun partition bulamadığındaysa ORA-14400 hatasını veriyordu. İşte Interval Partititoning ile artık bu sorun otomatik olarak çözülmektedir. Yani Interval 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.   Interval partitioning kullarnırken 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.

Bir örnek yapacak olursak;

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);

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;

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')));

Reference Partitioning

Referans partitioning, referans constraints ile birbiriyle ilişkili iki tablonun partitioningini sağlar. Partitioning key, etkin ve active primary key ve foreign key constraint leri tarafından uygulanan mevcut bir parent-child ilişkisi ile çözülür. Bu eklentinin yararı, parent-child ilişkisine sahip tabloların, primary key sütunları çoğaltmadan partitioning keyi ana tablodan miras alarak mantıksal olarak bölünmesidir. Mantıksal bağımlılık ayrıca partition bakım işlemlerini otomatik olarak basamaklandırır, böylece uygulama geliştirmeyi daha kolay ve daha az hataya açık hale getirir.

CREATE TABLE orders (
  order_id    NUMBER PRIMARY KEY,
  order_date  DATE NOT NULL,
  customer_id NUMBER NOT NULL,
  shipper_id  NUMBER)
PARTITION BY RANGE (order_date) (
  PARTITION y1 VALUES LESS THAN (TO_DATE('01-JAN-2006', 'DD-MON-YYYY')),
  PARTITION y2 VALUES LESS THAN (TO_DATE('01-JAN-2007', 'DD-MON-YYYY')),
  PARTITION y3 VALUES LESS THAN (TO_DATE('01-JAN-2008', 'DD-MON-YYYY')));
  
CREATE TABLE order_items (
  order_id    NUMBER NOT NULL,
  product_id  NUMBER NOT NULL,
  price       NUMBER,
  quantity    NUMBER,
  CONSTRAINT order_items_fk FOREIGN KEY (order_id) REFERENCES orders)
PARTITION BY REFERENCE (order_items_fk);  

Partition yapılmış Tablolarda Index Oluşturma

Partition tablomuzu oluşturduğumuzu varsayarsak, bu partitionlu tablolar üzerine nasıl ve ne tür index oluşturacağımızdan biraz bahsetmek istiyorum. Partitionlı tablolar gibi, partition yapılmış indexlerde yönetilebilirlik, kullanılabilirlik, performans ve ölçeklenebilirlik açısından geliştirici bir etkiye sahiptir.

İndexleri ya partitiondan bağımsız olarak (global indexler) oluşturabilir veya atomatik olarak sadece partitionlu alanlar üzerinde (local indexler) indexler oluşturabilirsiniz. Genel kullanım mantığına baktığımızda eğer OLTP sistemler üzerinde çalışıyorsanız yoğunlukla global index, eğer datawarehouse sistemler üzerinde çalışıyor iseniz local indexler yoğunlukla kullanılmaktadır. Ancak yönetimi bakımından eğer yapabiliyorsanız OLTP sistemlerde de local indexleri kullanabilirsiniz.

Global index, local index diye bir takım index türlerinden bahsettik. Buradaki bir diğer önemli soru şu aslında; BU index türlerinden hangisini kullanacağıma nasıl karar vermeliyim. Bu konudada oracle’ ın bir takım önerileri var;

  • Eğer tablo partitionladığınız kolonlardan biri, index atacağınız kolonlardan biri ise local index kullanabilirsiniz,
  • Index atacağınız kolon unique index olacaksa ve tablo partitionladığınız kolonlardan biri değilse global index kullanabilirsiniz,
  • Indexi oluşturmanızdaki sizin için birinci öncelik yönetilebilirliği ise local index kullanmalısınız,
  • Eğer OLTP sistem üzerinde bu çalışmayı yapıyor iseniz ve sorgunuzun responce süresi sizin için kritik ise global index, eğer Datawarehouse sistemi üzerinde bu çalışmayı yapıyor iseniz ve kullanıcılar daha çok sorgunun çıktısı ile ilgileniyor ise local index kullanabilirsiniz.

Local Partition Index

Partition indexler arasında yönetim en kolay olan indexler local partition indexlerdir. Yukarıda belirttiğimiz üzere daha çok dataware house sistemlerde kullanılmaktadır. Local index’ in her bir partitionı table’ ın partitioning’ I ile tam bir bütünlük içerisindedir. Bu fonksiyonilite oracle tarafından atomatik olarak index partitionların table partitionları ile senkronize olmasını sağlar, her bir table –index partitionı burada birbirinden bağımsız olarak düşünülmektedir. Yapılan her bir işlem sonucunda sadece ilgili index partition kısmı etkilenir.

Local indexlere yeni bir partition ekleyemezsiniz. Local indexe yeni bir partition eklemek için, tabloya yeni bir partition eklenmesi gerekmektedir. Aynı mantıkla baktığımızda local index’ den bir partitionını drop edemezsiniz. Ancak table partitionlarından birini drop ettiğinizde local index’ e ait index de drop edilmiş olur.

Local partition indexler aşağıdaki grafikdende anlaşılacağı üzere table partitioning yapısı üzerine kurulmaktadır.

Local Prefixed Indexes

Tablo üzerindeki partition yapılmış kolon üzerinde oluşturulursa PREFIXED index olur.

CREATE INDEX invoices_idx ON invoices (invoice_date) LOCAL;

CREATE INDEX invoices_idx ON invoices (invoice_date) LOCAL
 (PARTITION invoices_q1 TABLESPACE users,
  PARTITION invoices_q2 TABLESPACE users,
  PARTITION invoices_q3 TABLESPACE users,
  PARTITION invoices_q4 TABLESPACE users); 

Local Nonprefixed Indexes

Tablo üzerindeki partition yapılmış kolon üzerinde oluşturulmassa NONPREFIXED index olur.

CREATE INDEX invoices_idx ON invoices (invoice_no) LOCAL
 (PARTITION invoices_q1 TABLESPACE users,
  PARTITION invoices_q2 TABLESPACE users,
  PARTITION invoices_q3 TABLESPACE users,
  PARTITION invoices_q4 TABLESPACE users);

Global Partitioned Indexes

Tablodakinden farklı bir partition key’i veya yapısı kullanılarak oluşturulan index tipidir. Range veya Hash partition yöntemi ile oluşturulabilirler. Tablounun kendisi ay alanına göre partitionlanmış olup 12 adet partition’dan oluşurken, index range partitioning ile oluşturulmuş ve çok fazla sayıda partitiona sahip olabilir. Daha çok OLTP tipinde çalışan veritabanlarında kullanılır.

  • Global Range Partition Index
  • Global Hash Partition Index

Global Range Partition Index

Global range partitioned index, partitioning düzeyinin(degree) ve partitioning keyin, tablonun partitioning yönteminden bağımsız olması nedeniyle esnektir.

Global indexin en son partitionı Maxvalue ile bağlı olmalıdır. Bu şekilde tablodaki tüm değerlerin index içerisinde değerlendirimesini sağlanmış olur. Global prefixed index unique veya non unique olabilir.

Global range partition’ a sonradan partition ekleyemezsiniz, çünkü son partition zaten maxvalue ile tüm datayı kapsamaktadır. En sona yeni bir partition eklemek isterseniz ALTER INDEX SPLIT PARTITION komutunu kullanabilirsiniz. Global index partition boş ise yani o partitioning’ e hiçbir data girmemişse, ilgili partitionı ALTER INDEX DROP PARTITION komutunu kullanarak drop edebilirsiniz. Burada önemli olan bir diğer nokta eğer global index parition data içeriyorsa ve bu partitionı drop ettiyseniz, en son partition unusable olacaktır. Global indexlerde son partition drop edilemez.

CREATE INDEX invoices_idx ON invoices (invoice_date)
GLOBAL PARTITION BY RANGE (invoice_date)
 (PARTITION invoices_q1 VALUES LESS THAN (TO_DATE('01/04/2001', 'DD/MM/YYYY')) TABLESPACE users,
  PARTITION invoices_q2 VALUES LESS THAN (TO_DATE('01/07/2001', 'DD/MM/YYYY')) TABLESPACE users,
  PARTITION invoices_q3 VALUES LESS THAN (TO_DATE('01/09/2001', 'DD/MM/YYYY')) TABLESPACE users,
  PARTITION invoices_q4 VALUES LESS THAN (MAXVALUE) TABLESPACE users);

Global Hash Partition Index

Global hash partition indexler, index’ in tek bir noktada büyümesi durumunda, performans artırıcı bir etkisi bulunmaktadır.

Global Nonpartitioned Indexes

Partition’sız bir tablo üzerindeki index tanımı gibi olan partition yapısına sahip olmayan indextir. OLTP veritabanlarında daha çok PK veya unique değerleri temin etmek amacı ile kullanılan indextir.

Partitioning Availability, Manageability ve Performance

Partition Pruning

Partition pruning, veri ambarları için önemli bir performans özelliğidir. Partition pruning, optimizer, access list listesini oluştururken gereksiz partitionları ortadan kaldırmak için SQL sorgularındaki FROM ve WHERE yan tümcelerini analiz eder. Bu işlevsellik, Oracle Database’in yalnızca SQL deyimi ile ilgili partitionlarda işlem gerçekleştirmesini sağlar. Yani büyük bir segmenti küçük parçalar bölüp sorgulama… Tabloyu partition adlı kümelere bölüp, tüm kayıtlara bakmak yerine ilgilendiğimiz setleri sorgulama yöntemi. Burada dikkat edilmesi gereken, Oracle’ın sorguya bakarak ilgili partitionları çıkartabilecek biçimde bir sorgu yazmaktır.

Partition pruning, diskten alınan veri miktarını önemli ölçüde azaltır ve işlem süresini kısaltır, böylece sorgu performansını artırır ve kaynak kullanımını optimize eder. İndexi ve tabloyu farklı sütunlarda partitionlarsanız, partition pruning, temel tablodaki partitionlar ortadan kaldırılamadığında bile index partitionlarını elimine eder.

SQL ifadesine bağlı olarak, Oracle Database statik veya dinamik pruning kullanabilir. Statik pruning, derleme sırasında önceden erişilen partitionlar hakkında bilgi ile birlikte gerçekleşir. Dinamik pruning, çalışma zamanında gerçekleşir; bu, bir sorgu tarafından erişilecek kesin partitionların önceden bilinmediği anlamına gelir. Statik pruning için örnek bir senaryo, partition key sütunundaki sabit değişmeze sahip bir WHERE koşulu içeren bir SQL ifadesidir. Dinamik budama örneği, WHERE koşulundaki operatörlerin veya functionların kullanılmasıdır. Partition pruning, pruning gerçekleştiği nesnelerin istatistiklerini etkiler ve aynı zamanda bir ifadenin yürütme planını da etkiler.

Partition-Wise Joins

Tablo joinlerken, tablolardan en az birisi join edilen alan üzerinde partition’lu ise bu yöntem ile performans artışı sağlanabilir. Partition-wise join, büyük join işlemini küçük joinlere böler.

Index Partitioning

Partitioning indexes ile ilgili kurllar tablodakine bernzerdir.

  • Cluster indexler partition yapılamaz,
  • Cluster tablolar üzerine tanımlanacak olan index partition yapılamaz,
  • Partition tablo üzerine, partition veya nonpartition index tanımlanabilir,
  • Nonpartition tablo üzerine , partition veya nonpartition index tanımlanabilir,
  • Bitmap indexler, nonpartition tablolar üzerine partitionlı olarak tanımlanamazlar.
  • Bitmap indexler, partitionlı tablolar üzerine local index olarak tanımlanır.

Partitioned Table and Indexler hakkında Bilgileri Görüntüleme

  • DBA_PART_TABLES : Veritabanındaki tüm partitionlanmış tabloların partitioning bilgilerini görüntüler.
  • DBA_TAB_PARTITIONS : Partition düzeyinde partition bilgilerini, partition depolama parametrelerini ve DBMS_STATS paketi veya ANALYZE deyimi tarafından oluşturulan partition istatistiklerini görüntüleyin.
  • DBA_TAB_SUBPARTITIONS : Subpartition düzeyinde partition bilgilerini, sub partition depolama parametrelerini ve DBMS_STATS paketi veya ANALYZE deyimi tarafından oluşturulan alt bölüm istatistiklerini görüntüleyin.
  • DBA_PART_KEY_COLUMNS : Partitionlanmış tablolar için partition key sütunlarını görüntüler.
  • DBA_SUBPART_KEY_COLUMNS : Subpartitionlanmış tablolar için partition key sütunlarını görüntüler.
  • DBA_PART_COL_STATISTICS
  • DBA_SUBPART_COL_STATISTICS
  • DBA_PART_HISTOGRAMS
  • DBA_PART_INDEXES : Veritabanındaki tüm partitionlanmış indexlerin partitioning bilgilerini görüntüler
  • DBA_IND_PARTITIONS
  • DBA_IND_SUBPARTITIONS
  • DBA_SUBPARTITION_TEMPLATES

Kaynaklar;
https://docs.oracle.com/database/121/VLDBG/GUID-FBA59FA7-7F42-4039-96D1-ACEC71A07DD5.htm#VLDBG001
https://hakkioktay.wordpress.com/2007/03/15/partitioning-kavrami-ve-table-partitioning/
http://www.kamilturkyilmaz.com/2012/04/28/oracle-partitioning/
https://mehmetsalihdeveci.net/2014/06/06/oracle-partitioning/

Mustafa Bektaş Tepe
İyi Çalışmalar

Loading