İçeriğe geç
academia.sh

Ders 07 / 25

Sistem Kataloğu

Şema tanımının sorgulanabilir tablolarda tutulması, envanterin ve yönetim kurallarının sorguya çevrilmesi, iki kopya arasındaki şema sapmasının ölçülmesi ve kataloğun neden okunup yazılmadığı.

İçindekiler

Bu kursta şimdiye kadar sorulan her soru bir sayıyla yanıtlandı: sayfa sayısı, doluluk, çerçeve sayısı, isabet oranı. Bu sayıların kaynağı motorun kendi tuttuğu kayıtlardır ve o kayıtlar özel bir arayüzün arkasında değildir. Motor, şema hakkındaki bilgiyi sıradan tablolarda tutar ve sıradan sorgularla verir. Bu tabloların bütününe sistem kataloğu (system catalog) denir.

Kataloğun sorgulanabilir olması, yönetim işini bir belge işi olmaktan çıkarır. Hangi tabloların hangi sütunları taşıdığı, hangi dizinlerin var olduğu, hangi kısıtların tanımlandığı elle tutulan bir listede değil, veritabanının kendisinde yazılıdır — ve o liste her zaman günceldir, çünkü değişikliği yapan deyimin kendisi onu günceller.

Katalog Sıradan Bir Tablodur

Aşağıdaki blok kütüphane şemasını kurar. Şema önceki kurslardan tanıdıktır; buraya dizinler, bir görünüm ve bir değer denetimi eklenmiştir.

rm -f kutuphane.db
sqlite3 kutuphane.db <<'SQL'
CREATE TABLE sube (
  sube_id INTEGER PRIMARY KEY,
  ad      TEXT NOT NULL,
  sehir   TEXT NOT NULL
);
CREATE TABLE uye (
  uye_id       INTEGER PRIMARY KEY,
  ad           TEXT NOT NULL,
  eposta       TEXT UNIQUE,
  kayit_tarihi TEXT NOT NULL,
  durum        TEXT NOT NULL DEFAULT 'etkin' CHECK (durum IN ('etkin','askida','kapali'))
);
CREATE TABLE kitap (
  kitap_id   INTEGER PRIMARY KEY,
  baslik     TEXT NOT NULL,
  yazar      TEXT NOT NULL,
  isbn       TEXT UNIQUE,
  sube_id    INTEGER NOT NULL REFERENCES sube(sube_id)
);
CREATE TABLE odunc (
  odunc_id    INTEGER PRIMARY KEY,
  uye_id      INTEGER NOT NULL REFERENCES uye(uye_id),
  kitap_id    INTEGER NOT NULL REFERENCES kitap(kitap_id),
  alis_tarihi TEXT NOT NULL,
  iade_tarihi TEXT
);
CREATE INDEX odunc_uye ON odunc(uye_id);
CREATE INDEX odunc_kitap_tarih ON odunc(kitap_id, alis_tarihi);
CREATE VIEW acik_odunc AS SELECT * FROM odunc WHERE iade_tarihi IS NULL;
INSERT INTO sube VALUES (1,'Merkez','Ankara'),(2,'Bahçelievler','Ankara');
INSERT INTO uye (uye_id,ad,eposta,kayit_tarihi) VALUES (1,'Ayşe','[email protected]','2023-02-14');
INSERT INTO kitap VALUES (1,'Gökbilim El Kitabı','Y. Aydın','978-0201896831',1);
INSERT INTO odunc VALUES (1,1,1,'2025-06-01',NULL);
SQL

Şemadaki nesnelerin listesi tek bir sorguyla alınır.

sqlite3 kutuphane.db <<'SQL'
.headers on
.mode column
SELECT type, name, tbl_name FROM sqlite_schema ORDER BY type, name;
SQL
type   name                      tbl_name  
-----  ------------------------  ----------
index  odunc_kitap_tarih         odunc     
index  odunc_uye                 odunc     
index  sqlite_autoindex_kitap_1  kitap     
index  sqlite_autoindex_uye_1    uye       
table  kitap                     kitap     
table  odunc                     odunc     
table  sube                      sube      
table  uye                       uye       
view   acik_odunc                acik_odunc

Listede yazılmayan iki satır dikkat çeker: sqlite_autoindex_ önekli dizinler. Bunları tanımlayıcı yazmadı; benzersizlik kısıtını uygulayabilmek için motor kendisi oluşturdu. Katalog, yalnız yazılanı değil motorun kurduğu yapıyı da gösterir. Bu ayrım yönetimde işe yarar: bir sütunun benzersiz olması, arka planda bir dizin maliyeti demektir ve o maliyet burada görünür.

Nesne adlarının önekli ayrılması bir gelenektir ve motora göre değişir; değişmeyen, iç nesnelerin de katalogda bulunmasıdır.

