İçeriğe geç
academia.sh

Ders 23 / 23

Erişim Denetimi

Arama kümesinin yetki yüzeyi: aynı sorgunun okuyucu, görevli ve kapsamsız anahtar altında döndürdüğü dizin, belge ve alan kümesinin sayılması, belge düzeyi süzmenin puanlamadan önce mi sonra mı uygulandığının ilk on sonuca ve derin sıraya etkisinin ölçülmesi, süzülen belgelerin sayaç üzerinden sızdırdığı bilginin gösterilmesi, kapsamı yazılmamış bir anahtarın eriştiği dizin sayısıyla süresi dolmuş anahtarın yanıtsız bıraktığı sorgunun sayılması ve kursun yirmi üç dersinin küme, sıra ve bedel tablosunda toplanması.

İçindekiler

Önceki ders bir dizinin bütün olarak kopyalanmasını ve yeniden üretilmesini ele aldı; ortak varsayımı, kümeye erişen herkesin bütün dizini görmeye yetkili olduğuydu. Kütüphane kataloğunda bu doğru değildir: bağış koşuluyla kapatılmış kayıtlar, ödünç geçmişi ve edinim yazışmaları aynı kümede durur ama herkese açık değildir. Bu ders kimlik doğrulamayı değil, arama kümesinin yetki yüzeyini ölçer.

Yetki Yüzeyi

Bir rol burada üç şeyin çarpımıdır: erişilebilen dizinler, uygulanan belge süzgeci ve görülen alanlar. Düzenekte üç dizin var — açık katalog, ödünç kayıtları, edinim kaynağı — ve katalog kayıtlarının bir bölümünde yalnız görevlilerin gördüğü bir iç not alanı bulunuyor. Küme yine süreç içi bir modeldir: bir rol yalnızca bu üçlüdür.

AK21 — bağış partisi 1500 kayıttır, tek konudan gelir ve erişimi bağış koşuluyla kısıtlanmıştır. Doğrusal etkilidir: parti büyüdükçe aşağıdaki istatistik sapması büyür. AK22 — ödünç ve kaynak kayıtları ilgili kitabın ad ve konu terimlerini taşır. AK23 — anahtar yüz sorguluk akışın altmışıncısında dolar.

// kume/yetki.mjs — dizin, belge ve alan duzeyinde erisim denetimi. Uretec ve ters dizin onceki
// derslerle ayni. Yetki SUREC ICI BIR MODELDIR: kimlik dogrulama yoktur, bir rol yalnizca
// (dizinler, belge suzgeci, alanlar) uclusudur.

const ORTAK = ["kitap", "yazar", "eser", "metin", "bolum", "baski", "sayfa", "dil", "cilt", "yayin"];
const OZEL = {
  cocuk: ["masal", "resimli", "okul", "oyun", "hayvan", "cizgi"], oyku: ["kisa", "anlati", "derleme", "gunluk", "yalnizlik", "kasaba"],
  roman: ["kahraman", "kent", "kusak", "ev", "yolculuk", "mektup"], tarih: ["imparatorluk", "belge", "arsiv", "savas", "yuzyil", "vakayiname"],
  gezi: ["deniz", "yol", "harita", "sehir", "liman", "gemi"], siir: ["dize", "olcu", "imge", "ses", "sessizlik", "kafiye"],
  deneme: ["dusunce", "elestiri", "okuma", "zaman", "not", "soylesi"], bilim: ["olcum", "deney", "kuram", "veri", "gozlem", "denklem"],
};
const NADIR = ["fener", "kuyu", "ipek", "kule", "bahce", "kar", "ada", "koru", "tas", "cinar", "kirlangic", "demirci", "pusula", "kehribar"];
const KONU = Object.keys(OZEL);

function derlem({ adet = 4000, tohum = 20260731 } = {}) {
  let s = tohum % 2147483647;
  const r = () => (s = (s * 48271) % 2147483647) / 2147483647;
  const sec = (a) => a[Math.floor(r() * a.length)], belge = [];
  for (let i = 1; i <= adet; i += 1) {
    const konu = sec(KONU), oz = OZEL[konu], soz = [sec(oz), sec(NADIR)];
    if (r() < 0.5) soz.push(sec(ORTAK));
    for (let j = 0, n = 10 + Math.floor(r() * 7); j < n; j += 1)
      soz.push(r() < 0.45 ? sec(ORTAK) : r() < 0.85 ? sec(oz) : sec(NADIR));
    belge.push({ id: i, konu, yil: 1990 + Math.floor(r() * 36), metin: [soz[0], soz[1], konu, ...soz.slice(2)].join(" ") });
  }
  return belge;
}

