---
title: 'Anahtar–Değer Depoları'
source: 'https://academia.sh/tr/kurslar/nosql/anahtar-deger-depolari'
course: 'İlişkisel Olmayan Veri Modelleri'
language: tr
updated: '2026-08-17T18:08:58+00:00'
license: 'CC BY-SA 4.0'
---

# Anahtar–Değer Depoları

En basit erişim modelinin sözleşmesi ve bedeli: değerin depo için saydam olmaması, aynı üye sayfasının ilişkisel şemada ve anahtar–değer modelinde gidiş ile dokunulan kayıt cinsinden ölçülmesi, alan üzerinde sorgulama yeteneğinin kaybı ve uygulamada tutulan ikincil dizinin bütün halinde okunması, anahtar tasarımının yazma çarpanı ile okuma gidiş sayısı arasında kurduğu ödünleşim.

İlişkisel Veritabanı Yönetimi kursu, model üzerine tek bir soru sormadan kapandı: tablolar,
satırlar, şema ve işlemler verili kabul edildi, ölçülen her şey o modelin içinde ölçüldü. Bu
kurs verili kabul edilen şeyi konu yapıyor ve en yalın olanından başlıyor. Anahtar–değer
deposu (key–value store) tek bir sözleşme tanır: bir anahtar verirsin, bir değer alırsın.
Deponun değer hakkında bildiği hiçbir şey yoktur.

Ailelerin adı ve dört türün erişim örüntülerine göre karşılaştırması Veri Katmanı Ölçekleme
kursunda kurulmuştu; orada dönem taraması anahtar–değer deposunda 3001 istek isterken belge
ve geniş sütun deposunda tek istekte bitiyordu, üç adımlık bir dolaşma ise çizge deposunda
derinlikten bağımsız olarak tek istekte kalıyordu. O ölçüm burada tekrarlanmaz, girdi sayılır.
Bu dersin sorusu daha dardır ve **veri modelinin kendisine** bakar: değerin içine bakamayan bir
depo, kütüphane katalog ve ödünç verisini nasıl taşır, hangi işi ucuzlatır ve hangi yeteneği
kaybeder.

## Modelin Sözleşmesi

Anahtar–değer modelinde bir kayıt iki parçadır: eşsiz bir anahtar ve depo için anlamı olmayan
bir bayt dizisi. Depo anahtarı bilir, değeri bilmez. Bu tek cümleden üç sonuç çıkar. Değer
üzerinde koşul yazılamaz ve değerin bir parçası güncellenemez, çünkü depo alan diye bir kavram
tanımaz. İki kaydın birleştirilmesi diye bir işlem de yoktur, çünkü birleştirme alanların
eşleşmesiyle tanımlıdır.

Karşılığında elde edilen şey erişimin sabit adımda kalmasıdır: anahtar bilindiğinde kayıt tek
gidişte gelir ve bu, kayıt sayısından bağımsızdır.

Ölçüm için kütüphane verisi iki modelde birden kurulur; ilişkisel taraf `node:sqlite` ile
gerçekten kurulur. **NS1:** katalog 20.000 üye taşır ve her üyenin 1 ile 11 arası ödüncü
vardır; toplam ödünç 119.993. **NS2:** değerler JSON ile seri hale getirilir; okunan ve yazılan
baytlar bu gösterimden sayılır, ilişkisel tarafta sonuç kümesi aynı gösterime çevrilir.

