Veritabanı Yönetimi

    TimescaleDB ile Zaman Serisi Verisi Saklama

    TimescaleDB hypertable, sıkıştırma ve continuous aggregate ile zaman serisi verisini yönetme rehberi.

    10 dk okuma Güncellendi: 25 Ağustos 2026

    Sunucularınızdan saniyede bir metrik topluyorsunuz, tabloda üç ay içinde 800 milyon satır birikti ve "son 24 saatin ortalama CPU kullanımı" sorgusu artık 40 saniye sürüyor. Klasik bir PostgreSQL tablosu bu iş yükü için tasarlanmamıştır: veri sürekli sona eklenir, hemen hiç güncellenmez, sorgular neredeyse her zaman bir zaman aralığına bakar ve eski veri bir noktadan sonra ham haliyle gerekmez. TimescaleDB, PostgreSQL'i bu erişim desenine göre yeniden ayarlayan bir uzantıdır ve zaman serisi verisini saklamayı hem hızlı hem de ucuz hale getirir.

    Bu rehberde TimescaleDB kurulumunu, hypertable kavramını ve normal tablodan farkını, time_bucket ile zaman kovalarına özetleme yapmayı, sürekli toplulaştırma (continuous aggregate) ile önceden hesaplanmış özet tablolar tutmayı, yerel sıkıştırma ile disk kullanımını büyük ölçüde düşürmeyi ve saklama politikasıyla eski veriyi otomatik silmeyi anlatacağım. Sonunda da bu uzantıyı ilk kez kullananların takıldığı noktaları topladım.

    TimescaleDB Kurulumu#

    TimescaleDB, PostgreSQL üzerine kurulan bir uzantıdır; ayrı bir veritabanı sunucusu değildir. Bu, mevcut SQL bilginizin, sürücülerinizin, yedekleme araçlarınızın ve psql alışkanlıklarınızın olduğu gibi geçerli kalması demektir. Kurulum, sağlayıcının deposunu ekleyip paketi kurmakla başlar.

    # Depoyu ekleyin (dağıtım kod adını kendi sisteminize göre kontrol edin)
    sudo apt install -y gnupg postgresql-common apt-transport-https lsb-release wget
    sudo /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh -y
    
    echo "deb https://packagecloud.io/timescale/timescaledb/ubuntu/ $(lsb_release -cs) main" \
      | sudo tee /etc/apt/sources.list.d/timescaledb.list
    
    wget --quiet -O - https://packagecloud.io/timescale/timescaledb/gpgkey \
      | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/timescaledb.gpg
    
    sudo apt update
    sudo apt install -y timescaledb-2-postgresql-16
    

    Kurulumdan sonra uzantının PostgreSQL başlangıcında yüklenmesi gerekir. timescaledb-tune aracı hem bu ayarı yapar hem de shared_buffers, work_mem, max_worker_processes gibi değerleri makinenizin RAM ve CPU sayısına göre önerir:

    sudo timescaledb-tune --quiet --yes
    sudo systemctl restart postgresql
    

    Ardından uzantıyı kullanacağınız veritabanında etkinleştirin:

    CREATE EXTENSION IF NOT EXISTS timescaledb;
    SELECT extversion FROM pg_extension WHERE extname = 'timescaledb';
    

    shared_preload_libraries satırında timescaledb yoksa uzantı yüklenmez ve CREATE EXTENSION hata verir; bu, kurulum sonrası yeniden başlatmayı atlayanların en sık karşılaştığı sorundur.

    Hypertable: Otomatik Bölümlenen Tablo#

    TimescaleDB'nin temel yapı taşı hypertable'dır. Dışarıdan bakıldığında sıradan bir tablodur: aynı INSERT, aynı SELECT, aynı indeksler. İçeride ise zaman sütununa göre otomatik olarak "chunk" adı verilen parçalara bölünür. Bu, elle yönettiğiniz PostgreSQL tablo partitioning yapısının otomatikleştirilmiş halidir; yeni chunk açmayı, sınırları hesaplamayı ve indeksleri yaymayı uzantı üstlenir.

    -- 1) Sıradan bir tablo olarak başlayın
    CREATE TABLE metrikler (
        zaman     timestamptz NOT NULL,
        sunucu_id int         NOT NULL,
        metrik    text        NOT NULL,
        deger     double precision NOT NULL
    );
    
    -- 2) Hypertable'a dönüştürün; chunk aralığı 7 gün
    SELECT create_hypertable(
        'metrikler', by_range('zaman', INTERVAL '7 days')
    );
    
    -- 3) Tipik sorgu deseninize uygun indeks
    CREATE INDEX ON metrikler (sunucu_id, zaman DESC);
    

    Chunk aralığını seçerken kullanılan pratik kural şudur: bir chunk'ın indeksleriyle birlikte, makinenin RAM'inin yaklaşık dörtte birine sığması hedeflenir. Aralık çok büyük olursa sıcak veri belleğe sığmaz ve yazma yavaşlar; çok küçük olursa chunk sayısı patlar ve planlama maliyeti yükselir. Günde 5 GB veri üreten bir sistemde 7 günlük aralık genelde fazla büyüktür; günlük aralığa geçmek daha doğru olur. Aralığı sonradan değiştirebilirsiniz, değişiklik yalnızca yeni chunk'lara uygulanır:

    SELECT set_chunk_time_interval('metrikler', INTERVAL '1 day');
    

    Mevcut chunk'ları ve boyutlarını görmek için TimescaleDB'nin kendi görünümlerini kullanın:

    SELECT chunk_name, range_start, range_end,
           pg_size_pretty(total_bytes) AS boyut
    FROM timescaledb_information.chunks
    WHERE hypertable_name = 'metrikler'
    ORDER BY range_start DESC
    LIMIT 5;
    

    time_bucket ile Zaman Kovalarına Özetleme#

    Zaman serisi sorgularının neredeyse tamamı "şu aralıkta, şu periyotla özet ver" biçimindedir. PostgreSQL'in date_trunc fonksiyonu yalnızca sabit birimlere (saat, gün, ay) böler; 5 dakikalık ya da 15 dakikalık kovalar için elle aritmetik yapmanız gerekir. TimescaleDB'nin time_bucket fonksiyonu bu işi tek adımda çözer ve chunk atlamayı da doğru tetikler.

    -- Son 24 saatte, 5 dakikalık kovalarda ortalama ve tepe CPU değeri
    SELECT time_bucket('5 minutes', zaman) AS kova,
           sunucu_id,
           avg(deger)  AS ortalama,
           max(deger)  AS tepe
    FROM metrikler
    WHERE metrik = 'cpu_yuzde'
      AND zaman >= now() - INTERVAL '24 hours'
    GROUP BY kova, sunucu_id
    ORDER BY kova DESC;
    

    Buradaki kritik nokta WHERE zaman >= ... koşuludur. Bu koşul olmadan sorgu tüm chunk'ları tarar ve hypertable'ın sağladığı kazanç tamamen kaybolur. TimescaleDB, zaman koşuluna bakarak hangi chunk'ların sonucu etkileyemeyeceğini anlar ve onlara hiç dokunmaz — tıpkı PostgreSQL'in partition pruning mekanizması gibi. Sorgunuzun gerçekten az sayıda chunk okuduğunu EXPLAIN çıktısında doğrulayabilirsiniz; plan okuma yöntemi için EXPLAIN ANALYZE çıktısını okuma yazısına bakabilirsiniz.

    TimescaleDB, zaman serisi için sık gereken birkaç ek fonksiyon da sunar:

    FonksiyonNe yapar
    time_bucket(aralik, zaman)Zamanı sabit genişlikte kovalara böler
    first(deger, zaman) / last(deger, zaman)Kova içindeki ilk / son değeri döner
    locf(deger)Boş kovaları son bilinen değerle doldurur
    time_bucket_gapfill(...)Veri olmayan kovalar için de satır üretir

    last() fonksiyonu özellikle işe yarar: bir sayaç metriğinin kova sonundaki değerini almak için max() kullanmak yanlış sonuç verir çünkü sayaç sıfırlanmış olabilir; last(deger, zaman) zamana göre en son kaydı döndürür.

    Sürekli Toplulaştırma (Continuous Aggregate)#

    Aynı özet sorgusunu dakikada bir çalıştıran bir gösterge paneliniz varsa, her seferinde milyonlarca ham satırı okumanın anlamı yok. Sürekli toplulaştırma, özet sonucunu materyalize edilmiş bir görünümde saklar ve arka plandaki bir işçi süreç yalnızca değişen kısımları günceller. Klasik materyalize görünümden farkı budur: tamamı yeniden hesaplanmaz.

    -- Saatlik özet: ham veriden bağımsız olarak saklanır
    CREATE MATERIALIZED VIEW metrik_saatlik
    WITH (timescaledb.continuous) AS
    SELECT time_bucket('1 hour', zaman) AS saat,
           sunucu_id,
           metrik,
           avg(deger) AS ortalama,
           max(deger) AS tepe,
           min(deger) AS dip,
           count(*)   AS ornek_sayisi
    FROM metrikler
    GROUP BY saat, sunucu_id, metrik
    WITH NO DATA;
    
    -- Yenileme politikası: son 7 günü kapsayacak şekilde saatte bir güncelle
    SELECT add_continuous_aggregate_policy('metrik_saatlik',
        start_offset => INTERVAL '7 days',
        end_offset   => INTERVAL '1 hour',
        schedule_interval => INTERVAL '1 hour');
    

    end_offset parametresi göründüğünden önemlidir: en son bir saatlik dilimi materyalize etmemenizi sağlar. Gecikmeli gelen veriler (bir ajanın ağ kesintisi sonrası toplu gönderdiği metrikler) hâlâ akıyorsa, o dilimi erken dondurmak eksik özet üretir. TimescaleDB bu durumda özet ile ham veriyi otomatik birleştirerek doğru cevap döner — yani end_offset içindeki taze veriyi sorgu anında ham tablodan okur.

    Panel sorgunuz artık ham tablo yerine özet görünüme gider ve saniyeler yerine milisaniyeler sürer:

    SELECT saat, ortalama, tepe
    FROM metrik_saatlik
    WHERE sunucu_id = 7 AND metrik = 'cpu_yuzde'
      AND saat >= now() - INTERVAL '30 days'
    ORDER BY saat;
    

    Farklı çözünürlükler için birden fazla özet katmanı kurabilirsiniz: dakikalıktan saatliğe, saatlikten günlüğe. Üst katmanı alt katmanın üzerine kurmak (hiyerarşik toplulaştırma) hesaplama maliyetini ciddi biçimde düşürür.

    Sıkıştırma ve Saklama Politikaları#

    Zaman serisi verisinin en büyük maliyeti disktir ve TimescaleDB'nin sıkıştırma özelliği burada devreye girer. Sıkıştırma, chunk'ları satır bazlı düzenden sütun bazlı bir düzene çevirir; aynı sütundaki ardışık değerler birbirine benzediği için sıkıştırma oranları çok yüksek olur. Metrik verisinde 10 kat ve üzeri kazanç sıradışı değildir.

    -- Hangi sütuna göre gruplanacağı ve nasıl sıralanacağı belirtilir
    ALTER TABLE metrikler SET (
        timescaledb.compress,
        timescaledb.compress_segmentby = 'sunucu_id, metrik',
        timescaledb.compress_orderby   = 'zaman DESC'
    );
    
    -- 14 günden eski chunk'ları otomatik sıkıştır
    SELECT add_compression_policy('metrikler', INTERVAL '14 days');
    

    compress_segmentby seçimi sonucu doğrudan belirler: sorgularınızda WHERE ile filtrelediğiniz düşük kardinaliteli sütunları buraya koyun. Yanlış seçim hem sıkıştırma oranını düşürür hem sorguları yavaşlatır. sunucu_id gibi yüzlerce farklı değer alan bir sütun uygundur; her satırda farklı olan bir kimlik sütunu değildir.

    Sıkıştırma oranını ölçmek için hazır fonksiyon vardır:

    SELECT pg_size_pretty(before_compression_total_bytes) AS once,
           pg_size_pretty(after_compression_total_bytes)  AS sonra
    FROM hypertable_compression_stats('metrikler');
    

    Saklama politikası ise eski chunk'ları tamamen düşürür. Bu işlem DELETE değil DROP CHUNK olduğu için saniyeler sürer, WAL üretmez ve diski anında geri verir:

    -- 12 aydan eski ham veriyi sil (özet görünümler etkilenmez)
    SELECT add_retention_policy('metrikler', INTERVAL '12 months');
    
    -- Tanımlı tüm arka plan işlerini gör
    SELECT job_id, application_name, schedule_interval, next_start
    FROM timescaledb_information.jobs;
    

    Bu üçlü — sürekli toplulaştırma, sıkıştırma, saklama politikası — birlikte kullanıldığında güçlü bir katmanlı yapı kurar: son 14 gün ham ve hızlı, 14 gün-12 ay arası sıkıştırılmış, 12 aydan eskisi ise yalnızca özet görünümlerde saklanır. Uzun vadeli özetleri ayrı bir yerde tutmak isterseniz yedekleme hizmetimizle düzenli kopya alabilirsiniz.

    Sık Yapılan Hatalar ve Tuzaklar#

    Zaman filtresi olmayan sorgular. Hypertable'ın tüm avantajı chunk atlamaktan gelir. WHERE zaman >= ... koşulu olmayan bir sorgu her chunk'a dokunur ve normal bir tablodan daha yavaş çalışabilir. Panel sorgularınızda zaman aralığını her zaman açıkça verin.

    Çok küçük chunk aralığı. Beş dakikalık chunk aralığı seçmek, bir yılda yüz binden fazla chunk demektir. Her chunk ayrı bir tablodur ve planlama sırasında kilit tüketir; max_locks_per_transaction sınırını aşarak "out of shared memory" hatası alırsınız. Aralığı, chunk sayısı birkaç bini geçmeyecek şekilde seçin.

    Sıkıştırılmış chunk'a yazmaya çalışmak. Eski TimescaleDB sürümlerinde sıkıştırılmış bir chunk'a INSERT yapılamıyordu; güncel sürümlerde destekleniyor ama performansı ham chunk'a yazmaya göre çok daha düşük. Geç gelen veri düzenli olarak sıkıştırma sınırının gerisine düşüyorsa, add_compression_policy aralığını genişletin.

    Sürekli toplulaştırmayı gereğinden agresif yenilemek. schedule_interval değerini bir dakikaya çekmek arka plan işçilerini sürekli meşgul eder ve yazma performansını etkiler. Panelinizin gerçekten ihtiyaç duyduğu tazelikle politikayı eşleştirin; çoğu gösterge paneli için saatlik yenileme fazlasıyla yeterlidir.

    Yedekleme stratejisini uyarlamamak. pg_dump ile alınan mantıksal yedek hypertable yapısını ve politikaları geri yüklerken ek dikkat gerektirir. Fiziksel yedek (base backup + WAL arşivi) bu konuda daha güvenlidir çünkü tüm iç yapıyı olduğu gibi kopyalar. Uzantıyı kurduktan sonra kurtarma prosedürünüzü mutlaka bir kez prova edin.

    Ana sürüm uyumu. TimescaleDB paketi, kurulu PostgreSQL ana sürümüne bağlıdır. PostgreSQL'i yükseltirken uzantıyı da uygun sürüme geçirmeniz gerekir; sırayı ters yaparsanız sunucu açılmaz. Yükseltme öncesi mutlaka tam yedek alın.

    Sıkça Sorulan Sorular#

    TimescaleDB ayrı bir veritabanı mı yoksa PostgreSQL uzantısı mı#

    Bir PostgreSQL uzantısıdır. Ayrı bir sunucu süreci, ayrı bir protokol veya ayrı bir sorgu dili yoktur; aynı PostgreSQL örneği içinde çalışır. Bu, mevcut sürücülerinizin, ORM'inizin, psql alışkanlıklarınızın ve yedekleme araçlarınızın olduğu gibi geçerli kalması demektir. Uzantıyı kaldırdığınızda hypertable'lar çalışmaz hale gelir, dolayısıyla bir kez benimsediğinizde altyapı bağımlılığı oluşur.

    Hypertable ile PostgreSQL'in kendi partitioning'i arasındaki fark ne#

    İkisi de tabloyu parçalara böler ama TimescaleDB bu işi otomatikleştirir ve üzerine zaman serisine özel özellikler ekler. Yerel partitioning'de yeni partition açmayı, sınırları hesaplamayı ve eskiyi düşürmeyi siz yönetirsiniz; hypertable'da chunk'lar veri geldikçe kendiliğinden oluşur. Ayrıca sütun bazlı sıkıştırma, sürekli toplulaştırma ve time_bucket gibi fonksiyonlar yalnızca TimescaleDB'de vardır.

    Sıkıştırma ne kadar yer kazandırır#

    Kazanç verinin yapısına bağlıdır ama sayısal metrik verisinde 10 kat ve üzeri oranlar yaygındır, çünkü ardışık ölçümler birbirine çok benzer ve sütun bazlı düzen bunu çok iyi sıkıştırır. Serbest metin veya rastgele ikili veri saklıyorsanız oran belirgin biçimde düşer. Kendi verinizdeki gerçek oranı hypertable_compression_stats fonksiyonuyla ölçün; tahmin etmeyin.

    Sıkıştırılmış veriyi güncelleyebilir veya silebilir miyim#

    Güncel sürümlerde sıkıştırılmış chunk'lara ekleme ve silme desteklenir, ancak ham chunk'a göre çok daha maliyetlidir çünkü ilgili bölümün açılması gerekir. Zaman serisi verisi doğası gereği neredeyse hiç güncellenmediği için bu pratikte nadiren sorun olur. Düzenli olarak eski veriyi düzeltmeniz gerekiyorsa, sıkıştırma politikasının aralığını o düzeltmelerin geldiği süreden daha uzun tutun.

    TimescaleDB ücretsiz mi#

    Çekirdek özellikler açık kaynaklıdır ve ücretsiz kullanılabilir: hypertable, time_bucket, sürekli toplulaştırma ve sıkıştırma bunlara dahildir. Bazı ileri düzey ve yönetilen hizmete özgü özellikler farklı lisans koşullarına tabidir. Kendi sunucunuza kurup üretimde kullanmanın önünde bir ücret engeli yoktur; ayrıntılı lisans metnini kurulum öncesinde bir kez okumanızı öneririm.

    Prometheus veya InfluxDB yerine bunu mu kullanmalıyım#

    Cevap kullanım biçiminize bağlı. Verinizi ilişkisel tablolarla birleştirmeniz gerekiyorsa, SQL yazmak istiyorsanız ve mevcut PostgreSQL altyapınız varsa TimescaleDB güçlü bir tercihtir; tek bir sorguda metriklerle müşteri tablosunu birleştirebilirsiniz. Yalnızca altyapı izleme yapıyorsanız ve zengin bir uyarı ekosistemi istiyorsanız Prometheus daha az kurulum yüküyle çalışır. İkisini birlikte kullanmak da yaygındır: kısa vadeli izleme Prometheus'ta, uzun vadeli analiz TimescaleDB'de.

    Kapanış#

    TimescaleDB'yi verimli kullanmanın özeti dört alışkanlıkta toplanıyor: her sorguya zaman filtresi koyun yoksa chunk atlama devreye girmez, chunk aralığını RAM'inize göre seçip chunk sayısını birkaç binle sınırlayın, panel sorgularını ham tablo yerine sürekli toplulaştırmalara yönlendirin ve sıkıştırma ile saklama politikalarını ilk günden tanımlayın. Bu dördü kurulduğunda, aynı donanımda kat kat daha fazla veriyi kat kat daha hızlı sorgularsınız.

    Zaman serisi iş yükleri yazma yoğun olduğu için disk performansı belirleyicidir. NVMe destekli VDS veya kaynağını ihtiyaca göre büyütebileceğiniz bulut sunucu paketlerimiz sürekli akan metrik verisi altında kararlı çalışır; çok yüksek hacimli kurulumlar için dedicated sunucu daha öngörülebilir bir IO tabanı sunar. Kurulum, ayar ve düzenli bakım işlerini devretmek isterseniz sunucu yönetimi hizmetimiz bu süreci üstlenir.

    TimescaleDBPostgreSQLZaman Serisi

    Uygulamaya geçmeye hazır mısınız?

    NVMe SSD, ücretsiz SSL ve %99.9 uptime garantisiyle Clou.TR hosting ve sunucu çözümleriyle projenizi hayata geçirin.