Önceki yazımızda Kubernetes üzerinde iki ayrı kurulum (vanilla PostgreSQL ve TimescaleDB) yapıp az veriyle tablo + index boyutlarını kıyaslamıştık. Bu yazıda aynı environment üzerinde TimescaleDB'nin data retention (eski veriyi silme) yaklaşımını pratikte test ediyoruz.
Ortam
- Namespace: database
- TimescaleDB pod: timescaledb-single chart (master pod)
- StorageClass: local-path (tek node)
Komutlarda iki değişken kullanacağız: NS ve TSPOD.
NS=database
TSPOD="$(kubectl get pod -n $NS -l release=timescaledb,role=master -o jsonpath='{.items[0].metadata.name}')"
echo "TSPOD=$TSPOD"
Bu blok sonraki komutlarda kullanacağımız değişkenleri hazırlar.
Deney 1 - Manuel chunk droplama (drop_chunks)
Bu deneyde 48 saatlik veri bastık (5 dakikada bir), sonra 24 saatten eski chunk'ları manuel olarak dropladık.
1A) Kurulum ve veri basma
kubectl exec -n $NS -i $TSPOD -- psql -U postgres -v ON_ERROR_STOP=1 <<'SQL'
CREATE EXTENSION IF NOT EXISTS timescaledb;
CREATE SCHEMA IF NOT EXISTS lab;
DROP TABLE IF EXISTS lab.sensor_ret_manual;
CREATE TABLE lab.sensor_ret_manual (
time TIMESTAMPTZ NOT NULL,
device_id INT,
temperature DOUBLE PRECISION
);
SELECT create_hypertable(
'lab.sensor_ret_manual',
'time',
chunk_time_interval => INTERVAL '1 hour',
create_default_indexes => FALSE
);
CREATE INDEX sensor_ret_manual_time_idx ON lab.sensor_ret_manual(time);
INSERT INTO lab.sensor_ret_manual
SELECT
generate_series(NOW() - INTERVAL '48 hours', NOW(), INTERVAL '5 minutes'),
(random() * 10)::int,
random() * 100;
SQL
Burada lab schema'sını ve 1 saatlik chunk'larla hypertable'ı oluşturup sonra 48 saatlik örnek veri basıyoruz.
1B) Silmeden önce ölçüm
kubectl exec -n $NS -i $TSPOD -- psql -U postgres -v ON_ERROR_STOP=1 <<'SQL'
SELECT count(*) AS rows_before
FROM lab.sensor_ret_manual;
SELECT show_chunks('lab.sensor_ret_manual') AS chunk_before;
SELECT
pg_size_pretty(sum(pg_total_relation_size(chunk::regclass))) AS total_before
FROM show_chunks('lab.sensor_ret_manual') AS chunk;
SQL
Burada ise silmeden önce satır sayısı, hangi chunk'ların oluştuğu ve chunk'ların toplam disk boyutunu görüyoruz.
Benim makinemdeki çıktılar:
- rows_before: 577
- chunk_before: 49 chunk
- total_before: 1176 kB
1C) 24 saatten eski chunk'ları dropla (manuel)
kubectl exec -n $NS -i $TSPOD -- psql -U postgres -v ON_ERROR_STOP=1 <<'SQL'
SELECT drop_chunks('lab.sensor_ret_manual', older_than => INTERVAL '24 hours');
SQL
İşte şimdi 'now() - 24 hours' çizgisinin tamamen solunda kalan chunk tablolarını topluca DROP ettik. Satır satır silme yok. Chunk bazında hızlıca droplar.
1D) Silmeden sonra ölçüm
kubectl exec -n $NS -i $TSPOD -- psql -U postgres -v ON_ERROR_STOP=1 <<'SQL'
SELECT count(*) AS rows_after
FROM lab.sensor_ret_manual;
SELECT show_chunks('lab.sensor_ret_manual') AS chunk_after;
SELECT
pg_size_pretty(sum(pg_total_relation_size(chunk::regclass))) AS total_after
FROM show_chunks('lab.sensor_ret_manual') AS chunk;
SQL
Burada drop_chunks sonrasında satır/chunk/boyutun gerçekten azaldığını doğruladık.
Benim makinemdeki çıktılar:
- rows_after: 299
- chunk_after: 25 chunk
- total_after: 600 kB
Önemli not: 'older_than => 24 hours' her zaman 'tam 24 saatin dışındaki tüm satırlar gider' demek değildir. Cutoff çizgisini kesen bir chunk içinde hem eski hem yeni veri varsa, o chunk komple droplanmaz. Bu nedenle az miktarda daha eski satır kalabilir.
Deney 2 - Otomatik veri saklama politikası (add_retention_policy + run_job)
Bu deneyde ise TimescaleDB'nin dahili job mekanizması ile otomatik retention kurduk ve job'ı manuel tetikledik.
2A) Hypertable oluştur ve veri ekle
kubectl exec -n $NS -i $TSPOD -- psql -U postgres -v ON_ERROR_STOP=1 <<'SQL'
DROP TABLE IF EXISTS lab.sensor_ret_policy;
CREATE TABLE lab.sensor_ret_policy (
time TIMESTAMPTZ NOT NULL,
device_id INT,
temperature DOUBLE PRECISION
);
SELECT create_hypertable(
'lab.sensor_ret_policy',
'time',
chunk_time_interval => INTERVAL '1 hour',
create_default_indexes => FALSE
);
CREATE INDEX sensor_ret_policy_time_idx ON lab.sensor_ret_policy(time);
INSERT INTO lab.sensor_ret_policy
SELECT
generate_series(NOW() - INTERVAL '48 hours', NOW(), INTERVAL '5 minutes'),
(random() * 10)::int,
random() * 100;
SQL
Bu blok ile otomatik retention deneyi için ikinci bir hypertable oluşturduk ve aynı şekilde 48 saatlik örnek veriyi doldurduk.
2B) Retention policy ekle (24 saat tut)
kubectl exec -n $NS -i $TSPOD -- psql -U postgres -v ON_ERROR_STOP=1 <<'SQL'
SELECT add_retention_policy('lab.sensor_ret_policy', INTERVAL '24 hours');
SQL
Burada ise TimescaleDB içinde arka planda çalışacak bir retention job'u oluşturduk. Dönüş değeri job_id olur.
2C) Job'ı bul ve çalıştır
kubectl exec -n $NS -i $TSPOD -- psql -U postgres -v ON_ERROR_STOP=1 <<'SQL'
SELECT job_id, proc_name, schedule_interval, config
FROM timescaledb_information.jobs
WHERE proc_name = 'policy_retention'
ORDER BY job_id DESC;
CALL run_job(<yukaridaki_job_id>);
SQL
Burası retention job'unun konfigürasyonunu gösterir ve beklemeden hemen çalıştırır. Normalde job schedule_interval'a göre otomatik çalışır.
2D) Sonucu doğrula
kubectl exec -n $NS -i $TSPOD -- psql -U postgres -v ON_ERROR_STOP=1 <<'SQL'
SELECT count(*) AS rows_after
FROM lab.sensor_ret_policy;
SELECT
pg_size_pretty(sum(pg_total_relation_size(chunk::regclass))) AS total_after
FROM show_chunks('lab.sensor_ret_policy') AS chunk;
SQL
Bu blok policy çalıştıktan sonra kalan satır sayısını ve chunk toplam boyutunu ölçer. Yani job'un gerçekten eski chunk'ları dropladığını kanıtlar.
Benim makinemdeki çıktılar:
- rows_after: 299
- total_after: 600 kB
Bu, retention policy'nin temelde drop_chunks ile aynı chunk droplama mekanizmasını otomatik olarak çalıştırdığını gösteriyor.
Temizlik
kubectl exec -n $NS -i $TSPOD -- psql -U postgres -v ON_ERROR_STOP=1 <<'SQL'
SELECT remove_retention_policy('lab.sensor_ret_policy');
DROP SCHEMA IF EXISTS lab CASCADE;
SQL
Burası retention policy'yi kaldırır ve lab schema'sını CASCADE ile silerek tüm test tablolarını ve internal chunk tablolarını temizler.
SQL DELETE vs TimescaleDB retention
TimescaleDB'nin sunduğu yerleşik, chunk tabanlı silme yöntemlerini kullanmak çoğu zaman en verimli yoldur. Yine de hangi yöntemin doğru olduğuna senaryo karar verir.
SQL DELETE (satır bazlı)
Artıları:
- İnce ayar: Sadece belirli cihazın verisi, belirli aralık, GDPR gibi seçici silmeler için uygundur.
- Chunk sınırına bağlı kalmadan hedeflediğin satırları silersin.
Eksileri:
- PostgreSQL MVCC nedeniyle satırlar diskten hemen silinmez; dead tuple olarak kalır.
- Büyük silmeler table bloat üretir; disk alanını gerçekten geri almak için VACUUM (bazen agresif vacuum) ve kimi zaman REINDEX gerekebilir.
- Çok miktarda veride satır satır silmek yavaş ve maliyetlidir (IO/CPU artışı).
TimescaleDB retention (chunk bazlı)
Artıları:
- Chunk'lar komple droplandığı için genellikle çok hızlıdır (DROP TABLE benzeri).
- Relation size çoğu senaryoda hemen düşer (örneğin benim makinemde 1176 kB -> 600 kB).
- add_retention_policy ile cron/script yazmadan, DB içindeki job mekanizmasıyla otomatik yönetim sağlanır.
- Zaman serisi kullanımında en doğal model: 'ham veriyi X süre tut, eskisini at'.
Eksileri / dikkat edilmesi gerekenler:
- Granularity: Retention satır bazlı değil chunk bazlıdır. Cutoff'u kesen chunk kalabilir; bu yüzden az miktarda daha eski satır tutulabilir.
- Seçici silme için uygun değildir (ör. sadece device_id=3 verisini silmek). Bu tip işlerde DELETE gerekir.
- Lock ihtiyacı: Chunk drop, ilgili chunk'lar üzerinde lock alır; uzun transaction varsa drop gecikebilir veya timeout görebiliriz.
Sonuç
Hedefiniz 'X süreden eski zaman serisi ham verisini otomatik ve verimli şekilde kaldırmak' ise TimescaleDB'nin retention policy (add_retention_policy) veya manuel drop_chunks yaklaşımı genellikle en doğru ve yönetimi en kolay çözümdür. Buna rağmen seçici ve ince ayarlı silme ihtiyaçlarında SQL DELETE hala gerekli bir araçtır.
Top comments (0)