```js
// kv/model.mjs — ayni uye sayfasinin iliskisel semada ve anahtar-deger modelinde
// olculmesi. Iliskisel taraf node:sqlite ile kurulur; sayilar kosumdan bagimsizdir.
import { DatabaseSync } from "node:sqlite";

const UYE = 20_000, SEHIR = ["Ankara", "Istanbul", "Izmir", "Bursa", "Konya"];
function* uyeler() {                       // uye i'nin 1 + (i % 11) oduncu vardir
  for (let i = 1; i <= UYE; i += 1) {
    const odunc = Array.from({ length: 1 + (i % 11) }, (_, j) => ({
      odunc_id: i * 100 + j, kitap_id: 1 + ((i * 7 + j * 13) % 200_000),
      alis_tarihi: `2024-${String(1 + ((i + j) % 12)).padStart(2, "0")}-15`,
      ceza_kurus: (i * 37 + j * 11) % 900,
    }));
    yield { uye_id: i, ad: `Uye ${i}`, sehir: SEHIR[i % 5], odunc,
      ceza_kurus: odunc.reduce((t, o) => t + o.ceza_kurus, 0) };
  }
}

class AnahtarDegerDeposu {                 // deger deponun gozunde bir bayt dizisidir
  #tablo = new Map();
  gidis = 0; kayit = 0; bayt = 0;
  yaz(anahtar, deger) { this.gidis += 1; this.kayit += 1;
    const s = JSON.stringify(deger); this.bayt += Buffer.byteLength(s);
    this.#tablo.set(anahtar, s); }
  oku(anahtar) { this.gidis += 1; const s = this.#tablo.get(anahtar);
    if (s === undefined) return undefined;
    this.kayit += 1; this.bayt += Buffer.byteLength(s); return JSON.parse(s); }
  sayaclari_sifirla() { this.gidis = 0; this.kayit = 0; this.bayt = 0; }
}

const db = new DatabaseSync(":memory:");
db.exec(`CREATE TABLE uye (uye_id INTEGER PRIMARY KEY, ad TEXT NOT NULL,
           sehir TEXT NOT NULL, ceza_kurus INTEGER NOT NULL);
         CREATE TABLE odunc (odunc_id INTEGER PRIMARY KEY, uye_id INTEGER NOT NULL,
           kitap_id INTEGER NOT NULL, alis_tarihi TEXT NOT NULL, ceza_kurus INTEGER NOT NULL);`);
const ekleU = db.prepare("INSERT INTO uye VALUES (?,?,?,?)");
const ekleO = db.prepare("INSERT INTO odunc VALUES (?,?,?,?,?)");
const depo = new AnahtarDegerDeposu();
db.exec("BEGIN");
for (const u of uyeler()) {
  ekleU.run(u.uye_id, u.ad, u.sehir, u.ceza_kurus);
  for (const o of u.odunc) ekleO.run(o.odunc_id, u.uye_id, o.kitap_id, o.alis_tarihi, o.ceza_kurus);
  depo.yaz(`uye:${u.uye_id}`, u);          // ayni bilgi tek deger olarak
}
db.exec("COMMIT");
db.exec("CREATE INDEX odunc_uye ON odunc(uye_id); CREATE INDEX uye_ceza ON uye(ceza_kurus);");

const bayt = (x) => Buffer.byteLength(JSON.stringify(x));
const HEDEF = 4242;
console.log(`model: ${UYE} uye, ${db.prepare("SELECT count(*) n FROM odunc").get().n} odunc; ` +
  `hedef uye ${HEDEF}, odunc sayisi ${1 + (HEDEF % 11)}`);
console.log(db.prepare("EXPLAIN QUERY PLAN SELECT * FROM odunc WHERE uye_id = ?").all()[0].detail);

const satir = [];
{ const u = db.prepare("SELECT uye_id, ad, sehir, ceza_kurus FROM uye WHERE uye_id = ?").get(HEDEF);
  const o = db.prepare("SELECT odunc_id, kitap_id, alis_tarihi, ceza_kurus FROM odunc WHERE uye_id = ?").all(HEDEF);
  satir.push(["iliskisel, iki sorgu", 2, 1 + o.length, bayt(u) + bayt(o)]); }
{ const r = db.prepare(`SELECT u.ad, u.sehir, u.ceza_kurus, o.odunc_id, o.kitap_id,
    o.alis_tarihi FROM uye u JOIN odunc o ON o.uye_id = u.uye_id WHERE u.uye_id = ?`).all(HEDEF);
  satir.push(["iliskisel, tek birlestirme", 1, r.length, bayt(r)]); }
{ depo.sayaclari_sifirla(); const v = depo.oku(`uye:${HEDEF}`);
  satir.push([`anahtar-deger, tek anahtar (${v.odunc.length} odunc)`, depo.gidis, depo.kayit, depo.bayt]); }

console.log(`\n${"yol".padEnd(40)}${"gidis".padStart(7)}${"kayit".padStart(7)}${"bayt".padStart(7)}`);
for (const [a, g, k, b] of satir)
  console.log(a.padEnd(40) + String(g).padStart(7) + String(k).padStart(7) + String(b).padStart(7));
```

```
model: 20000 uye, 119993 odunc; hedef uye 4242, odunc sayisi 8
SEARCH odunc USING INDEX odunc_uye (uye_id=?)

yol                                       gidis  kayit   bayt
iliskisel, iki sorgu                          2      9    714
iliskisel, tek birlestirme                    1      8    913
anahtar-deger, tek anahtar (8 odunc)          1      1    723
```

