Sql & Veritabanı İle Uygulamalar İçin Veri Tablosu Partitioning Nasıl Yapılır?

Sql & Veritabanı İle Uygulamalar İçin Veri Tablosu Partitioning Nasıl Yapılır?
Sql & Veritabanı İle Uygulamalar İçin Veri Tablosu Partitioning Nasıl Yapılır?

Gereksinimler ve Ön Hazırlık

Partitioning uygulamalarına başlamadan önce, veri tabanı sunucunuzun bu özelliği desteklediğinden emin olmalısınız. 2026 yılı standartlarına göre, PostgreSQL 14+ veya MySQL 8.0+ sürümlerini kullanmanız önerilir. Eski sürümlerde partitioning desteği sınırlı olabilir veya manuel tetikleyiciler (triggers) gerektirebilir, bu da performans kaybına yol açar.

  • Veri Tabanı Sunucusu: PostgreSQL 16 veya MySQL 8.4 LTS tercih edilmelidir.
  • Yetkilendirme: Tablo oluşturma ve değiştirme (ALTER) yetkisine sahip bir kullanıcı hesabı.
  • Analiz Araçları: Sorgu performansını ölçmek için EXPLAIN ANALYZE komutuna hakimiyet.
  • Disk Kapasitesi: Bölümleme sırasında geçici olarak iki katı veri alanı gerekebilir.

Partitioning Stratejileri ve Yöntemleri

Veri tablosu bölümleme, verinin mantıksal olarak nasıl parçalanacağına bağlı olarak üç ana yönteme ayrılır. Doğru yöntemi seçmek, sorgu performansınızı doğrudan etkiler.

Yöntem Kullanım Senaryosu Avantajı
Range Partitioning Tarih bazlı loglar, siparişler Zaman aralığı sorgularında çok hızlıdır.
List Partitioning Bölge, kategori veya durum kodları Belirli gruplara göre filtreleme için idealdir.
Hash Partitioning Kullanıcı ID, ürün ID Veriyi bölümler arasında eşit dağıtır.

Adım Adım Range Partitioning Uygulaması

Range partitioning, genellikle zaman damgası (timestamp) içeren tablolarda kullanılır. Örneğin, 2026 yılına ait satış verilerini aylara bölmek, eski verilerin arşivlenmesini veya silinmesini (data retention) kolaylaştırır.

Aşağıdaki kod örneği, PostgreSQL üzerinde tarih bazlı bir bölümleme tablosu oluşturmayı gösterir:

CREATE TABLE satislar (
    id SERIAL,
    tutar DECIMAL(10,2),
    satis_tarihi TIMESTAMP NOT NULL
) PARTITION BY RANGE (satis_tarihi);

CREATE TABLE satislar_2026_ocak PARTITION OF satislar
    FOR VALUES FROM ('2026-01-01') TO ('2026-02-01');

CREATE TABLE satislar_2026_subat PARTITION OF satislar
    FOR VALUES FROM ('2026-02-01') TO ('2026-03-01');

Bu yapı sayesinde, 2026 Ocak ayına ait bir sorgu çalıştırdığınızda, veri tabanı motoru sadece satislar_2026_ocak tablosuna bakar. Bu, "partition pruning" (bölüm budama) olarak adlandırılır ve sorgu süresini ciddi oranda kısaltır.

List Partitioning ile Veri Gruplama

Eğer verileriniz belirli kategorilere veya coğrafi bölgelere ayrılıyorsa, List Partitioning en iyi tercihtir. Örneğin, bir e-ticaret sisteminde "TR", "EU", "US" gibi bölge kodlarına göre verileri ayırabilirsiniz.

CREATE TABLE musteriler (
    id INT,
    isim VARCHAR(100),
    bolge_kodu VARCHAR(2)
) PARTITION BY LIST (bolge_kodu);

CREATE TABLE musteriler_tr PARTITION OF musteriler FOR VALUES IN ('TR');
CREATE TABLE musteriler_eu PARTITION OF musteriler FOR VALUES IN ('EU', 'DE', 'FR');

Bu yöntem, özellikle bölgesel veri gizliliği (KVKK/GDPR) gereksinimleri olan uygulamalarda, belirli bir bölgenin verisini fiziksel olarak izole etmek için kullanılır.

Hash Partitioning ile Yük Dengeleme

