---
title: 'Ölçüt Toplama Sistemi'
source: 'https://academia.sh/tr/kurslar/vaka-calismalari/olcut-toplama-sistemi'
course: 'Vaka Çalışmaları'
language: tr
updated: '2026-08-17T18:10:55+00:00'
license: 'CC BY-SA 4.0'
---

# Ölçüt Toplama Sistemi

Tek tek hiçbir kaydın anlamlı olmadığı vaka: zaman serisi yazma yolunun örnek hızıyla bütçelenmesi, saklama basamaklarının toplam bayta etkisi ve seyreltmenin hangi soruyu bozmadan, hangisini yüzde yüz yanlış yanıtladığının gerçek bir motorda ölçülmesi.

Önceki iki vakada üretilen her bayt saklanmaya değerdi: bir nesne yazıldığı gibi tutuldu, bir video
parçası üretildikten sonra defalarca okundu. Bu vaka o varsayımı kaldırır. Burada kayıtlar saniyede
yüz binlerce üretilir, tek tek hiçbiri anlamlı değildir ve hepsini süresiz saklamak ne mümkündür ne
de gereklidir.

Sistem bir **ölçüt toplama** sistemidir: düğümler düzenli aralıklarla sayısal örnek gönderir,
örnekler **zaman serisi** olarak yazılır ve sorular hep bir zaman aralığı üzerinden sorulur.
Ölçülecek karar **seyreltme** (downsampling) ile **toplulaştırmanın** (rollup) ikili etkisidir:
saklanan bayt ve taranan satır düşer, ama toplulaştırılmış veriden okunan yanıt ham veriden okunana
eşit değildir. Bu fark soru türüne göre değişir ve tasarım o farkı bilerek seçer.

Hangi ölçütün toplanmaya değer olduğu bu vakanın konusu değil; o soru Başarım Karşıt Kalıpları ve
İzleme kursunun Enstrümantasyon Tasarımı dersinde kuruldu. Burada ölçüt kümesi verilidir ve tasarım
onu taşıma işidir.

## Kısıtlar

İşlevsel gereksinim: örnek kabul etme, seri ve zaman aralığına göre okuma, seri üzerinde ortalama /
en büyük / yüzdelik / eşik aşımı sorularını yanıtlama ve saklama süresi dolan veriyi düşürme.

İşlevsel olmayan gereksinim, sayıyla: yazma yolu tepe **480.000** örnek/s'yi kayıpsız kabul eder;
toplam saklanan bayt **40** TB'ı geçmez; altı saatlik bir gösterge tablosu sorgusu seri başına
**400**'den az satır tarar; son **7** gün içinde yüzdelik ve eşik aşımı soruları **hatasız**
yanıtlanır.

Kapsam daraltması: uyarı kuralları, gösterge tablosu arayüzü, izleme kategorileri ve dağıtık iz
toplama tasarlanmaz — bunlar Başarım Karşıt Kalıpları ve İzleme kursunun konusudur.

## Varsayımlar

| Kod | Varsayım | Değer | Gerekçe |
|---|---|---|---|
| OT1 | izlenen düğüm | 20.000 | işletilen süreçlerin toplamı |
| OT2 | düğüm başına seri | 120 | süreç, kaynak ve uç başına birkaç ölçüt |
| OT3 | örnekleme aralığı | 10 s | ajanın gönderme sıklığı |
| OT4 | ham örnek kaydı | 26 bayt | seri kimliği, zaman ve değer |
| OT5 | özet kaydı | 34 bayt | kova, adet, toplam ve en büyük |
| OT6 | tepe çarpanı | 2 | ölçüt akışı düzenlidir, tepesi sığdır |
| OT7 | ham saklama | 7 gün | olay incelemesi bir haftaya bakar |
| OT8 | bir dakikalık özet saklama | 90 gün | çeyrek dönem karşılaştırması |
| OT9 | beş dakikalık özet saklama | 730 gün | kapasite eğilimi iki yıl geriye gider |
| OT10 | gösterge tablosu aralığı | 6 saat | bir vardiyanın penceresi |