Sayılar **ölçüm** sınıfındadır: gerçekten koşan iki motordan gelir, belirlenimlidir.

Üye sayfası anahtar–değer modelinde **tek gidiş, tek kayıt**tır. İlişkisel şemada aynı sayfa ya
iki sorgu ve dokuz kayıt ister, ya da tek birleştirmeye indirilir; birleştirme gidişi bire
düşürür ama üye alanlarını her ödünç satırında tekrarladığı için taşınan baytı 714'ten 913'e
çıkarır. Anahtar–değer değeri 723 bayttır: aynı bilgi, tekrarsız, tek parça.

Buradaki kazanç birleştirmenin yokluğundan değil, **modellemenin okuma birimine göre
yapılmasından** gelir. Değer, uygulamanın bir seferde istediği şeyin tamamıdır. Aynı şey
ilişkisel şemada da yapılabilir — Veri Modelleme ve İlişkisel Kuram kursunda ölçülen
denormalizasyondur — ama orada bir karardır; burada modelin tek biçimi budur.

## Sorgulanabilirliğin Kaybı

Kütüphanenin ikinci sorusu şudur: cezası bir eşiği aşan üyeler kimlerdir. İlişkisel şemada bu,
üye tablosundaki bir alan üzerinde dizin gerektirir; anahtar–değer deposunda böyle bir alan
yoktur.

```js
// kv/sorgu.mjs — "cezasi esikten buyuk uyeler" sorusunun ayni veri uzerinde uc yolu.
// Uretec kv/model.mjs ile birebir aynidir; blok kendi basina calisir.
import { DatabaseSync } from "node:sqlite";

const UYE = 20_000, SEHIR = ["Ankara", "Istanbul", "Izmir", "Bursa", "Konya"], ESIK = 8000;
function* uyeler() {
  for (let i = 1; i <= UYE; i += 1) {
    const odunc = Array.from({ length: 1 + (i % 11) }, (_, j) => ({
      odunc_id: i * 100 + j, kitap_id: 1 + ((i * 7 + j * 13) % 200_000),
      alis_tarihi: `2024-${String(1 + ((i + j) % 12)).padStart(2, "0")}-15`,
      ceza_kurus: (i * 37 + j * 11) % 900,
    }));
    yield { uye_id: i, ad: `Uye ${i}`, sehir: SEHIR[i % 5], odunc,
      ceza_kurus: odunc.reduce((t, o) => t + o.ceza_kurus, 0) };
  }
}
class AnahtarDegerDeposu {
  #tablo = new Map();
  gidis = 0; kayit = 0; bayt = 0;
  yaz(a, d) { const s = JSON.stringify(d); this.#tablo.set(a, s); }
  oku(a) { this.gidis += 1; const s = this.#tablo.get(a);
    if (s === undefined) return undefined;
    this.kayit += 1; this.bayt += Buffer.byteLength(s); return JSON.parse(s); }
  anahtarlar() { return [...this.#tablo.keys()].filter((a) => a.startsWith("uye:")); }
  sifirla() { this.gidis = 0; this.kayit = 0; this.bayt = 0; }
}

const db = new DatabaseSync(":memory:");
db.exec(`CREATE TABLE uye (uye_id INTEGER PRIMARY KEY, ad TEXT NOT NULL,
           sehir TEXT NOT NULL, ceza_kurus INTEGER NOT NULL);`);
const ekle = db.prepare("INSERT INTO uye VALUES (?,?,?,?)");
const depo = new AnahtarDegerDeposu();
const dizin = [];                          // uygulamanin elle tuttugu ikincil dizin
db.exec("BEGIN");
for (const u of uyeler()) {
  ekle.run(u.uye_id, u.ad, u.sehir, u.ceza_kurus);
  depo.yaz(`uye:${u.uye_id}`, u);
  dizin.push([u.ceza_kurus, u.uye_id]);
}
db.exec("COMMIT");
db.exec("CREATE INDEX uye_ceza ON uye(ceza_kurus);");
dizin.sort((x, y) => x[0] - y[0]);
depo.yaz("dizin:ceza", dizin);             // dizin de bir degerdir: butun halinde okunur

const bayt = (x) => Buffer.byteLength(JSON.stringify(x));
const satir = [];
{ const r = db.prepare("SELECT uye_id FROM uye WHERE ceza_kurus > ?").all(ESIK);
  satir.push(["iliskisel, ceza dizini", 1, r.length, bayt(r), r.length]); }
{ depo.sifirla(); const bulunan = [];
  for (const a of depo.anahtarlar()) { const u = depo.oku(a); if (u.ceza_kurus > ESIK) bulunan.push(u.uye_id); }
  satir.push(["anahtar-deger, anahtar taramasi", depo.gidis, depo.kayit, depo.bayt, bulunan.length]); }
{ depo.sifirla(); const d = depo.oku("dizin:ceza");
  const bulunan = d.filter(([c]) => c > ESIK).map(([, id]) => depo.oku(`uye:${id}`).uye_id);
  satir.push(["anahtar-deger, uygulama dizini", depo.gidis, depo.kayit, depo.bayt, bulunan.length]); }

console.log(`model: ${UYE} uye, esik ${ESIK} kurus; ` +
  `iliskisel plan: ${db.prepare("EXPLAIN QUERY PLAN SELECT uye_id FROM uye WHERE ceza_kurus > ?").all()[0].detail}`);
console.log(`dizin:ceza degerinin boyutu ${bayt(dizin)} bayt, girdi sayisi ${dizin.length}`);
console.log(`\n${"yol".padEnd(32)}${"gidis".padStart(7)}${"kayit".padStart(7)}${"okunan bayt".padStart(13)}${"sonuc".padStart(7)}`);
for (const [a, g, k, b, n] of satir)
  console.log(a.padEnd(32) + String(g).padStart(7) + String(k).padStart(7) +
    String(b).padStart(13) + String(n).padStart(7));
```

