6 tablo · 5 FK zinciri · 10 index · 1 trigger · 2 extension
7 kolon · Kök tablo
Kullanıcı hesapları
15 kolon · 2 JSONB · ENUM
Hikaye meta + config + session
6 kolon · UNIQUE composite
OAuth sağlayıcıları
13 kolon · vector · HNSW
En hızlı büyüyen tablo
6 kolon · 2 FK · vector
Kullanıcı kararları
9 kolon · idempotency
Transactional event kuyruğu
Tüm tablolar ve aralarındaki ilişkiler. Tablo isimlerine tıklayarak detaylara gidin.
Her tablonun SQL tanımı ve kolon açıklamaları. Tabloya tıklayarak inceleyin.
PostgreSQL JSONB içeriğini doğrulamaz. Yapısını biz tanımlıyoruz, validasyonu uygulama katmanında TypeBox yapar.
10 index — her biri belirli bir sorgu pattern'ini hızlandırır.
| Index Adı | Tablo | Tip | Kolon(lar) | Amacı |
|---|---|---|---|---|
| idx_stories_user_cursor | stories | B-Tree Composite | user_id, created_at DESC, id DESC | Cursor-based pagination (OFFSET yerine) |
| idx_story_chunks_ordering | story_chunks | UNIQUE B-Tree | story_id, chunk_index | Kronolojik sıralama + uniqueness garantisi |
| idx_story_chunks_embedding | story_chunks | HNSW Conditional | embedding (WHERE IS NOT NULL) | RAG semantic search — ~12ms @ 1M satır |
| idx_story_decisions_story | story_decisions | B-Tree Composite | story_id, created_at | Hikayeye ait kararları kronolojik çek |
| idx_story_decisions_embedding | story_decisions | HNSW Conditional | embedding (WHERE IS NOT NULL) | RAG related_decisions semantic search |
| idx_stories_cache_dirty | stories | Partial B-Tree | cache_dirty WHERE true | Sadece dirty story'leri tara (Q16 — sessions'tan taşındı) |
| idx_outbox_pending | outbox | Partial B-Tree | status, created_at WHERE pending | Worker polling — bekleyen event'leri çek |
| idx_outbox_story_pending | outbox | Partial B-Tree | story_id, created_at WHERE pending | Per-story outbox kontrolü (Phase 1) |
| idx_outbox_cleanup | outbox | Partial B-Tree | status, sent_at WHERE sent | Cleanup cron — eski sent kayıtları sil |
| idx_outbox_dead_letter | outbox | Partial B-Tree | status, created_at WHERE dead_letter | Monitoring — müdahale gerektiren event'ler |
Hierarchical Navigable Small World — pgvector'ın approximate nearest neighbor index'i. Exact search yerine ~%99 doğrulukla 70x hızlı arama. m=16 her node 16 komşuya bağlı, ef_construction=64 build kalitesi.
Sadece belirli koşulu sağlayan satırlar index'lenir. WHERE status = 'pending' → 1M outbox kaydından sadece ~100 pending olan index'te. Küçük, hızlı, az disk.
PRIMARY KEY ve UNIQUE constraint'ler otomatik index oluşturur. users.email, users.username, outbox.idempotency_key için ayrı index yazmadık — PG kendisi yapıyor.
Kullanıcıyı sil → tüm verisi otomatik temizlenir. Orphan kayıt riski yok.
Kullanıcı kaydı siliniyor...
user_id FK CASCADE → tüm hikayeler siliniyor...
story_id FK CASCADE → tüm chunk'lar siliniyor...
chunk_id FK CASCADE + story_id FK CASCADE → tüm kararlar siliniyor...
story_id FK CASCADE → event'ler siliniyor...
⚠️ DBA Uyarısı: Büyük veri setlerinde CASCADE silme tablo kilitlemeye neden olabilir. Üretimde soft-delete (status='deleted') tercih edilebilir.
SQL yazmak yerine TypeScript ile tanımlıyoruz. Drizzle Kit otomatik migration SQL'i üretir.
1 tabloda (stories) UPDATE yapıldığında updated_at otomatik NOW() olur.
Neden BEFORE UPDATE? AFTER UPDATE'ten farklı olarak, BEFORE trigger satır yazılmadan önce değişiklik yapabilir. Performans farkı yok ama mantıksal olarak daha doğru — updated_at değerini "yazılacak verinin" parçası yapıyoruz.