Merhaba arkadaşlar, bugün sizlere özellikle log tabloları veya zaman bazlı çok büyük veri içeren tablolarda performans ve yönetilebilirlik için hayat kurtaran bir konudan bahsedeceğim: Partitioning (Parçalara Ayırma). Benim sunucularda genelde kullandığım bu yöntem, bir tabloyu mantıksal olarak bölümlere ayırırken, uygulama için tek bir tablo gibi görünmesini sağlar. Bu sayede eski verileri silmek veya yedek almak çok daha hızlı ve risksiz hale gelir.
Partitioning Nedir ve Ne Zaman Gerekir?
Partitioning, tek bir tablonun verilerini, belirlediğiniz bir kurala göre (genellikle tarih) fiziksel olarak farklı bölümlere ayırma işlemidir. Örneğin, her ayın verisini ayrı bir partition'da tutabilirsiniz.
Şu durumlarda mutlaka düşünmelisiniz:
- Tablonuz birkaç yüz GB veya TB boyutuna ulaştıysa.
- Sık sık "DELETE FROM log_table WHERE created_at < '2022-01-01'" gibi büyük silme işlemleri yapıyorsanız. Bu silmeler tabloyu kilitler ve disk I/O'yu çok yorar.
- Sorgularınızın çoğu son 1 ay, 3 ay gibi belirli bir zaman aralığındaki verileri tarıyorsa. Partitioning ile sadece ilgili bölüm taranır, bu da sorgu süresini dramatik şekilde kısaltır.
Range Partitioning ile Pratik Örnek
En yaygın kullanılan tür "RANGE" partitioning'dir. Hemen basit bir log tablosu üzerinden adım adım gidelim. Diyelim ki `server_logs` adında bir tablonuz var ve verileri aylık olarak bölmek istiyorsunuz.
İlk olarak, partition key olarak kullanacağımız alanın (bu örnekte `log_date`) bir index üzerinde olması veya primary key'in bir parçası olması gerekir. Şu ayara çok dikkat etmelisiniz.
Önce tablomuzu partition'lu olarak oluşturalım:
Bu komut, tabloyu `log_date` sütununun YIL ve AY'ına göre böler. `p_202301` partition'ı 2023-Ocak ayına ait tüm verileri tutacaktır. `p_future` ise tanımlanmamış tarihler için bir çekince görevi görür.
Dikkat Edilmesi Gerekenler
Partitioning sihirli bir değnek değil, yanlış kullanılırsa performansı düşürebilir.
- Partition Key Seçimi: Sorgularınızın WHERE koşulunda sık kullandığınız sütunu seçin. Tarih en ideal adaydır.
- Primary Key Kısıtı: Partition key'iniz, eğer tabloda PRIMARY KEY varsa, mutlaka onun bir parçası OLMALIDIR. Yukarıdaki örnekte olduğu gibi: `PRIMARY KEY (id, log_date)`. Bunu atlarsanız hata alırsınız.
- Çok Fazla Partition: Binlerce partition oluşturmak, dosya sistemi ve metadata yönetimi açısından yük getirebilir. Mantıklı bir sayıda tutun (örneğin, aylık 36 partition = 3 yıl).
- Yedekleme: Tek bir partition'ı yedeklemek veya farklı bir diske taşımak çok kolaydır. Örneğin, `ALTER TABLE server_logs ARCHIVE PARTITION p_202301;` gibi komutlarla eski verileri arşivleyebilirsiniz.
Mevcut Bir Tabloyu Partition'a Ayırma
Elimizde zaten dolu bir `server_logs` tablosu varsa, onu dönüştürmek biraz daha plan gerektirir. En güvenli yöntem yeni bir partition'lu tablo oluşturup veriyi oraya taşımaktır. Ancak dikkatli bir ALTER TABLE komutu ile de yapılabilir. İşlemin uzun sürebileceğini ve tabloyu kilitleyebileceğini unutmayın. Mümkünse bakım penceresinde yapın.
Avantajları Özetle
- Performans: Sorgular sadece ilgili partition'ı tarar (Partition Pruning).
- Yönetim Kolaylığı: Eski bir aya ait veriyi silmek için `ALTER TABLE server_logs DROP PARTITION p_202201;` komutu yeterli. Bu, saniyeler içinde, DELETE ile haftalar sürebilecek bir I/O yükü yaratmadan tamamlanır.
- Arşivleme: Tek bir partition'ı kolayca dışa aktarıp, daha ucuz depolama alanında saklayabilirsiniz.
- Bakım: `OPTIMIZE TABLE`, `ANALYZE TABLE` gibi işlemleri partition bazında çalıştırabilirsiniz, bu da süreyi kısaltır.
Umarım bu temel bilgiler işinize yarar. Ben zaman serisi verisi olan hemen hemen tüm tablolarda bu yapıyı kullanıyorum. Özellikle log tutan sistemlerde disk alanı ve performans yönetimi artık çok daha kolay.
Siz bu konfigürasyonu kendi sunucularınızda nasıl yapıyorsunuz? Farklı partitioning türleri (LIST, HASH) kullanan var mı? Deneyimlerinizi paylaşın veya takıldığınız bir nokta olursa aşağıya yazın, yardımcı olmaya çalışalım.
Partitioning, tek bir tablonun verilerini, belirlediğiniz bir kurala göre (genellikle tarih) fiziksel olarak farklı bölümlere ayırma işlemidir. Örneğin, her ayın verisini ayrı bir partition'da tutabilirsiniz.
Şu durumlarda mutlaka düşünmelisiniz:
- Tablonuz birkaç yüz GB veya TB boyutuna ulaştıysa.
- Sık sık "DELETE FROM log_table WHERE created_at < '2022-01-01'" gibi büyük silme işlemleri yapıyorsanız. Bu silmeler tabloyu kilitler ve disk I/O'yu çok yorar.
- Sorgularınızın çoğu son 1 ay, 3 ay gibi belirli bir zaman aralığındaki verileri tarıyorsa. Partitioning ile sadece ilgili bölüm taranır, bu da sorgu süresini dramatik şekilde kısaltır.
En yaygın kullanılan tür "RANGE" partitioning'dir. Hemen basit bir log tablosu üzerinden adım adım gidelim. Diyelim ki `server_logs` adında bir tablonuz var ve verileri aylık olarak bölmek istiyorsunuz.
İlk olarak, partition key olarak kullanacağımız alanın (bu örnekte `log_date`) bir index üzerinde olması veya primary key'in bir parçası olması gerekir. Şu ayara çok dikkat etmelisiniz.
Önce tablomuzu partition'lu olarak oluşturalım:
SQL:
CREATE TABLE server_logs (
id INT NOT NULL AUTO_INCREMENT,
log_date DATE NOT NULL,
message TEXT,
severity VARCHAR(20),
PRIMARY KEY (id, log_date)
)
PARTITION BY RANGE (YEAR(log_date) 100 + MONTH(log_date)) (
PARTITION p_202301 VALUES LESS THAN (202302),
PARTITION p_202302 VALUES LESS THAN (202303),
PARTITION p_202303 VALUES LESS THAN (202304),
PARTITION p_future VALUES LESS THAN MAXVALUE
);
Bu komut, tabloyu `log_date` sütununun YIL ve AY'ına göre böler. `p_202301` partition'ı 2023-Ocak ayına ait tüm verileri tutacaktır. `p_future` ise tanımlanmamış tarihler için bir çekince görevi görür.
Partitioning sihirli bir değnek değil, yanlış kullanılırsa performansı düşürebilir.
- Partition Key Seçimi: Sorgularınızın WHERE koşulunda sık kullandığınız sütunu seçin. Tarih en ideal adaydır.
- Primary Key Kısıtı: Partition key'iniz, eğer tabloda PRIMARY KEY varsa, mutlaka onun bir parçası OLMALIDIR. Yukarıdaki örnekte olduğu gibi: `PRIMARY KEY (id, log_date)`. Bunu atlarsanız hata alırsınız.
- Çok Fazla Partition: Binlerce partition oluşturmak, dosya sistemi ve metadata yönetimi açısından yük getirebilir. Mantıklı bir sayıda tutun (örneğin, aylık 36 partition = 3 yıl).
- Yedekleme: Tek bir partition'ı yedeklemek veya farklı bir diske taşımak çok kolaydır. Örneğin, `ALTER TABLE server_logs ARCHIVE PARTITION p_202301;` gibi komutlarla eski verileri arşivleyebilirsiniz.
Elimizde zaten dolu bir `server_logs` tablosu varsa, onu dönüştürmek biraz daha plan gerektirir. En güvenli yöntem yeni bir partition'lu tablo oluşturup veriyi oraya taşımaktır. Ancak dikkatli bir ALTER TABLE komutu ile de yapılabilir. İşlemin uzun sürebileceğini ve tabloyu kilitleyebileceğini unutmayın. Mümkünse bakım penceresinde yapın.
SQL:
-- Büyük tablolarda bu işlem ÇOK UZUN sürebilir. Öncesinde mutlaka yedek alın!
ALTER TABLE server_logs
PARTITION BY RANGE (YEAR(log_date) 100 + MONTH(log_date)) (
PARTITION p_202201 VALUES LESS THAN (202202),
PARTITION p_202202 VALUES LESS THAN (202203),
-- ... Diğer aylar ...
PARTITION p_future VALUES LESS THAN MAXVALUE
);
- Performans: Sorgular sadece ilgili partition'ı tarar (Partition Pruning).
- Yönetim Kolaylığı: Eski bir aya ait veriyi silmek için `ALTER TABLE server_logs DROP PARTITION p_202201;` komutu yeterli. Bu, saniyeler içinde, DELETE ile haftalar sürebilecek bir I/O yükü yaratmadan tamamlanır.
- Arşivleme: Tek bir partition'ı kolayca dışa aktarıp, daha ucuz depolama alanında saklayabilirsiniz.
- Bakım: `OPTIMIZE TABLE`, `ANALYZE TABLE` gibi işlemleri partition bazında çalıştırabilirsiniz, bu da süreyi kısaltır.
Umarım bu temel bilgiler işinize yarar. Ben zaman serisi verisi olan hemen hemen tüm tablolarda bu yapıyı kullanıyorum. Özellikle log tutan sistemlerde disk alanı ve performans yönetimi artık çok daha kolay.
Siz bu konfigürasyonu kendi sunucularınızda nasıl yapıyorsunuz? Farklı partitioning türleri (LIST, HASH) kullanan var mı? Deneyimlerinizi paylaşın veya takıldığınız bir nokta olursa aşağıya yazın, yardımcı olmaya çalışalım.