function dizinle(belge) {
  const gonderi = new Map(), uzunluk = new Map();
  for (const d of belge) {
    const t = d.metin.split(" "), sayim = new Map();
    for (const x of t) sayim.set(x, (sayim.get(x) ?? 0) + 1);
    uzunluk.set(d.id, t.length);
    for (const [x, n] of sayim) {
      if (!gonderi.has(x)) gonderi.set(x, []);
      gonderi.get(x).push([d.id, n]);                       // gonderi girisi: kimlik + siklik
    }
  }
  const ort = [...uzunluk.values()].reduce((a, b) => a + b, 0) / (belge.length || 1);
  return { gonderi, uzunluk, N: belge.length, ort };
}

// Puanlama: terim sikligi, ters belge sikligi ve uzunluk. Puan, ISTATISTIGI HANGI DIZIN
// VERIYORSA ondan gelir; dersin ikinci olcumu tam olarak bu secimi karsilastirir.
function ara(dz, terim, k) {
  const N = dz.N, ort = dz.ort, puan = new Map();
  let taranan = 0;
  for (const t of terim) {
    const g = dz.gonderi.get(t) ?? [], df = g.length;
    const idf = Math.log(1 + (N - df + 0.5) / (df + 0.5));
    for (const [id, tf] of g) {
      taranan += 1;
      const norm = tf + 1.2 * (0.25 + 0.75 * dz.uzunluk.get(id) / ort);
      puan.set(id, (puan.get(id) ?? 0) + idf * tf * 2.2 / norm);
    }
  }
  const sirali = [...puan].sort((a, b) => b[1] - a[1] || a[0] - b[0]).slice(0, k);
  return { aday: sirali.map(([id, p]) => ({ id, p })), taranan, eslesen: puan.size };
}


const K = 10, AKIS = 100, OMUR = 60, KISITLI = 1500;
const SORGU = ["oyku", "fener", "kitap", "bagis"];   // bagis kaydi olan, adinda fener gecen oyku kitabi
const s = (x, n) => String(x).padStart(n);

// Katalog: 4000 acik kayit + bagis kosuluyla kisitli, tek konudan gelen bir parti (ayri tohum,
// kimlikler 4000 sonrasina tasinir). Odunc ve kaynak ayri dizinlerdir.
const ACIK = derlem({ adet: 4000 });
const KATALOG = [...ACIK, ...derlem({ adet: 20000, tohum: 20260801 }).filter((d) => d.konu === "oyku")
  .slice(0, KISITLI).map((d, i) => ({ ...d, id: 4001 + i, kisitli: true }))];
const ODUNC = derlem({ adet: 900, tohum: 20260901 }).map((d) => ({ ...d, id: 20000 + d.id }));
const KAYNAK = derlem({ adet: 400, tohum: 20261001 }).map((d) => ({ ...d, id: 30000 + d.id }));

// Ic not alani: edinim yazismasi, kendi sozlugu ve tohumu var.
const NOT_SOZ = ["bagis", "kosul", "sart", "edinim", "satin", "alma", "yazisma", "fatura", "vasiyet"];
let n = 20261101;
const r = () => (n = (n * 48271) % 2147483647) / 2147483647;
for (const d of KATALOG) if (r() < 0.35)
  d.not = Array.from({ length: 3 + Math.floor(r() * 4) }, () => NOT_SOZ[Math.floor(r() * 9)]).join(" ");

// Bir (belge kumesi, alan) cifti icin dizin; "not" alaninda yalnizca notu olan belge vardir.
const kur = (belge, alan) => dizinle(alan === "not"
  ? belge.filter((d) => d.not).map((d) => ({ id: d.id, metin: d.not })) : belge);

// Sorgu her (dizin, alan) ciftinde puanlanir ve puanlar toplanir; suz belge duzeyi denetimidir.
// ham suzmeden onceki eslesmedir: sayaca bu yazilirsa kisitli belgeler disari sizar.
function sor(dizinler, terim, suz = () => true) {
  const puan = new Map();
  let taranan = 0, ham = 0;
  for (const dz of dizinler) {
    const c = ara(dz, terim, Infinity);
    taranan += c.taranan; ham += c.eslesen;
    for (const a of c.aday) if (suz(a.id)) puan.set(a.id, (puan.get(a.id) ?? 0) + a.p);
  }
  const y = [...puan].sort((a, b) => b[1] - a[1] || a[0] - b[0]).map(([id]) => id);
  return { tum: y, ilk: y.slice(0, K), eslesen: y.length, taranan, ham };
}
const ortak = (a, b) => a.filter((x) => b.includes(x)).length;

