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! 🚀