OT6 bu vakanın ayırt edici varsayımıdır: tepe çarpanı önceki vakalarda 3'tü, burada 2. Ölçüt akışı
kullanıcı davranışına değil ajanın zamanlayıcısına bağlıdır, bu yüzden tepesi sığdır.

## Ölçek

```js
// olcut-olcek.mjs — OT tablosundan cikan olcek hesabi ve saklama basamaklarinin toplami
const OT = { dugum: 20_000, seriBasinaDugum: 120, aralikSn: 10, hamBayt: 26, ozetBayt: 34,
  tepe: 2, sorguAralikSaat: 6, hamGun: 7, dakikaGun: 90, besDakikaGun: 730 };
const seri = OT.dugum * OT.seriBasinaDugum;
const ornekSn = seri / OT.aralikSn;
const gunlukHam = ornekSn * 86_400 * OT.hamBayt;
const ozetGunluk = (tanecikSn) => (seri * (86_400 / tanecikSn)) * OT.ozetBayt;

for (const [ad, d] of [
  ["seri sayisi", seri],
  ["ortalama ornek/s", ornekSn],
  ["tepe ornek/s", ornekSn * OT.tepe],
  ["ham gunluk GB", gunlukHam / 1e9],
  ["1 dk ozet gunluk GB", ozetGunluk(60) / 1e9],
  ["5 dk ozet gunluk GB", ozetGunluk(300) / 1e9],
]) console.log(ad.padEnd(24) + d.toFixed(2).padStart(12));

const basamak = [["ham", gunlukHam, OT.hamGun], ["1 dk ozet", ozetGunluk(60), OT.dakikaGun],
  ["5 dk ozet", ozetGunluk(300), OT.besDakikaGun]];
let toplam = 0;
console.log(`\n${"basamak".padEnd(12)}${"gun".padStart(6)}${"saklanan TB".padStart(14)}`);
for (const [ad, gun, sure] of basamak) {
  toplam += (gun * sure) / 1e12;
  console.log(ad.padEnd(12) + String(sure).padStart(6) + ((gun * sure) / 1e12).toFixed(2).padStart(14));
}
const hepsiHam = (gunlukHam * OT.besDakikaGun) / 1e12;
console.log(`toplam ${toplam.toFixed(2)} TB; hepsi ham ve ${OT.besDakikaGun} gun tutulsaydi ` +
  `${hepsiHam.toFixed(2)} TB (x${(hepsiHam / toplam).toFixed(2)})`);
console.log(`${OT.sorguAralikSaat} saatlik sorgu seri basina okunan satir: ham ` +
  `${(OT.sorguAralikSaat * 3600) / OT.aralikSn}, 1 dk ${OT.sorguAralikSaat * 60}, ` +
  `5 dk ${(OT.sorguAralikSaat * 3600) / 300}`);
```

```
seri sayisi               2400000.00
ortalama ornek/s           240000.00
tepe ornek/s               480000.00
ham gunluk GB                 539.14
1 dk ozet gunluk GB           117.50
5 dk ozet gunluk GB            23.50

basamak        gun   saklanan TB
ham              7          3.77
1 dk ozet       90         10.58
5 dk ozet      730         17.16
toplam 31.50 TB; hepsi ham ve 730 gun tutulsaydi 393.57 TB (x12.49)
6 saatlik sorgu seri basina okunan satir: ham 2160, 1 dk 360, 5 dk 72
```

Bu sayılar **hesap** sınıfındadır. Üçü tasarımı belirliyor. Yazma yolu saniyede 240.000, tepede
480.000 örnek görüyor; bu, bir isteğin bir kayda karşılık geldiği önceki vakalardan iki mertebe
yüksektir ve yazma yolunun her adımının örnek başına maliyetini belirleyici yapar. Saklama
basamakları toplamı 31,50 TB ile 40 TB kısıtının altında; aynı veri ham tutulsaydı 393,57 TB, yani
12,49 katı olurdu ve kısıt çiğnenirdi. Altı saatlik sorgu bir dakikalık özetten 360 satır okuyor,
ham basamaktan 2160; 400 satır kısıtını yalnız özet basamakları karşılıyor.

