class PostgreSQL Mini‑Kılavuz extends Post

@created_at( "2025-07-14 08:40" ) @tag( "postgresql" )
## PostgreSQL Mini‑Kılavuz *SQL güvenlik ve performans çıtasını yukarı taşıyan pratik bir yol haritası. --- ### 1. Temel Yapılar #### 1.1. Tablo Oluştur
CREATE TABLE urunler (
    id          SERIAL PRIMARY KEY,
    ad          TEXT            NOT NULL,
    kategori    TEXT            NOT NULL,
    fiyat       NUMERIC(10,2)   CHECK (fiyat >= 0),
    stok        INT             DEFAULT 0 CHECK (stok >= 0),
    aktif       BOOLEAN         DEFAULT TRUE
);
**İpucu:** PostgreSQL 17’de `SERIAL` yerine identity sütun kullan:
id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY
Sekans yönetimini otomatikleştirir. #### 1.2. CRUD Örnekleri
-- INSERT
INSERT INTO urunler (ad, kategori, fiyat, stok)
VALUES ('USB‑C Hub', 'Elektronik', 349.90, 25)
RETURNING id;

-- SELECT
SELECT id,
       ad                AS urun,
       fiyat || ' ₺'     AS fiyat_etiket,
       stok,
       CASE WHEN stok = 0 THEN 'Stok Yok' ELSE 'Var' END AS durum
FROM urunler
WHERE aktif IS TRUE
ORDER BY fiyat DESC
LIMIT 10;

-- UPDATE
UPDATE urunler
SET stok = stok - 1
WHERE id = 42;

-- DELETE (kampanya bitince)
DELETE FROM urunler
WHERE aktif IS FALSE AND stok = 0;
--- ### 2. İlişkiler & JOIN’ler
-- Basit JOIN: sipariş detayındaki ürün bilgisi
SELECT u.ad, u.kategori, sd.miktar
FROM urunler u
JOIN siparis_detay sd  ON sd.urun_id = u.id
WHERE sd.birim_fiyat > 100;

-- LEFT JOIN + agregasyon: hiç satmayan ürünleri bul
SELECT u.id,
       COALESCE(SUM(sd.miktar), 0) AS toplam_satis
FROM urunler u
LEFT JOIN siparis_detay sd ON sd.urun_id = u.id
GROUP BY u.id
HAVING SUM(sd.miktar) IS NULL;
**Performans Tüyosu:** JOIN’lenen sütunlara (`siparis_detay.urun_id`) mutlaka indeks bas. Yabancı anahtarlar için `ON DELETE CASCADE` ya da `DEFERRABLE` senaryolarını değerlendir. --- ### 3. Güvenlik — “Veri kalesini” sağlamlaştır | Tehdit | Karşı Hamle | | ------------------ | ----------------------------------------------------------------------------------------- | | **SQL Injection** | Parametreli sorgu (`$1`, `pg_prepare`, PDO::prepare\`). | | **Aşırı yetki** | `CREATE ROLE readonly LOGIN...`; sonra sadece gerekli tablolara `GRANT SELECT`. | | **Şifreler** | Sunucu‑CLI SSL (`hostssl`), `scram-sha-256` auth; uygulama katmanında Argon2/BCrypt hash. | | **Veri sızıntısı** | Sütun şifreleme (`pgcrypto`), satır düzeyi politikalar (Row‑Level Security). | | **Kaza‑silme** | WAL + `pg_basebackup`; v17’de artımlı yedek (delta) desteği. | > 🔐 **Ekstra:** Trigger ile “soft delete” (örn. `deleted_at`) tut, yetkisi olmayan kullanıcılara `WHERE deleted_at IS NULL` filtreli view göster. --- ### 4. Performans — “Uçan” sorgular için reçete 1. **İndeks Stratejisi** * `btree` → eşitlik/sırala * `hash`  → saf eşitlik (v17’de hızlandı) * `GIN/GIST` → JSONB, coğrafi, full‑text 2. **EXPLAIN (ANALYZE, BUFFERS)** ile plan oku:
EXPLAIN (ANALYZE, BUFFERS)
   SELECT * FROM urunler WHERE ad ILIKE 'usb%';
3. **Autovacuum Ayarı** — büyük tablolarda `autovacuum_vacuum_scale_factor = 0.02` gibi agresif değer. 4. **Konfig:** * `shared_buffers = 25%` RAM * `work_mem` = (eşzamanlı sorgu × 1–2 MB) * `maintenance_work_mem` = rebuild/vacuum sırasında yüksek tut 5. **PostgreSQL 17 Bonusları** * **Streaming I/O** → sekansiyel taramada %20 hız * **Adaptive Vacuum** → yoğun trafikte daha az dur‑kalk * **JSON\_TABLE()** → JSON’u satırlara aç, sonra join 6. **Connection Pool** → PgBouncer / PgCat. 7. **Partisyonlama** → yıllık veya kategori bazlı tablolar; eski partisyonu `DETACH` edip salt‑okunur sakla. --- ### 5. Mikroservis / Modüler Data Layer * **Schema‑per‑module:** `CREATE SCHEMA stok;`, `siparis;` vb. Çakışma riskini sıfırlar. * **Foreign Data Wrapper** (`postgres_fdw`) ile modüller arası sorgu, ya da * **Logical Replication** — modül A’daki `urunler` tablosunu modül B’ye yayınla; v17’de **failover** kontrolü geldi. * **Event Bus**: `LISTEN/NOTIFY` ile hafif publish–subscribe. --- ### 6. Öğrenme Rotaları & Alıştırmalar 1. **Challenge** — *“Kritik stok”* fonksiyonu yaz:
CREATE OR REPLACE FUNCTION urun_kritik_stokta_mi(p_id INT)
   RETURNS BOOLEAN LANGUAGE plpgsql AS $$
   DECLARE
       s INT;
   BEGIN
       SELECT stok INTO s FROM urunler WHERE id = p_id;
       RETURN s < 10;  -- eşik değeri
   END;
   $$;
2. **Index Lab** — `generate_series` ile 1 M satırlık sahte veri doldur; `btree` vs `gin` arası hız farkını ölç. 3. **RLS Görevi** — tedarikçi bazlı satır politikası: `tedarikci_id = current_user`. --- ### 7. Son Tüyolar * **Versiyon Güncellemesi** — 15→17 in‑place upgrade artık tek tık; downtime kısa. * **pg\_stat\_statements** → yavaş sorguları sınıflandır; sonra gereken yerde `CREATE INDEX` / `REFRESH MATERIALIZED VIEW`. * **Test ≠ Prod** — staging’de farklı `work_mem`/istatistik hedefi, hatalı plan doğurur. * **CLI Ninja Move** — `\watch 1` ile `psql` çıktısını saniyelik güncelle; canlı monitoring gibi. --- Şimdi terminali aç, birkaç `EXPLAIN` patlat: kaç satır diskten geldi, kaç buffer hit oldu bir bak. Sonra kahveni yudumla; bir sonraki optimizasyon turunda görüşürüz! 🚀