DEV Community

Tarık Anafarta
Tarık Anafarta

Posted on

Kubernetes'te TimescaleDB Retention Testleri

Ö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"
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

İş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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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)