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 VIEWiç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ı
| Senaryo | Neden Kullanılır |
|---|---|
| Raporlama & Dashboard | Bü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
| Özellik | View | Materialized View |
|---|---|---|
| Veri tutulur mu? | ❌ Hayır | ✅ Evet |
| Performans | Yavaş (her seferinde çalışır) | Çok hızlı (önbellekten okur) |
| Güncelleme | Anlık (her sorguda) | Manuel / zamanlanmış |
| Veri güncelliği | Her zaman taze | Yenileme sıklığına bağlı |
| Kullanım alanı | Dinamik raporlar | Statik / ö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ık | Açıklama |
|---|---|
| Tanım | Sorgu sonucunun fiziksel olarak saklandığı tablo |
| Avantajı | Hızlı okuma, düşük CPU yükü, dashboard hızlanması |
| Dezavantajı | Güncelleme manuel / planlı |
| Kullanım yeri | BI, raporlama, Timescale continuous aggregates |
| Güncelleme komutu | REFRESH 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ı?