Hash partitioning, veriyi belirli bir sütunun hash değerine göre bölümlere dağıtır. Bu yöntem, verinin bölümler arasında dengeli dağılmasını sağlar ve tek bir bölümün aşırı büyümesini (hotspot) engeller.

CREATE TABLE kullanici_loglari (
    log_id INT,
    mesaj TEXT
) PARTITION BY HASH (log_id);

CREATE TABLE log_part_1 PARTITION OF kullanici_loglari FOR VALUES WITH (MODULUS 4, REMAINDER 0);
CREATE TABLE log_part_2 PARTITION OF kullanici_loglari FOR VALUES WITH (MODULUS 4, REMAINDER 1);

Burada MODULUS değeri, verinin kaç parçaya bölüneceğini temsil eder. REMAINDER ise ilgili bölümün hangi hash artığına sahip olduğunu belirler.

Partitioning Yönetimi ve Bakım İpuçları

Bölümlenmiş tabloları yönetirken en sık yapılan hata, bölümleri oluşturmayı unutmaktır. Özellikle tarih bazlı tablolarda, her ayın başında otomatik olarak yeni partition oluşturacak bir "cron job" veya veri tabanı prosedürü tanımlamalısınız.

Kritik Uyarı: Partitioning yaparken indeksleme stratejinizi gözden geçirin. Global indeksler yerine yerel indeksler (local indexes) kullanmak, bakım maliyetini düşürür ve veri kaybı riskini azaltır. Ayrıca, üretim ortamında (production) büyük bir tabloyu aniden bölümlere ayırmak sistem kilitlemelerine (lock) yol açabilir; bu işlemi bakım saatlerinde yapın.

Aşağıdaki sorgu ile mevcut bölümlerinizi ve boyutlarını kontrol edebilirsiniz:

SELECT relname AS tablo_adi, pg_size_pretty(pg_total_relation_size(relid)) AS boyut
FROM pg_catalog.pg_statio_user_tables
WHERE relname LIKE 'satislar_%';

Sıkça Sorulan Sorular

Partitioning her zaman performans artışı sağlar mı?

Hayır. Küçük veri setlerinde partitioning ek bir karmaşıklık getirir. Sadece milyonlarca satırın olduğu ve sorguların genellikle belirli bir aralıkta (tarih veya ID) yapıldığı durumlarda performans artışı sağlar.

Partitioning ve Sharding arasındaki fark nedir?

Partitioning, tek bir veri tabanı sunucusu üzerinde veriyi bölmektir. Sharding ise veriyi farklı sunuculara dağıtarak yatay ölçeklendirme yapmaktır.

Bölümlenmiş tabloda Primary Key nasıl olmalı?

Primary key, partitioning sütununu mutlaka içermelidir. Aksi takdirde, veri tabanı motoru tekil (unique) kaydı doğrulamak için tüm bölümleri taramak zorunda kalır.

Eski verileri nasıl temizlerim?

Partitioning ile eski verileri silmek çok kolaydır: Sadece ilgili partition tablosunu DROP TABLE komutu ile silmek, milyonlarca satırı DELETE ile silmekten çok daha hızlı ve güvenlidir.

İndeksler bölümlenmiş tabloda nasıl çalışır?

İndeksler her bir bölüm (partition) için ayrı ayrı oluşturulur. Sorgu, sadece ilgili bölümü hedeflediğinde o bölümün indeksi kullanılır.

Sorumluluk Reddi: Bu makaledeki kod örnekleri genel eğitim amaçlıdır. Veri tabanı şemalarınızı üretim ortamına taşımadan önce mutlaka bir geliştirme ortamında (staging) test edin. Yanlış yapılandırılmış bölümlendirme veri kaybına veya erişim sorunlarına yol açabilir.

Partitioning Stratejilerinde İleri Seviye Performans İzleme

Bölümlenmiş bir tabloda performansın beklendiği gibi seyredip seyretmediğini anlamak için sadece EXPLAIN çıktısına bakmak yeterli değildir. Veri tabanı motorunun hangi bölümleri (partition) taradığını ve ne kadar I/O harcadığını izlemek, darboğazları tespit etmek için kritiktir. PostgreSQL gibi sistemlerde pg_stat_user_tables ve pg_stat_user_indexes görünümleri üzerinden bölümlere özel istatistikleri takip edebilirsiniz.