## Seyreltmenin Bedeli

Yukarıdaki tablo yalnız kazancı gösteriyor. Bedel yanıtın kendisindedir ve gerçek bir motorda
ölçülür. Aşağıdaki model bir küme kurmaz; tek bir serinin altı saatini `node:sqlite` içinde üretir,
iki tanecikte toplulaştırır ve aynı dört soruyu üç biçime birden sorar.

```js
// seyreltme.mjs — node:sqlite ile gercek bir motorda tek serinin ham ve toplulastirilmis
// bicimleri. Uretec kendi yazilmistir, tohum gorunur; olculen sey saklanan bayt, taranan satir
// ve ayni dort sorunun iki bicimden aldigi yanitin farkidir. Model oldugu yazilir.
import { DatabaseSync } from "node:sqlite";

const SURE = 21_600, TOHUM = 20260801, ESIK = 200;        // 6 saat, saniyede bir ornek
let durum = TOHUM;
const rast = () => { durum = (durum * 1103515245 + 12345) % 2147483648; return durum / 2147483648; };
const uret = (t) => {                                      // gunluk dalga + gurultu + ani sicrama
  const taban = 100 + 40 * Math.sin((2 * Math.PI * t) / 86_400) + (rast() - 0.5) * 30;
  return taban + (rast() < 0.002 ? 300 : 0);
};

const db = new DatabaseSync(":memory:");
db.exec(`CREATE TABLE ham(t INTEGER PRIMARY KEY, deger REAL);
CREATE TABLE ozet60(kova INTEGER PRIMARY KEY, adet INTEGER, toplam REAL, enBuyuk REAL);
CREATE TABLE ozet300(kova INTEGER PRIMARY KEY, adet INTEGER, toplam REAL, enBuyuk REAL);`);
db.exec("BEGIN");
const ekle = db.prepare("INSERT INTO ham VALUES(?,?)");
for (let t = 0; t < SURE; t += 1) ekle.run(t, uret(t));
db.exec("COMMIT");
for (const g of [60, 300]) db.exec(`INSERT INTO ozet${g}
  SELECT t / ${g}, count(*), sum(deger), max(deger) FROM ham GROUP BY t / ${g}`);

const yuzdelik = (a, p) => { const s = [...a].sort((x, y) => x - y); return s[Math.floor(s.length * p)]; };
const hamDeger = db.prepare("SELECT deger FROM ham").all().map((r) => r.deger);
const bayt = (t) => db.prepare("SELECT sum(pgsize) AS b FROM dbstat WHERE name = ?").get(t).b;
const satir = (t) => db.prepare(`SELECT count(*) AS n FROM ${t}`).get().n;

const HAM = { ort: hamDeger.reduce((a, b) => a + b) / SURE, enBuyuk: Math.max(...hamDeger),
  p95: yuzdelik(hamDeger, 0.95), asan: hamDeger.filter((d) => d > ESIK).length };
console.log(`model: ${SURE} ornek (saniyede bir), tohum ${TOHUM}, esik ${ESIK}\n`);
console.log("bicim".padEnd(10) + "satir".padStart(7) + "bayt".padStart(9) + "bayt/satir".padStart(12) +
  "ortalama".padStart(10) + "en buyuk".padStart(10) + "p95".padStart(9) + "esik ustu sn".padStart(14));
const yaz = (ad, n, b, o, e, p, a) => console.log(ad.padEnd(10) + String(n).padStart(7) +
  String(b).padStart(9) + (b / n).toFixed(1).padStart(12) + o.toFixed(2).padStart(10) +
  e.toFixed(2).padStart(10) + p.toFixed(2).padStart(9) + String(a).padStart(14));
yaz("ham", satir("ham"), bayt("ham"), HAM.ort, HAM.enBuyuk, HAM.p95, HAM.asan);

const OZET = {};
for (const g of [60, 300]) {
  const k = db.prepare(`SELECT adet, toplam, enBuyuk FROM ozet${g}`).all();
  const kovaOrt = k.map((r) => r.toplam / r.adet);
  const o = { ort: k.reduce((a, r) => a + r.toplam, 0) / SURE, enBuyuk: Math.max(...k.map((r) => r.enBuyuk)),
    p95: yuzdelik(kovaOrt, 0.95), asan: kovaOrt.filter((d) => d > ESIK).length * g };
  OZET[g] = o;
  yaz(`${g} sn ozet`, satir(`ozet${g}`), bayt(`ozet${g}`), o.ort, o.enBuyuk, o.p95, o.asan);
}

console.log(`\nham yanittan sapma (yuzde):`);
for (const g of [60, 300]) {
  const s = (a, b) => (((a - b) / b) * 100).toFixed(2);
  console.log(`  ${g} sn ozet -> ortalama ${s(OZET[g].ort, HAM.ort)}, en buyuk ` +
    `${s(OZET[g].enBuyuk, HAM.enBuyuk)}, p95 ${s(OZET[g].p95, HAM.p95)}, ` +
    `esik ustu sure ${s(OZET[g].asan, HAM.asan)}`);
}
for (const g of [60, 300]) {                                // ayni soru enBuyuk sutunuyla
  const n = db.prepare(`SELECT count(*) AS n FROM ozet${g} WHERE enBuyuk > ?`).get(ESIK).n;
  console.log(`  ${g} sn ozet, esik ustu sure enBuyuk ile: ${n * g} sn (ham ${HAM.asan} sn, ` +
    `x${((n * g) / HAM.asan).toFixed(1)})`);
}
console.log(`taranan satir orani: 60 sn ozet 1/${SURE / satir("ozet60")}, ` +
  `300 sn ozet 1/${SURE / satir("ozet300")}; bayt orani 1/` +
  `${(bayt("ham") / bayt("ozet60")).toFixed(1)} ve 1/${(bayt("ham") / bayt("ozet300")).toFixed(1)}`);
```