Envanteri Sorguyla Çıkarmak

Katalog sorgulanabilir olduğu için, şema hakkındaki her soru bir sorguya çevrilebilir. Aşağıdaki sorgu tablo başına sütun ve kısıt sayımını üretir.

sqlite3 kutuphane.db <<'SQL'
.headers on
.mode column
-- Sema envanteri: tablo basina sutun ve kisit sayilari.
SELECT m.name AS tablo, count(*) AS sutun, sum(ti."notnull") AS not_null,
       sum(ti.pk > 0) AS birincil_anahtar
FROM sqlite_schema m JOIN pragma_table_info(m.name) ti
WHERE m.type='table' GROUP BY m.name ORDER BY m.name;
SQL
tablo  sutun  not_null  birincil_anahtar
-----  -----  --------  ----------------
kitap  5      3         1               
odunc  5      3         1               
sube   3      2         1               
uye    5      3         1

Bu tablo bir şema tasarımı tartışmasının başlangıç noktasıdır: hangi tablo kaç sütun taşıyor, kaç sütun zorunlu, birincil anahtarı olmayan tablo var mı. Elle tutulan bir belgede bu üç soru için üç ayrı bölüm gerekir ve üçü de eskir; katalogdan çıkarıldığında sorgu her çalıştırıldığında güncel yanıtı verir.

Katalogla Yazılan Denetimler

Kataloğun asıl değeri, kuralların sorgu olarak yazılabilmesidir. Dizinler ve Bölümleme konusunda görülecek bir kuralı şimdiden uygulayalım: yabancı anahtar taşıyan her sütunun kendi dizini olmalıdır, yoksa ana tablodaki silme ve güncelleme işlemleri çocuk tabloyu baştan sona taramak zorunda kalır.

sqlite3 kutuphane.db <<'SQL'
.headers on
.mode column
-- 1. Yabanci anahtari dizinsiz kalan sutunlar: silme ve guncelleme maliyetini artirir.
SELECT m.name AS tablo, f."from" AS sutun, f."table" AS hedef
FROM sqlite_schema m
JOIN pragma_foreign_key_list(m.name) f
WHERE m.type = 'table'
  AND NOT EXISTS (
    SELECT 1 FROM pragma_index_list(m.name) il
    JOIN pragma_index_info(il.name) ii
    WHERE ii.seqno = 0 AND ii.name = f."from"
  );
SQL
tablo  sutun    hedef
-----  -------  -----
kitap  sube_id  sube

Denetim tek bir bulgu üretti: kitap tablosundaki şube başvurusu dizinsiz. Ödünç tablosundaki iki başvuru kapsanıyor — biri kendi dizinine, diğeri bileşik dizinin ilk sütunu olduğu için ona dayanıyor. Bileşik dizinin yalnız ilk sütununun bu işi gördüğü, Sorgu Başarımı konusunda kurulan kuralın buradaki karşılığıdır.

Bu denetimin elle tutulan listeye üstünlüğü üç noktadadır. Yeni bir tablo eklendiğinde denetim onu kendiliğinden kapsar. Bir dizin kaldırıldığında bulgu kendiliğinden geri gelir. Ve denetim, tanımlayıcının ne yazdığını değil motorun ne bildiğini okur — ikisi ayrıştığında ayrışma görünür olur.

Aynı kalıpla yazılabilecek başka denetimler vardır: birincil anahtarı olmayan tablolar, hiç kullanılmayan dizinler, aynı sütun listesini paylaşan yinelenen dizinler, değer denetimi olmayan durum sütunları. Her biri bir yönetim kuralının sorgu biçimidir.

Şema Sapmasının Ölçülmesi

Katalog sorgulanabilir olduğu için iki veritabanının şeması karşılaştırılabilir. Bu, sürüm yükseltmelerinde ve ortamlar arası tutarlılık denetiminde en sık ihtiyaç duyulan işlemdir.

# Iki semanin farki: gelistirme ve uretim kopyalari ayni mi?
sqlite3 uretim.db <<'SQL'
CREATE TABLE sube (sube_id INTEGER PRIMARY KEY, ad TEXT NOT NULL, sehir TEXT NOT NULL);
CREATE TABLE uye (uye_id INTEGER PRIMARY KEY, ad TEXT NOT NULL, eposta TEXT UNIQUE,
                  kayit_tarihi TEXT NOT NULL);
CREATE TABLE kitap (kitap_id INTEGER PRIMARY KEY, baslik TEXT NOT NULL, yazar TEXT NOT NULL,
                    isbn TEXT UNIQUE, sube_id INTEGER NOT NULL REFERENCES sube(sube_id));