console.log(`katalog ${KATALOG.length} belge (4000 acik + ${KISITLI} bagis kosuluyla kisitli), odunc ${ODUNC.length}, kaynak`);
console.log(`${KAYNAK.length}, not alani ${KATALOG.filter((d) => d.not).length} kayitta. Tohum 20260731 ve 20261101. Sorgu "oyku fener kitap bagis".\n`);
console.log("rol / anahtar         | dizin | belge | alan       | yanitlanan | taranan giris | eslesen | ilk 3 sonuc");
console.log("----------------------|-------|-------|------------|------------|---------------|---------|------------------");
for (const [ad, kume, izin, alan, yanit] of [
  ["okuyucu", [KATALOG], (d) => !d.kisitli, ["metin"], AKIS],
  ["gorevli", [KATALOG, ODUNC], () => true, ["metin", "not"], AKIS],
  ["gorevli, not kapali", [KATALOG, ODUNC], () => true, ["metin"], AKIS],
  ["kapsamsiz anahtar", [KATALOG, ODUNC, KAYNAK], () => true, ["metin", "not"], AKIS],
  ["suresi dolmus anahtar", [], () => true, [], OMUR],
]) {
  const c = sor(kume.flatMap((x) => alan.map((a) => kur(x.filter(izin), a))), SORGU);
  console.log(`${ad.padEnd(21)} | ${s(kume.length, 5)} | ${s(kume.reduce((t, x) => t + x.filter(izin).length, 0), 5)} | ` +
    `${(alan.join(", ") || "-").padEnd(10)} | ${s(`${yanit}/${AKIS}`, 10)} | ${s(c.taranan, 13)} | ${s(c.eslesen, 7)} | ${c.ilk.slice(0, 3).join(" ") || "-"}`);
}

const once = sor([kur(ACIK, "metin")], SORGU);
const sonra = sor([kur(KATALOG, "metin")], SORGU, (id) => id <= 4000);
console.log("\nbelge duzeyi suzme (okuyucu rolu, iki uygulama, ayni 4000 acik kayit):");
console.log("uygulama  | istatistigi veren kume  | eslesen | raporlanan sayac | ilk 10 ortak | yer degistiren belge");
for (const [ad, kume, c, sayac] of [["once suz", "izinli 4000 kayit", once, once.eslesen],
  ["sonra suz", "tam katalog 5500", sonra, sonra.ham]]) {
  console.log(`${ad.padEnd(9)} | ${kume.padEnd(23)} | ${s(c.eslesen, 7)} | ${s(sayac, 16)} | ` +
    `${s(ortak(c.ilk, once.ilk) + "/10", 12)} | ${s(c.tum.filter((x, i) => once.tum[i] !== x).length, 20)}`);
}
console.log(`ilk 10, once suz : ${once.ilk.join(" ")}`);
console.log(`ilk 10, sonra suz: ${sonra.ilk.join(" ")}`);

console.log(`\nkosumdan bagimsiz: kapsami yazilmamis anahtar en yetkili rolle ayni ucluyu alir ve` +
  ` suresi dolmus anahtar ${AKIS - OMUR} sorguyu yanitsiz birakir.`);
katalog 5500 belge (4000 acik + 1500 bagis kosuluyla kisitli), odunc 900, kaynak
400, not alani 1931 kayitta. Tohum 20260731 ve 20261101. Sorgu "oyku fener kitap bagis".

rol / anahtar         | dizin | belge | alan       | yanitlanan | taranan giris | eslesen | ilk 3 sonuc
----------------------|-------|-------|------------|------------|---------------|---------|------------------
okuyucu               |     1 |  4000 | metin      |    100/100 |          2998 |    2463 | 1613 3589 2806
gorevli               |     2 |  6400 | metin, not |    100/100 |          6882 |    4743 | 4551 4589 5265
gorevli, not kapali   |     2 |  6400 | metin      |    100/100 |          6130 |    4542 | 20332 20557 20765
kapsamsiz anahtar     |     3 |  6800 | metin, not |    100/100 |          7175 |    4986 | 4551 4589 5265
suresi dolmus anahtar |     0 |     0 | -          |     60/100 |             0 |       0 | -