```
model: 21600 ornek (saniyede bir), tohum 20260801, esik 200

bicim       satir     bayt  bayt/satir  ortalama  en buyuk      p95  esik ustu sn
ham         21600   356352        16.5    125.84    450.17   148.84            41
60 sn ozet    360    16384        45.5    125.84    450.17   140.74             0
300 sn ozet     72     4096        56.9    125.84    450.17   139.88             0

ham yanittan sapma (yuzde):
  60 sn ozet -> ortalama 0.00, en buyuk 0.00, p95 -5.44, esik ustu sure -100.00
  300 sn ozet -> ortalama 0.00, en buyuk 0.00, p95 -6.02, esik ustu sure -100.00
  60 sn ozet, esik ustu sure enBuyuk ile: 2400 sn (ham 41 sn, x58.5)
  300 sn ozet, esik ustu sure enBuyuk ile: 9600 sn (ham 41 sn, x234.1)
taranan satir orani: 60 sn ozet 1/60, 300 sn ozet 1/300; bayt orani 1/21.8 ve 1/87.0
```

Bu sayılar **ölçüm** sınıfındadır; değerler bu koşumun tohumuna bağlıdır, sapmaların işareti ve
mertebesi bağlı değildir. Bayt sütunu sayfa taneciğine bağlı olduğu için az satırlı tabloda satır
başına bayt büyük görünüyor; kıyas için toplam bayt oranına bakılır.

Dört soru üç ayrı davranış gösteriyor. **Ortalama ve en büyük hiç bozulmuyor:** sapma her iki
tanecikte de yüzde 0,00, çünkü özet satırı toplamı, adedi ve en büyüğü taşıyor — bu üçünden
ortalama ile en büyük tam olarak yeniden kurulabiliyor. **Yüzdelik bozuluyor ama az:** p95 bir
dakikalık tanecikte yüzde 5,44, beş dakikalıkta yüzde 6,02 düşük çıkıyor, çünkü kova ortalaması
kova içindeki dağılımı düzleştiriyor. **Eşik aşımı tamamen kayboluyor:** kova ortalamasıyla
bakıldığında 41 saniyelik aşım 0 saniye görünüyor, yani yüzde 100 hata.