CREATE TABLE odunc (odunc_id INTEGER PRIMARY KEY, uye_id INTEGER NOT NULL REFERENCES uye(uye_id),
                    kitap_id INTEGER NOT NULL REFERENCES kitap(kitap_id), alis_tarihi TEXT NOT NULL,
                    iade_tarihi TEXT);
CREATE INDEX odunc_uye ON odunc(uye_id);
SQL

esle() {
  sqlite3 "$1" "SELECT type||' '||name||' ('||coalesce((SELECT group_concat(ti.name||':'||ti.type, ', ')
                  FROM pragma_table_info(m.name) ti), '')||')'
                FROM sqlite_schema m WHERE name NOT LIKE 'sqlite_%' ORDER BY type, name;"
}
esle kutuphane.db > gelistirme.liste
esle uretim.db    > uretim.liste
echo "--- yalniz gelistirmede olan ---"
comm -23 gelistirme.liste uretim.liste
echo "--- yalniz uretimde olan ---"
comm -13 gelistirme.liste uretim.liste
--- yalniz gelistirmede olan ---
index odunc_kitap_tarih ()
table uye (uye_id:INTEGER, ad:TEXT, eposta:TEXT, kayit_tarihi:TEXT, durum:TEXT)
view acik_odunc (odunc_id:INTEGER, uye_id:INTEGER, kitap_id:INTEGER, alis_tarihi:TEXT, iade_tarihi:TEXT)
--- yalniz uretimde olan ---
table uye (uye_id:INTEGER, ad:TEXT, eposta:TEXT, kayit_tarihi:TEXT)

Fark üç kalem gösteriyor. Bir dizin ve bir görünüm yalnız geliştirme kopyasında var. Üye tablosu ise iki tarafta da var ama aynı değil: geliştirmede bir durum sütunu eklenmiş, üretimde yok. Sütun listesini karşılaştırmaya katmak bu farkı görünür kılar; yalnız nesne adları karşılaştırılsaydı iki tablo eşit sayılırdı.

Sapmanın yönü de bilgidir. Geliştirmede olup üretimde olmayan bir sütun, henüz uygulanmamış bir göç demektir. Üretimde olup geliştirmede olmayan bir nesne ise daha kaygı vericidir: doğrudan üretime yazılmış, sürüm kontrolünde karşılığı olmayan bir değişikliğe işaret eder.

Kataloğa Yazmak

Katalog okunur; elle yazılmaz. Şema değişikliği veri tanımlama deyimleriyle yapılır ve katalog güncellemesini motor üstlenir. Katalog tablolarına doğrudan yazmak — bazı motorlarda teknik olarak olanaklı olsa da — motorun iç tutarlılığını bozar: veri dosyalarındaki fiziksel düzenle katalogdaki tanım ayrışır ve bu ayrışma çoğu zaman sonraki bir okumada, tanısı zor bir hata olarak görünür.

Kuralın pratik karşılığı şudur: göçler deyimlerle yazılır ve sürüm kontrolünde durur; katalog ise bu göçlerin uygulanıp uygulanmadığını doğrulamak için okunur.

Özet

  • Sistem kataloğu, şemanın tanımını tutan ve sıradan sorgularla okunabilen tablolardır; değişikliği yapan deyimin kendisi onu güncellediği için her zaman günceldir.
  • Katalog yalnız yazılanı değil motorun kendiliğinden kurduğu nesneleri de gösterir: benzersizlik kısıtının arkasındaki dizin listede görünür.
  • Şema hakkındaki her yönetim kuralı bir sorguya çevrilebilir; dizinsiz yabancı anahtar denetimi modelde tek bulgu üretti ve yeni tabloları kendiliğinden kapsar.
  • İki kopyanın şeması sütun listeleriyle birlikte karşılaştırıldığında sapma görünür olur; yalnız nesne adları karşılaştırılırsa değişmiş bir tablo eşit sayılır.
  • Katalog okunur, elle yazılmaz: şema değişikliği deyimlerle yapılır, katalog o değişikliğin uygulandığını doğrulamak için sorgulanır.

Sonraki Adım

Motorun içyapısı bu dersle tamamlanıyor: süreçler, sayfalar, günlük, denetim noktaları, sürüm zincirleri, temizlik ve bunların hepsini kayda geçiren katalog. Bu bölümde bir bulgu askıda kaldı — dizinsiz yabancı anahtar. Sonraki konu bu bulgunun ait olduğu alanı açar: dizin türlerinin birbirinden farkı, bileşik dizinde sütun sırasının neden sonucu değiştirdiği, kısmi ve kapsayan dizinlerin ne zaman kazandırdığı ve bir tablonun bölümlere ayrılmasının hangi sorunu çözüp hangisini doğurduğu.

İ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