Materialized View Nedir?

Çok güzel bir soru Yakup 👏
“Materialized View” (kısaca MV) kavramı — özellikle PostgreSQL, TimescaleDB ve analitik sistemlerde — performans optimizasyonunun kalbidir.
Kısaca özetleyecek olursam:

Materialized View, bir sorgunun sonucunu fiziksel olarak diske kaydeden, yani “önceden hesaplanmış tablo”dur.

Hemen detaylara geçelim 👇


🧠 1. Materialized View Nedir?

Normal bir VIEW sadece sorgu tanımıdır:

CREATE VIEW active_users AS
SELECT * FROM users WHERE is_active = true;

➡️ Her çağırdığında sorgu yeniden çalışır (gerçek zamanlı ama yavaş).

Ama MATERIALIZED VIEW şöyle çalışır:

CREATE MATERIALIZED VIEW user_summary AS
SELECT country, COUNT(*) AS total_users
FROM users
GROUP BY country;

➡️ Bu, sorgunun çıktısını tablo gibi saklar.
Yani SELECT * FROM user_summary dediğinde, tabloya erişir gibi hızlıdır — çünkü veriler önceden hesaplanmıştır.


⚙️ 2. Temel Kullanım

🏗️ Oluşturma

CREATE MATERIALIZED VIEW sales_summary AS
SELECT date_trunc('day', created_at) AS day,
       SUM(amount) AS total_sales
FROM sales
GROUP BY day;

🔍 Kullanma

SELECT * FROM sales_summary WHERE day >= now() - interval '7 days';

Bu sorgu, ana tabloya dokunmaz, direkt MV’den okur — yani çok hızlıdır ⚡


🔄 3. Güncelleme (Refresh)

Materialized View, veriler değiştiğinde otomatik güncellenmez
(Klasik VIEW gibi dinamik değildir).
O yüzden periyodik olarak “yenilemen” gerekir:

REFRESH MATERIALIZED VIEW sales_summary;

Bu komut, CREATE MATERIALIZED VIEW içindeki sorguyu yeniden çalıştırır ve içeriği günceller.

Performanslı yöntem:

REFRESH MATERIALIZED VIEW CONCURRENTLY sales_summary;

Bu sürüm:

  • Okuma sırasında kilitlemez
  • MV içeriğini arka planda yeniler
  • Ancak bunun için UNIQUE INDEX gerekir.
CREATE UNIQUE INDEX idx_sales_summary_day ON sales_summary(day);
REFRESH MATERIALIZED VIEW CONCURRENTLY sales_summary;


⚡ 4. Kullanım Alanları

SenaryoNeden Kullanılır
Raporlama & DashboardBüyük sorguların sonuçlarını önceden hazırlar, dashboard’lar anında yüklenir.
Analitik sistemler (Timescale, BI)Aggregation (sum, avg, group by) işlemleri ağırdır, MV ile cache’lenir.
API performans artırma“read-heavy” API uçları için hızlı sorgulama sağlar.
ETL sonrası özetlemeİşlenen verilerin aggregate sonuçları saklanır.

🧮 5. TimescaleDB ile Materialized View (Continuous Aggregate)

TimescaleDB bu konsepti otomatikleştirir.
“Continuous Aggregate” adını verir — yani arka planda kendisi günceller 🔁

Örnek:

CREATE MATERIALIZED VIEW cpu_hourly
WITH (timescaledb.continuous) AS
SELECT time_bucket('1 hour', time) AS bucket,
       avg(cpu_usage) AS avg_cpu
FROM metrics
GROUP BY bucket;

Timescale arka planda otomatik “refresh policy” uygular:

SELECT add_continuous_aggregate_policy('cpu_hourly',
  start_offset => INTERVAL '1 day',
  end_offset   => INTERVAL '1 hour',
  schedule_interval => INTERVAL '1 hour');

Yani her saat başı son 24 saati yeniden hesaplar ✅
Senin elinle REFRESH etmen gerekmez.


🧩 6. Materialized View vs Normal View

ÖzellikViewMaterialized View
Veri tutulur mu?❌ Hayır✅ Evet
PerformansYavaş (her seferinde çalışır)Çok hızlı (önbellekten okur)
GüncellemeAnlık (her sorguda)Manuel / zamanlanmış
Veri güncelliğiHer zaman tazeYenileme sıklığına bağlı
Kullanım alanıDinamik raporlarStatik / özet raporlar

🔐 7. Örnek Senaryo

🧱 Büyük tablo:

CREATE TABLE logs (
  id serial,
  service text,
  created_at timestamptz,
  status text
);

🧾 Ağır sorgu:

SELECT service, count(*)
FROM logs
WHERE created_at > now() - interval '1 day'
GROUP BY service;

Bu sorgu 50 milyon satırlık log tablosunda çok yavaş olur.

⚙️ Materialized çözüm:

CREATE MATERIALIZED VIEW log_summary AS
SELECT date_trunc('hour', created_at) AS hour,
       service,
       count(*) AS request_count
FROM logs
GROUP BY hour, service;

Sonra cron veya pg_cron ile periyodik olarak güncelle:

REFRESH MATERIALIZED VIEW CONCURRENTLY log_summary;


🧰 8. Bonus: Otomatik Yenileme (pg_cron ile)

pg_cron eklentisiyle PostgreSQL içinde zamanlayıcı kurabilirsin:

SELECT cron.schedule(
  'refresh_sales_summary',
  '0 * * * *',  -- her saat
  $$REFRESH MATERIALIZED VIEW CONCURRENTLY sales_summary;$$
);

Böylece tamamen otomatik hale gelir 💪


🧠 Özet

BaşlıkAçıklama
TanımSorgu sonucunun fiziksel olarak saklandığı tablo
AvantajıHızlı okuma, düşük CPU yükü, dashboard hızlanması
DezavantajıGüncelleme manuel / planlı
Kullanım yeriBI, raporlama, Timescale continuous aggregates
Güncelleme komutuREFRESH MATERIALIZED VIEW [CONCURRENTLY] name;

İstersen sana küçük bir demo hazırlayayım:
PostgreSQL üzerinde gerçek bir MATERIALIZED VIEW oluşturup,
öncesi-sonrası sorgu hızlarını göstereyim (örneğin 10M satırlık örnek data ile).
Hazırlayayım mı?

Bunlar da hoşunuza gidebilir...