belge duzeyi suzme (okuyucu rolu, iki uygulama, ayni 4000 acik kayit):
uygulama  | istatistigi veren kume  | eslesen | raporlanan sayac | ilk 10 ortak | yer degistiren belge
once suz  | izinli 4000 kayit       |    2463 |             2463 |        10/10 |                    0
sonra suz | tam katalog 5500        |    2463 |             3963 |         7/10 |                 1433
ilk 10, once suz : 1613 3589 2806 493 1188 1100 3214 308 476 1012
ilk 10, sonra suz: 1613 3589 2806 493 1188 3127 1100 3214 3695 3561

kosumdan bagimsiz: kapsami yazilmamis anahtar en yetkili rolle ayni ucluyu alir ve suresi dolmus anahtar 40 sorguyu yanitsiz birakir.

Üç Düzeyde Aynı Sorgu

Birinci tablo tek bir soruyu beş yetki altında koşturuyor. Okuyucu tek dizine ve 4000 açık kayda erişip 2463 belge alıyor; görevli iki dizine ve 6400 kayda erişiyor, eşleşen 4743’e çıkıyor ve ilk üç sonucun üçü de değişiyor. Kümeyi büyüten yalnız izin değil, izinle gelen başka dizinlerin aynı sıraya girmesidir.

Üçüncü satır alan düzeyini yalıtıyor: aynı görevli, aynı iki dizin, aynı 6400 kayıt, tek fark not alanının kapatılması. Eşleşen 4542’ye iniyor — 201 kayıt yalnızca not alanından eşleşiyordu — ve ilk üç, katalogdan ödünç kayıtlarına geçiyor. Bir alanı kapatmak listeden belge silmekle kalmaz, kalanların puan bileşenlerinden birini de siler.

Dördüncü satır varsayılan açık kurulumdur: kapsamı yazılmamış anahtar üç dizine ve 6800 kayda erişiyor, hiçbir role verilmemiş bir genişlik alıyor ve taranan girişi 7175’e çıkarıyor. Beşincisi süreyi gösteriyor: süresi dolmuş anahtar yüz sorgunun kırkını yanıtsız bırakıyor.

Süzmenin Puanlamaya Sızması

İkinci tablo dersin asıl ölçümüdür. Okuyucu rolü iki biçimde uygulanabilir: kısıtlı 1500 kayıt ya baştan dizinin dışında tutulur (önce süz), ya da tam katalog üzerinden puanlanıp listeden atılır (sonra süz). İkisi de aynı 2463 belgeyi döndürüyor — küme birebir aynı.

Sıra aynı değil. İlk on sonucun yalnız yedisi ortak: altıncı sırada 3127, dokuzuncu ve onuncuda 3695 ile 3561 beliriyor, buna karşılık 308, 476 ve 1012 listeden düşüyor; derin sırada 2463 belgenin 1433’ü yer değiştirmiş. Sebep tek bir sayıdır: ters belge sıklığı. Sonra süzen kurulumda oyku terimi 5500 belgede sayılıyor ve kısıtlı parti tek konudan geldiği için o terimin ayırt ediciliği düşüyor. Okuyucunun göremeyeceği belgeler, görebildiği belgelerin sırasını belirliyor.

Aynı kurulum bilgi de sızdırıyor: raporlanan sayaç önce süzende 2463, sonra süzende 3963 ve aradaki 1500 kısıtlı partinin tam boyudur — sayaç okuyucuya göremediği kayıtların sayısını söylüyor. Süzmenin puanlamadan önce mi sonra mı uygulandığı bir başarım ayrıntısı değildir: hem sırayı hem sızıntıyı belirler.

Özet

  • Yetki üç ayrı kesme yapar: okuyucu 1 dizin ve 4000 kayıtla 2463, görevli 2 dizin ve 6400 kayıtla 4743 belge aldı; ilk üç sonuç tümüyle değişti. Not alanı kapatılınca eşleşen 4542’ye indi.
  • Kapsamı yazılmamış anahtar üç dizine ve 6800 kayda erişti, taranan girişi 2998’den 7175’e çıkardı; süresi dolmuş anahtar yüz sorgunun kırkını yanıtsız bıraktı.
  • Belge düzeyi süzme kümeyi değiştirmeden sırayı değiştirdi: aynı 2463 belgede ilk onun yalnız yedisi ortaktı, 1433 belge yer değiştirdi ve sayaç kısıtlı 1500 kaydı sızdırdı.

Kurs Kapanışı