Aynı soruyu en büyük sütunuyla sormak da işe yaramıyor, ters yöne kaçırıyor: bir dakikalık
tanecikte 2400 saniye, beş dakikalıkta 9600 saniye çıkıyor — ham yanıtın 58,5 ve 234,1 katı, çünkü
kovanın herhangi bir saniyesindeki aşım bütün kovayı aşmış sayıyor. **Bir özet satırı, taşıdığı
sütunların yanıtladığı soruları yanıtlar; ötekiler için alt sınır ile üst sınır arasında bir
belirsizlik bırakır.**

## Tasarım

Yazma yolu bir **ileti aracısı** ve **rekabet eden tüketiciler** üzerine kurulur (Uygulama Katmanı
ve Servis Etkileşimi kursunun Kuyruklar ve İş Akışları konusu); aynı konudaki **kuyruk tabanlı yük
dengeleme** tepedeki 480.000 örnek/s'yi yazıcıların gördüğü sabit bir hıza düzleştirir. Ajan
tarafında **geri basınç** (Dayanıklılık ve Güvenilirlik kursunun Arıza Yalıtımı konusu) tampon
doluluğuyla ölçülür ve tampon dolduğunda en eski örnek atılır.

Depo bir **geniş sütun deposudur** (Veri Katmanı Ölçekleme kursunun Veri Dağıtımı konusu, Depo
Türleri): satır anahtarı seri kimliği, sütunlar zaman sıralıdır. **Parçalama** anahtarı seri
kimliğidir, düğüm adı değil — düğüm adına göre parçalansaydı 120 serisi tek parçaya düşen bir düğüm
sıcak parça yaratırdı. **Bölümleme** zamana göredir (aynı konu, Bölümleme Stratejileri) ve saklama
politikası bölüm düşürmeyle uygulanır: 7 günden eski ham bölüm tek işlemde silinir, satır satır
değil.

Toplulaştırma iki **somutlaştırılmış görünümdür** (aynı konu): tazeleme artımlıdır ve yalnız
kapanan kovayı yazar. Parametreler taneciklerdir — 60 saniye ve 300 saniye — ve gerekçeleri OT8 ile
OT9'un saklama süreleridir. Kapasite tahmini için okunan basamak beş dakikalıktır; zaman serisinden
kaynak tahminine geçişin yöntemi Başarım Karşıt Kalıpları ve İzleme kursunun Kapasite Planlama
dersinde kuruldu ve burada tekrarlanmaz, yalnız girdisi bu basamaktan gelir.

**Bilerek kullanılmayan kalıp: tekillik anahtarı defteri.** Dayanıklılık ve Güvenilirlik kursunun
Etkisiz İşlemler dersindeki defter buraya konmaz, çünkü örnek zaten (seri, zaman) çiftiyle
adreslenir ve yinelenen yazma aynı hücrenin üstüne aynı değeri yazar; ayrı bir defter örnek başına
26 baytlık kaydın yanına aynı mertebede bir kayıt daha ekler ve saniyede 240.000 kez ödenirdi.
İkincisi **federasyondur** (Veri Dağıtımı konusu): bölünecek ayrı bir işlevsel alan yok, bütün veri
tek biçimde ve tek erişim örüntüsüne sahip.

## Elenen Alternatifler

**Her şeyi ham tutmak** yüzdelik ve eşik sorularını her tarihte hatasız yanıtlar. 393,57 TB ister,
40 TB kısıtının on katı; ayrıca altı saatlik sorgu seri başına 2160 satır tarar ve 400 satır
kısıtını da çiğner. İki kısıtla birden eleniyor.

**Her şeyi beş dakikalık özet tutmak** en ucuzudur: toplam 17,16 TB ve sorgu başına 72 satır. Eşik
aşımı sorusunu yüzde 100 hatayla (0 saniye) ya da 234,1 kat şişirerek (9600 saniye) yanıtlar,
yüzdelikte 6,02 puan sapar. "Son 7 gün içinde hatasız" kısıtıyla eleniyor.

Seçilen üç basamaklı düzen 31,50 TB'da kalıyor, sorgu başına 360 satır tarıyor ve son yedi günde
ham veri durduğu için hassas soruları hatasız yanıtlıyor. **Hangi kısıt değişirse alternatif
kazanır:** eşik aşımı ve yüzdelik soruları hiç sorulmuyorsa ham basamağın varlık nedeni kalmaz, 3,77
TB'lik kalem düşer ve yazma yolu doğrudan özete yazabilir; tersine, olay incelemesi bir haftadan
eskiye bakıyorsa ham saklama uzatılır ve toplam hızla 40 TB'ı zorlar.

## Arıza Davranışı ve Feda Edilen

İleti aracısı düştüğünde ajanlar tamponlarında biriktirir; tampon dolduğunda en eski örneği atmak
**zarif bozulmadır** (Arıza Yalıtımı konusu), çünkü seri kesintisiz kalır ama tanecik geçici olarak
kabalaşır — ortalama ve en büyük sorusu yanıtlanmaya devam eder, eşik aşımı yanıtlanamaz. İşin
tersi de olur: toplulaştırma işi geri kalırsa gösterge tablosu ham basamaktan okur ve seri başına
taranan satır 360'tan 2160'a, yani altı kat artar. Bir parça düğümü düştüğünde yalnız o parçadaki
serilerin okuması etkilenir; sorular seri bazında sorulduğu için bulaşma kapsamı bir parçadır.

**Feda edilen:** yedi günden eski veride yüzdelik ve eşik aşımı soruları güvenilir yanıt almaz. Bir
ay önceki bir dalgalanmanın kaç saniye sürdüğü bu tasarımda sorulamaz; alınabilecek yanıt ya 0 ya
da gerçeğin 58,5 katıdır.

## Özet

- Ölçüt akışı örnek başına maliyeti belirleyici yapar: 2.400.000 seri, saniyede 240.000 örnek,
  tepede 480.000; tepe çarpanı önceki vakalardaki 3 değil 2, çünkü akış ajanın zamanlayıcısına
  bağlıdır.
- Saklama basamakları toplamı 31,50 TB; aynı veri ham tutulsaydı 393,57 TB, yani 12,49 katı.
- Toplulaştırma taranan satırı 60 ve 300 kat, saklanan baytı 21,8 ve 87,0 kat düşürüyor.
- Sapma soru türüne bağlıdır: ortalama ve en büyük yüzde 0,00, p95 yüzde 5,44 ile 6,02, eşik aşımı
  süresi yüzde 100 — aynı soru en büyük sütunuyla sorulduğunda 58,5 ve 234,1 kat şişiyor.
- Bu yüzden ham basamak bir başarım kalemi değil, bir **yanıtlanabilirlik** kalemidir: yedi günlük
  ham veri 3,77 TB'a mal olur ve karşılığında hassas soruların yanıtlanabildiği pencereyi tanımlar.

## Sonraki Adım

Bu vakada bir kaydı bulmak kolaydı: seri kimliği ile zaman aralığı verildiğinde okunacak satırlar
tek bir yerde ve sıralı duruyordu. Sonraki vaka bu kolaylığı kaldırır. Orada kayıtlar iki boyutlu
bir düzlemde durur ve soru "şu noktaya yakın olanlar" biçiminde gelir; yakınlığın sıralı bir
anahtarı yoktur, çünkü iki boyutu tek bir eksende sıralamanın her yolu bazı komşuları birbirinden
uzağa düşürür. Soru şuna dönüşür: böyle bir sorguyu yanıtlamak için kaç aday kayda bakmak gerekir
ve bu sayı seçilen hücre boyuna nasıl bağlıdır.
