Önce şunu sorun: soru tekrar ediyor mu?
Bir pano her dakika aynı metrikleri soruyorsa ham tabloyu her seferinde taramak pahalı olabilir. Analitik sistemlerde iyi performans bazen daha hızlı sorgu yazmak değil, aynı cevabı sürekli yeniden hesaplamamaktır.
Bu yüzden projection ve materialized view kararından önce ürün sorusunu anlamak gerekir: kullanıcı ham event mi görmek istiyor, yoksa gün/tenant/event bazında hazır metrik mi?
Projection aynı tablonun başka okuma düzeni gibidir
Projection, aynı tablonun içinde farklı bir fiziksel düzen veya ön hesaplama sağlayabilir. Sorgu optimizer uygun görürse projection kullanabilir. Bu, bazı sorgu desenlerini hızlandırırken uygulama tarafında ayrı tablo yönetimini azaltabilir.
Ama projection her şeyi görünmezce çözmez. Sorgunun projection kullanıp kullanmadığını ölçmek gerekir; aksi halde ek yazma ve depolama maliyeti üretip beklenen hızlanmayı alamayabilirsiniz.
Projection fikri
ALTER TABLE events ADD PROJECTION events_by_user ( SELECT tenant_id, user_id, created_at, event_name ORDER BY (tenant_id, user_id, created_at) ); ALTER TABLE events MATERIALIZE PROJECTION events_by_user;
Materialized view cevabı başka tabloya hazırlar
Materialized view özellikle tekrar eden agregasyonlarda çok değerlidir. Ham event verisi akarken günlük veya saatlik özet tabloyu besleyebilirsiniz. Pano artık milyarlarca ham satırı değil, çok daha küçük bir özet tabloyu okur.
Günlük event rollup örneği
CREATE TABLE events_daily ( tenant_id String, event_name LowCardinality(String), day Date, events UInt64 ) ENGINE = SummingMergeTree PARTITION BY toYYYYMM(day) ORDER BY (tenant_id, event_name, day); CREATE MATERIALIZED VIEW events_daily_mv TO events_daily AS SELECT tenant_id, event_name, toDate(created_at) AS day, count() AS events FROM events GROUP BY tenant_id, event_name, day;
Kararı query_log ile doğrulayın
Projection veya materialized view ekledikten sonra “hızlandı gibi” demek yetmez. query_log üzerinde read_rows, read_bytes ve duration değerleri düşüyor mu bakın. Eğer düşmüyorsa sorgu hâlâ ham tabloyu okuyor olabilir.
TürkDB tarafındaki doğru ilişki burada kapasite kararını ertelemek değil, daha bilinçli vermektir. Önce okuma modelini düzeltin; sonra hâlâ sınırdaysanız ölçek büyütmek daha anlamlıdır.
Önce/sonra query_log kontrolü
SELECT query_duration_ms, read_rows, formatReadableSize(read_bytes) AS read_size, left(query, 180) AS query FROM system.query_log WHERE type = 'QueryFinish' AND event_time > now() - INTERVAL 30 MINUTE ORDER BY query_duration_ms DESC LIMIT 20;