Aşağıdaki sorgu, bölümlenmiş tablonuzdaki her bir parçanın ne kadar veri okuduğunu ve indeks kullanım oranlarını analiz etmenize yardımcı olur:

SELECT 
    relname AS partition_name, 
    seq_scan, 
    idx_scan, 
    n_live_tup, 
    n_dead_tup 
FROM pg_stat_user_tables 
WHERE relname LIKE 'orders_partition_%' 
ORDER BY idx_scan DESC;

Bu veriler, özellikle "hot data" (sık erişilen veri) ile "cold data" (arşivlenmiş veri) arasındaki dengesizliği görmenizi sağlar. Eğer belirli bir bölüm üzerinde sürekli seq_scan (tam tablo taraması) görüyorsanız, bu durum o bölümdeki indekslerin eksik olduğunu veya sorgu parametrelerinizin bölümlendirme anahtarı (partition key) ile eşleşmediğini gösterir.

Bölümlenmiş Tablolarda Veri Taşıma ve Deployment Senaryoları

Canlı bir sistemde mevcut devasa bir tabloyu bölümlenmiş yapıya geçirmek, veri kaybı riski taşıyan hassas bir operasyondur. "Blue-Green" deployment veya "Logical Replication" yöntemleri bu süreci sıfır kesinti (zero-downtime) ile yönetmenizi sağlar. En güvenli yöntem, yeni bir bölümlenmiş tablo oluşturup verileri parça parça aktarmaktır.

Aşağıdaki örnek, mevcut bir tablodan bölümlenmiş tabloya veri aktarımı sırasında kullanılabilecek güvenli bir döngü mantığını göstermektedir:

-- Adım 1: Yeni bölümlenmiş tabloyu oluşturun
-- Adım 2: Verileri batch (yığın) halinde aktarın
DO $$
DECLARE
    start_date DATE := '2023-01-01';
    end_date DATE := '2023-01-31';
BEGIN
    LOOP
        INSERT INTO orders_partitioned
        SELECT * FROM old_orders 
        WHERE created_at >= start_date AND created_at < start_date + INTERVAL '1 month';
        
        EXIT WHEN start_date >= '2024-01-01';
        start_date := start_date + INTERVAL '1 month';
    END LOOP;
END $$;

Deployment İpuçları:

  • Batch Boyutu: Veri aktarımı sırasında işlem günlüğü (transaction log) şişmesini önlemek için verileri 10.000'lik veya 50.000'lik paketler halinde aktarın.
  • İndeksleme Stratejisi: Veri aktarımı tamamlanmadan indeks oluşturmayın. Büyük veriyi aktardıktan sonra indeksleri oluşturmak, her satır eklenirken indeks güncelleme maliyetinden sizi kurtararak süreci %40'a kadar hızlandırır.
  • Constraint Kontrolü: Bölümlenmiş tabloya geçiş yaparken CHECK kısıtlamalarının doğru tanımlandığından emin olun; aksi takdirde "Partition Pruning" mekanizması çalışmayacak ve sorgularınız tüm bölümleri tarayacaktır.
Dikkat: Bölümlenmiş tablolarda "Foreign Key" kısıtlamaları genellikle sadece ana tablo (parent) üzerinden tanımlanabilir. Alt tablolara (child) doğrudan yabancı anahtar referansı vermek, veri tabanı motoruna bağlı olarak kısıtlı olabilir veya desteklenmeyebilir. Tasarımınızı yaparken bu kısıtlamayı göz önünde bulundurun.

Sonuç

Veri tabanı partitioning, büyük ölçekli uygulamaların sürdürülebilirliği için vazgeçilmez bir tekniktir. Doğru stratejiyi seçerek (Range, List veya Hash), sorgu sürelerini düşürebilir ve veri tabanı bakım süreçlerinizi otomatize edebilirsiniz. Bir sonraki adım olarak, mevcut projenizdeki en büyük tabloyu belirleyin ve EXPLAIN ANALYZE komutu ile yavaşlayan sorgularınızı analiz ederek uygun partitioning yöntemini projenize uygulamaya başlayın.

Bu yazıya tepkinizi paylaşın:
Selin Yılmaz

Zaman yönetimi ve üretkenlik ipuçları üzerine uzmanlaşmış bir içerik yazarıyım. Günlük yaşamı kolaylaştıran etkili yöntemleri okuyucularla paylaşarak hayat kalitesini artırmayı hedefliyorum.

Yorumlar (0)

Yorum Yaz