```
model: 20000 uye, esik 8000 kurus; iliskisel plan: SEARCH uye USING COVERING INDEX uye_ceza (ceza_kurus>?)
dizin:ceza degerinin boyutu 243132 bayt, girdi sayisi 20000

yol                               gidis  kayit  okunan bayt  sonuc
iliskisel, ceza dizini                1    359         5903    359
anahtar-deger, anahtar taramasi   20000  20000     11311097    359
anahtar-deger, uygulama dizini      360    360       584880    359
```

Üç yol da aynı 359 üyeyi buluyor; ayrım işin nerede yapıldığındadır. İlişkisel motor kapsayan
bir dizin üzerinden **tek gidişte** yalnız eşleşen 359 kayda dokunuyor ve 5.903 bayt taşıyor.
Anahtar–değer deposunda süzme uygulamada olduğu için bütün anahtar uzayı geziliyor: 20.000
gidiş ve 11,3 MB — sonucun **iki bin katı** veri, sonucu bulabilmek için okunuyor.

Üçüncü satır asıl dersi taşır. Uygulama, ceza değerine göre sıralı bir liste tutup onu tek
anahtara yazdığında gidiş 20.000'den 360'a iniyor. Ama bu liste bir dizin değil bir
**değerdir**: her sorguda bütün halinde, 243.132 baytın tamamı okunur. İlişkisel dizin bir
ağaçtır ve motor onun içine inebilir; uygulama dizini yalnız okunup çözümlenebilir. Okunan bayt
bu yüzden 584.880'de kalıyor — ilişkisel yolun yüz katı. Üstelik iki anahtara yapılan iki yazma
tek bir işlem değildir; kayıt ile dizin arasında kalıcı bir tutarsızlık penceresi açılır.

## Anahtar Tasarımı Tek Ayardır

İlişkisel şemada tasarımcının elinde tablo, sütun, kısıt ve dizin vardır. Anahtar–değer
modelinde tek bir ayar vardır: anahtarın ne olduğu ve değerin sınırının nereden geçtiği.

Bir ödüncün eklenmesi, bütünsel değer tasarımında **oku-değiştir-yaz (read-modify-write)**
demektir: bütün değer okunur, diziye bir kayıt eklenir, bütün değer geri yazılır. Ayrı anahtar
tasarımında yalnız yeni kayıt yazılır.