Ders Değişen küme Değişen sıra Bedel
Motor ve Veritabanı Farkı LIKE 68, dizin 12 plan düzeni, kimlik düzeni 124.863 → 1.076 bayt
Ters Dizin konum 23 → 10 gönderi listesi kimlik sırasında kesişim 19.622 → 470
Çözümleyici Zinciri 80 / 122 / 463 ilk beşin beşi de değişti 187.780 → 146.080 bayt
Eşlemeler ve Alan Tipleri çocuk 93’e karşı 0 ilk onun onu oynadı konu 8.203 → 11.686 bayt
Dinamik ve Açık Eşleme çatışma 111 belge attı düşen belge sırada görünmez üstveri 1.595 → 3.022 bayt
Belge Yaşam Döngüsü #10 kümeden kümeye geçti 7. sıradan 509. sıraya 119.722 → 136.322 bayt
Sorgu Dili Yapısı 4.211 / 132 / 71 2.023. basamaktan ilk ona 21.303 → 7.576 giriş
Terim ve İfade Sorguları 757 → 144 bitişik eşleşme 1 → 10 216.480 → 330.578 bayt
Bağlam Sorguları olumsuz 512, isteğe bağlı 0 ilk onun dokuzu değişti giriş 2.678 → 4.638
Süzme ve Sorgu Ayrımı iki bağlamda da 1.138 ortalama 173 basamak puan hesabı 2.276 → 1.138
İlgililik Puanlaması kesinlik 0,353 → 0,640 bileşen yokluğu 499 basamak anma için 567 sonuç
Puan Ayarlama ağırlık 325, alan seçimi 199 ilk onun onu değişti 698 → 265 giriş
Toplama Sorguları 208 / 168 / 1 kova sıra kova sırasıdır 1.045 kova, 25.080 bayt
Vurgulama ve Sayfalama 60 eşleşmeden 12’si dışarıda sıra değişmez 20. sayfa 800 aday
Anlamsal ve Vektör Arama 0,5 eşiğinde 383 ilk onun altısı eşanlamlıdan 153.600 bayt
Düğüm Rolleri geciken durum 800 kaydı reddetti ilk beş tamamen değişti eşgüdüm %0,8 → %11,4
Parçalar ve Kopyalar düğüm kaybında 515 → 379 ilk on ortak 10,00 → 4,75 aday 10 → 160
Bölünmüş Beyin azınlıkta 210 kayıt kayboldu iki yarı iki liste verdi 600 → 1590 ileti
Toplu Dizinleme yenileme kapalıyken 600 eksik ilk on 6/10 4000 bölüt, 24.000 arama
Bölüt Birleştirme değişmedi, 18.775 50 basamağın 42’si farklı 3.193.775 → 2.552.007 bayt
Dizin Yaşam Döngüsü 10.262 → 12.274 ilk onun ikisi silinmiş günden giriş 19.476 → 1.993
Anlık Görüntü ve Geri Yükleme 7.879 → 17.387 49 basamak değişti 10.790.530 → 3.180.562 bayt
Erişim Denetimi okuyucu 2.463, görevli 4.743 ilk on ortak 7/10 giriş 2.998 → 7.175

Tablonun üç sütunu kursun kuralıdır: bir arama kararı ancak küme ve sıra üzerindeki etkisiyle savunulur. “Daha alakalı sonuç” bir karar değildir; bir çözümleyici, bir ağırlık, bir parça sayısı ya da bir yetki kuralı ancak hangi belgelerin hangi sırayla döndüğünü ve neye mal olduğunu söyleyerek savunulur.

Bu kurs M17’nin yedincisi ve sonuncusudur. İlişkisel Kuram verinin nasıl modelleneceğini, SQL Temelleri o modelin nasıl sorgulanacağını, İleri SQL aynı sorgunun neden yavaşladığını, Veritabanı Yönetimi çalışan bir dizgenin nasıl işletileceğini, İlişkisel Olmayan Veri Modelleri başka bir yolun neyi kazandırıp neyi bıraktığını, Bellek İçi Depolar bellek bütçesinin nasıl harcandığını kurdu. Bu kurs son boşluğu kapattı: anahtarı bilinmeyen veriye metnin içinden gitmeyi.

Buradan sonrası ölçüm alışkanlığıdır ve başlangıcı kendi verinin erişim örüntüsüdür: sorular anahtarla mı geliyor yoksa metnin içinden mi, kaç belge dönüyor, hangi sırayla ve o sırayı kim belirliyor. Yirmi üç dersin yaptığı tek şey buydu.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat