Merhaba arkadaşlar, bugün sizlere özellikle loglama, metrik kaydı veya sensör verisi gibi sürekli büyüyen devasa tabloları yönetmek için benim de sıkça başvurduğum bir yöntemi anlatacağım: Partitioning (Bölümleme). Bu yöntemle, tek bir tablo içindeki verileri, örneğin aylara göre, mantıksal parçalara ayırabiliriz. Bu sayede hem eski verileri silmek/arşivlemek çok kolaylaşır, hem de sorgu performansı artar. Özellikle "log tablosu 100 GB'ı geçti, sorgular çok yavaşladı" diyenler için biçilmiş kaftan.
Neden Partitioning Kullanmalıyız?
Partitioning'in en büyük avantajı, veri yönetimini ve performansı iyileştirmesidir. Şöyle düşünün: 5 yıllık log veriniz var. "2022 Ocak ayındaki hataları getir" dediğinizde, veritabanı tüm 5 yıllık veriyi taramak yerine, sadece ilgili aya ait bölümü (partition) tarar. Bu da disk I/O ve bellek kullanımını ciddi oranda düşürür. Ayrıca, 2020 yılına ait tüm verileri silmek istediğinizde, tek bir satırı silmek yerine, tüm 2020 bölümünü (DROP PARTITION) saniyeler içinde silebilirsiniz. Bu işlem, klasik DELETE komutuna göre çok daha hızlıdır ve tabloyu kilitlemez.
Örnek Tablomuzu Oluşturalım
İşe, bölümleyeceğimiz örnek bir log tablosu oluşturarak başlayalım. Diyelim ki `uygulama_loglari` adında bir tablomuz var.
Burada çok önemli bir nokta var: Partitioning yapabilmek için, bölümleme anahtarımız olan `olusturulma_tarihi` sütununun, birincil anahtarın (PRIMARY KEY) bir parçası olması gerekir. Bu yüzden `PRIMARY KEY (id, olusturulma_tarihi)` şeklinde bileşik bir anahtar tanımladık.
Tablomuzu Aylık Partition'lara Bölelim
Şimdi geldik işin en can alıcı noktasına. Mevcut tabloyu, `olusturulma_tarihi` sütununa göre ve her ay için ayrı bir bölüm oluşturacak şekilde yeniden yapılandıracağız. Ben genelde 1 yıllık bir geçmiş + 1-2 ay ileriye dönük boş partition'lar oluşturmayı tercih ederim.
Burada ne yaptık?
- PARTITION BY RANGE COLUMNS(olusturulma_tarihi): Bölümlemeyi bu sütuna göre yap dedik.
- PARTITION p_2023_01 VALUES LESS THAN ('2023-02-01'): `p_2023_01` adlı bölüm, Şubat 2023'ten önceki (yani Ocak 2023'e ait) tüm kayıtları tutacak.
- PARTITION p_2023_oncesi: 2023'ten önceki tüm eski kayıtların toplandığı bir bölüm. Temizlik için hazır.
- PARTITION p_gelecek VALUES LESS THAN MAXVALUE: Tanımladığımız tarih aralıklarının ötesindeki TÜM gelecek kayıtların gideceği bölüm. Bu olmazsa, tanımsız bir tarihten veri gelirse hata alırsınız.
Dikkat Edilmesi Gerekenler
1. ALTER TABLE işlemi büyük tablolarda UZUN sürebilir ve sunucu yükünü artırabilir. Bu işlemi bakım pencerenizde yapın.
2. İleride yeni bir ay başladığında (örneğin 2024 Ocak), yeni bir partition eklemeyi UNUTMAYIN! Aksi takdirde tüm yeni veriler `p_gelecek` bölümüne dolar ve amacınız bozulur.
3. Partition eklemek/silmek, tüm tabloyu yeniden yazmaktan çok daha hızlıdır. Eski bir ayı silmek için:
komutu yeterli. Saniyeler içinde biter.
Partition Yönetimi ve Bakımı
Partition'ların durumunu kontrol etmek ve yeni partition'lar eklemek çok önemli. İşte sık kullandığım komutlar:
Hangi partition'lar var, ne kadar veri tutuyorlar görelim:
2024 Ocak ayı için yeni bir partition ekleyelim:
Bu komut, `p_gelecek` bölümünü ikiye ayırır: 2024 Ocak ayı için yeni bir bölüm ve ondan sonrası için yeni bir `p_gelecek` bölümü.
Sonuç ve Performans Kazanımı
Bu yapıyı kurduktan sonra, aylık rapor sorgularınızın ne kadar hızlandığını göreceksiniz. Veri temizliği artık bir kabus olmaktan çıkacak. Benim yönettiğim birkaç yüksek trafikli uygulamanın log veritabanında bu yapıyı kullanıyorum ve hem disk kullanımı hem de backup/restore süreleri üzerinde inanılmaz olumlu etkileri oldu.
Siz bu tarz büyük tabloları yönetmek için hangi yöntemleri kullanıyorsunuz? Partitioning dışında farklı stratejileriniz var mı? Ya da bu konuda takıldığınız bir nokta olursa, aşağıya yazmaktan çekinmeyin. Hep birlikte tartışıp öğrenelim.
Partitioning'in en büyük avantajı, veri yönetimini ve performansı iyileştirmesidir. Şöyle düşünün: 5 yıllık log veriniz var. "2022 Ocak ayındaki hataları getir" dediğinizde, veritabanı tüm 5 yıllık veriyi taramak yerine, sadece ilgili aya ait bölümü (partition) tarar. Bu da disk I/O ve bellek kullanımını ciddi oranda düşürür. Ayrıca, 2020 yılına ait tüm verileri silmek istediğinizde, tek bir satırı silmek yerine, tüm 2020 bölümünü (DROP PARTITION) saniyeler içinde silebilirsiniz. Bu işlem, klasik DELETE komutuna göre çok daha hızlıdır ve tabloyu kilitlemez.
İşe, bölümleyeceğimiz örnek bir log tablosu oluşturarak başlayalım. Diyelim ki `uygulama_loglari` adında bir tablomuz var.
SQL:
CREATE TABLE uygulama_loglari (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
log_mesaji TEXT NOT NULL,
seviye ENUM('INFO', 'WARNING', 'ERROR') NOT NULL DEFAULT 'INFO',
kaynak VARCHAR(255),
olusturulma_tarihi DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id, olusturulma_tarihi)
) ENGINE=InnoDB;
Burada çok önemli bir nokta var: Partitioning yapabilmek için, bölümleme anahtarımız olan `olusturulma_tarihi` sütununun, birincil anahtarın (PRIMARY KEY) bir parçası olması gerekir. Bu yüzden `PRIMARY KEY (id, olusturulma_tarihi)` şeklinde bileşik bir anahtar tanımladık.
Şimdi geldik işin en can alıcı noktasına. Mevcut tabloyu, `olusturulma_tarihi` sütununa göre ve her ay için ayrı bir bölüm oluşturacak şekilde yeniden yapılandıracağız. Ben genelde 1 yıllık bir geçmiş + 1-2 ay ileriye dönük boş partition'lar oluşturmayı tercih ederim.
SQL:
ALTER TABLE uygulama_loglari
PARTITION BY RANGE COLUMNS(olusturulma_tarihi) (
PARTITION p_2023_oncesi VALUES LESS THAN ('2023-01-01'),
PARTITION p_2023_01 VALUES LESS THAN ('2023-02-01'),
PARTITION p_2023_02 VALUES LESS THAN ('2023-03-01'),
PARTITION p_2023_03 VALUES LESS THAN ('2023-04-01'),
PARTITION p_2023_04 VALUES LESS THAN ('2023-05-01'),
PARTITION p_2023_05 VALUES LESS THAN ('2023-06-01'),
PARTITION p_2023_06 VALUES LESS THAN ('2023-07-01'),
PARTITION p_2023_07 VALUES LESS THAN ('2023-08-01'),
PARTITION p_2023_08 VALUES LESS THAN ('2023-09-01'),
PARTITION p_2023_09 VALUES LESS THAN ('2023-10-01'),
PARTITION p_2023_10 VALUES LESS THAN ('2023-11-01'),
PARTITION p_2023_11 VALUES LESS THAN ('2023-12-01'),
PARTITION p_2023_12 VALUES LESS THAN ('2024-01-01'),
PARTITION p_gelecek VALUES LESS THAN MAXVALUE
);
Burada ne yaptık?
- PARTITION BY RANGE COLUMNS(olusturulma_tarihi): Bölümlemeyi bu sütuna göre yap dedik.
- PARTITION p_2023_01 VALUES LESS THAN ('2023-02-01'): `p_2023_01` adlı bölüm, Şubat 2023'ten önceki (yani Ocak 2023'e ait) tüm kayıtları tutacak.
- PARTITION p_2023_oncesi: 2023'ten önceki tüm eski kayıtların toplandığı bir bölüm. Temizlik için hazır.
- PARTITION p_gelecek VALUES LESS THAN MAXVALUE: Tanımladığımız tarih aralıklarının ötesindeki TÜM gelecek kayıtların gideceği bölüm. Bu olmazsa, tanımsız bir tarihten veri gelirse hata alırsınız.
1. ALTER TABLE işlemi büyük tablolarda UZUN sürebilir ve sunucu yükünü artırabilir. Bu işlemi bakım pencerenizde yapın.
2. İleride yeni bir ay başladığında (örneğin 2024 Ocak), yeni bir partition eklemeyi UNUTMAYIN! Aksi takdirde tüm yeni veriler `p_gelecek` bölümüne dolar ve amacınız bozulur.
3. Partition eklemek/silmek, tüm tabloyu yeniden yazmaktan çok daha hızlıdır. Eski bir ayı silmek için:
SQL:
ALTER TABLE uygulama_loglari DROP PARTITION p_2023_oncesi;
Partition'ların durumunu kontrol etmek ve yeni partition'lar eklemek çok önemli. İşte sık kullandığım komutlar:
Hangi partition'lar var, ne kadar veri tutuyorlar görelim:
SQL:
SELECT
PARTITION_NAME,
TABLE_ROWS,
DATA_LENGTH
FROM INFORMATION_SCHEMA.PARTITIONS
WHERE TABLE_NAME = 'uygulama_loglari';
2024 Ocak ayı için yeni bir partition ekleyelim:
SQL:
ALTER TABLE uygulama_loglari REORGANIZE PARTITION p_gelecek INTO (
PARTITION p_2024_01 VALUES LESS THAN ('2024-02-01'),
PARTITION p_gelecek VALUES LESS THAN MAXVALUE
);
Bu komut, `p_gelecek` bölümünü ikiye ayırır: 2024 Ocak ayı için yeni bir bölüm ve ondan sonrası için yeni bir `p_gelecek` bölümü.
Bu yapıyı kurduktan sonra, aylık rapor sorgularınızın ne kadar hızlandığını göreceksiniz. Veri temizliği artık bir kabus olmaktan çıkacak. Benim yönettiğim birkaç yüksek trafikli uygulamanın log veritabanında bu yapıyı kullanıyorum ve hem disk kullanımı hem de backup/restore süreleri üzerinde inanılmaz olumlu etkileri oldu.
Siz bu tarz büyük tabloları yönetmek için hangi yöntemleri kullanıyorsunuz? Partitioning dışında farklı stratejileriniz var mı? Ya da bu konuda takıldığınız bir nokta olursa, aşağıya yazmaktan çekinmeyin. Hep birlikte tartışıp öğrenelim.