```js
// kv/anahtar.mjs — tek oduncun eklenmesi iki anahtar tasariminda, ve ayni tasarimlarin
// uye sayfasi okumasina bedeli. Butun bayt sayilari gercek seri hale getirmeden gelir.
class AnahtarDegerDeposu {
  #tablo = new Map(); #sirali = false;
  gidis = 0; kayit = 0; okunan = 0; yazilan = 0;
  constructor(sirali) { this.#sirali = sirali; }
  yaz(a, d) { const s = JSON.stringify(d); this.gidis += 1; this.kayit += 1;
    this.yazilan += Buffer.byteLength(a) + Buffer.byteLength(s); this.#tablo.set(a, s); }
  oku(a) { this.gidis += 1; const s = this.#tablo.get(a); if (s === undefined) return undefined;
    this.kayit += 1; this.okunan += Buffer.byteLength(s); return JSON.parse(s); }
  onek(p) {                                // yalniz sirali anahtar uzayinda vardir
    if (!this.#sirali) throw new Error("karma anahtar uzayinda onek taramasi yok");
    this.gidis += 1; const c = [];
    for (const [a, s] of [...this.#tablo].sort(([x], [y]) => (x < y ? -1 : x > y ? 1 : 0)))
      if (a.startsWith(p)) { this.kayit += 1; this.okunan += Buffer.byteLength(s); c.push(JSON.parse(s)); }
    return c; }
  sifirla() { this.gidis = 0; this.kayit = 0; this.okunan = 0; this.yazilan = 0; }
}
const odunc = (i, j) => ({ odunc_id: i * 1000 + j, kitap_id: 1 + ((i * 7 + j * 13) % 200_000),
  alis_tarihi: `2024-${String(1 + ((i + j) % 12)).padStart(2, "0")}-15`, ceza_kurus: (i * 37 + j * 11) % 900 });

console.log(`tek oduncun eklenmesi (yeni kaydin kendisi ${Buffer.byteLength(JSON.stringify(odunc(1, 0)))} bayt)`);
console.log(`${"odunc sayisi k".padStart(14)}${"butunsel deger: yazilan".padStart(25)}` +
  `${"carpan".padStart(8)}${"ayri anahtar: yazilan".padStart(23)}${"carpan".padStart(8)}`);
for (const k of [1, 8, 64, 512]) {
  const butun = new AnahtarDegerDeposu(true), ayri = new AnahtarDegerDeposu(true);
  const u = { uye_id: 7, ad: "Uye 7", sehir: "Izmir", odunc: Array.from({ length: k }, (_, j) => odunc(7, j)) };
  butun.yaz("uye:0007", u);
  for (let j = 0; j < k; j += 1) ayri.yaz(`uye:0007:odunc:${String(j).padStart(6, "0")}`, odunc(7, j));
  const yeni = odunc(7, k);
  butun.sifirla(); ayri.sifirla();
  const v = butun.oku("uye:0007"); v.odunc.push(yeni); butun.yaz("uye:0007", v);   // oku-degistir-yaz
  ayri.yaz(`uye:0007:odunc:${String(k).padStart(6, "0")}`, yeni);                  // yalniz yeni kayit
  console.log(String(k).padStart(14) + String(butun.yazilan).padStart(25) +
    (butun.yazilan / ayri.yazilan).toFixed(1).padStart(8) +
    String(ayri.yazilan).padStart(23) + "1.0".padStart(8));
}

const K = 64;
const kurulum = (sirali) => { const d = new AnahtarDegerDeposu(sirali);
  for (let j = 0; j < K; j += 1) d.yaz(`uye:0007:odunc:${String(j).padStart(6, "0")}`, odunc(7, j));
  d.yaz("uye:0007", { uye_id: 7, ad: "Uye 7", sehir: "Izmir" });
  d.yaz("uye:0007:odunc-listesi", Array.from({ length: K }, (_, j) => j));
  d.sifirla(); return d; };
console.log(`\nayni uyenin ${K} oduncluk sayfasinin okunmasi`);
console.log(`${"anahtar uzayi".padEnd(34)}${"gidis".padStart(7)}${"kayit".padStart(7)}${"okunan bayt".padStart(13)}`);
const s = kurulum(true); s.oku("uye:0007"); s.onek("uye:0007:odunc:");
console.log("sirali, onek taramasi".padEnd(34) + String(s.gidis).padStart(7) +
  String(s.kayit).padStart(7) + String(s.okunan).padStart(13));
const h = kurulum(false); h.oku("uye:0007");
for (const j of h.oku("uye:0007:odunc-listesi")) h.oku(`uye:0007:odunc:${String(j).padStart(6, "0")}`);
console.log("karma, uygulama anahtar listesi".padEnd(34) + String(h.gidis).padStart(7) +
  String(h.kayit).padStart(7) + String(h.okunan).padStart(13));
```

```
tek oduncun eklenmesi (yeni kaydin kendisi 73 bayt)
odunc sayisi k  butunsel deger: yazilan  carpan  ayri anahtar: yazilan  carpan
             1                      211     2.2                     96     1.0
             8                      748     7.7                     97     1.0
            64                     5053    52.6                     96     1.0
           512                    39936   407.5                     98     1.0

ayni uyenin 64 oduncluk sayfasinin okunmasi
anahtar uzayi                       gidis  kayit  okunan bayt
sirali, onek taramasi                   2     65         4895
karma, uygulama anahtar listesi        66     66         5078
```

Üst tablo **yazma çarpanını (write amplification)** gösteriyor: eklenen bilgi her satırda 73
baytken, bütünsel değer tasarımında yazılan bayt 211'den 39.936'ya çıkıyor. Çarpan üyenin ödünç
sayısıyla doğru orantılı büyür ve 512 ödünçte 407 kata varır. Ayrı anahtar tasarımında yazılan
bayt üye büyüdükçe değişmiyor: 96 ile 98 bayt arası, çarpan 1.

Alt tablo bunun bedelini gösteriyor. Ödünçler ayrı anahtarlara dağıldığında üye sayfası artık
tek gidişte gelmiyor. **Sıralı anahtar uzayında** — anahtarların sözlük sırasında tutulduğu
depolarda — bir önek taraması (prefix scan) tek istek sayılır ve 2 gidişte biter. **Karma
anahtar uzayında** önek diye bir kavram yoktur, çünkü ardışık anahtarlar ardışık yerlere
düşmez; uygulama ayrıca bir anahtar listesi tutmak ve her ödüncü tek tek çekmek zorunda kalır:
66 gidiş. Aynı 65 kayıt, aynı bayt mertebesi, otuz üç kat gidiş.

İki tablo birlikte okunduğunda modelin tek kuralı çıkar: **anahtar–değer deposunda değerin
sınırı, uygulamanın erişim biriminin sınırıdır.** Sınır geniş tutulursa okuma tek gidişe iner
ve yazma çarpanı büyür; dar tutulursa yazma ucuzlar ve okuma, anahtar uzayının sıralı olup
olmamasına bağımlı hâle gelir. Karar şemayla değil anahtar adlandırmasıyla verilir; sonradan
değiştirmek bütün veriyi yeniden yazmaktır.

## Özet

- Anahtar–değer modeli tek bir sözleşme tanır: anahtar verilir, değer alınır. Depo değerin
  içini görmez; bu yüzden alan üzerinde koşul, kısmi güncelleme ve birleştirme yoktur.
- Üye sayfası anahtar–değer modelinde 1 gidiş ve 1 kayıt; ilişkisel şemada 2 gidiş ve 9 kayıt,
  ya da tek birleştirmeyle 1 gidiş ve 8 kayıt karşılığında 714 yerine 913 bayt.
- Alan üzerinde sorgulama kaybolur: cezası eşiği aşan 359 üye ilişkisel dizinle 1 gidişte ve
  5.903 baytta bulunurken, anahtar taramasıyla 20.000 gidiş ve 11,3 MB istiyor.
- Uygulamanın tuttuğu ikincil dizin bir ağaç değil bir değerdir: gidişi 360'a indirir ama
  243.132 baytlık listeyi her sorguda bütün halinde okutur ve kayıtla arasında tutarsızlık
  penceresi bırakır.
- Anahtar tasarımı tek ayardır: bütünsel değerde 73 baytlık bir ekleme 512 ödünçlü üyede 39.936
  bayt yazdırır (çarpan 407), ayrı anahtarda çarpan 1 kalır ama üye sayfası sıralı anahtar
  uzayında 2, karma anahtar uzayında 66 gidiş ister.

## Sonraki Adım

Bu dersin bütün kazancı tek bir varsayıma dayanıyordu: uygulamanın istediği şey her seferinde
anahtarı bilinen tek bir bütündür. Varsayım tutmadığı anda model çöküyor — değerin içindeki bir
alana göre süzme, 20.000 gidiş demek. Ortada duran soru şudur: depo değerin içini **görebilse**
ne değişirdi. Sonraki ders bu aileyi ele alıyor ve iki şeyi ölçüyor: iç içe bir yapının tek
okumada gelmesiyle aynı verinin ilişkisel birleştirmeyle kurulması arasındaki fark, ve şema
esnekliğinin okuma tarafına yıktığı yük — alanın var olup olmadığını her okumada denetlemenin
bedeli.
