KARŞILAŞTIRMA11m READ17 Haziran 2026

PostgreSQL vs MySQL: 2025'te Hangi Veritabanı?

JSONB, full-text search, DDL transaction, performans ve ekosistem açısından karşılaştırmalı analiz.

PostgreSQL mi yoksa MySQL mi kullanmalısın? Bu soruyu yıllardır geliştiriciler tartışıyor. 2025'te her ikisi de olgun ve güçlü — ama kullanım senaryosuna göre farklı güçlü yönleri var. İşte tarafsız bir karşılaştırma.

Kısa Özet

// PLAINTEXT //
PostgreSQL:
✓ Gelişmiş veri tipleri (JSONB, array, range, hstore)
✓ ACID tam uyumluluk
✓ Güçlü full-text search
✓ Karmaşık sorgular ve analitik
✓ PostGIS ile coğrafi veri
✓ Extensible — özel tip ve fonksiyon
 
MySQL:
✓ Basit CRUD'da çok hızlı
✓ WordPress, Laravel ekosisteminde yaygın
✓ Read replica kurulumu kolay
✓ Daha geniş hosting desteği
✓ InnoDB ile iyi ACID uyumu

Performans

// SQL //
-- Basit okuma (SELECT * FROM users WHERE id = ?)
-- Her ikisi de B-Tree index ile: < 1ms — fark yok
 
-- Karmaşık analitik sorgu
SELECT
    DATE_TRUNC('month', created_at) AS ay,
    category,
    COUNT(*) AS siparis_sayisi,
    SUM(amount) AS toplam,
    AVG(amount) AS ortalama,
    PERCENTILE_CONT(0.95) WITHIN GROUP (ORDER BY amount) AS p95
FROM orders
WHERE created_at > NOW() - INTERVAL '1 year'
GROUP BY 1, 2
ORDER BY 1, toplam DESC;
 
-- PostgreSQL: Window function, percentile, CTEs — native destek
-- MySQL 8.0+: Window function var ama PERCENTILE_CONT yok (user-defined gerekir)

Veri Tipleri: PostgreSQL Kazanıyor

// SQL //
-- JSONB — binary JSON, index destekli
-- PostgreSQL
CREATE TABLE products (
    id SERIAL PRIMARY KEY,
    meta JSONB
);
CREATE INDEX idx_meta ON products USING GIN(meta);
SELECT * FROM products WHERE meta->>'brand' = 'Apple';
SELECT * FROM products WHERE meta @> '{"color": "blue", "size": "M"}';
 
-- MySQL JSON tipi var ama GIN index yok, daha yavaş
-- Çözüm: generated column + index (ek karmaşıklık)
ALTER TABLE products
    ADD COLUMN brand VARCHAR(100) AS (JSON_UNQUOTE(JSON_EXTRACT(meta, '$.brand'))) STORED,
    ADD INDEX idx_brand(brand);
 
-- Array tipi — PostgreSQL
SELECT * FROM posts WHERE 'typescript' = ANY(tags);
UPDATE posts SET tags = array_append(tags, 'react');
 
-- MySQL'de dizi yok — ayrı tablo veya virgüllü metin (antipattern)

ACID ve Transaction

// SQL //
-- Her ikisi de InnoDB/PostgreSQL ile ACID uyumlu
-- Fark: PostgreSQL DDL de transaction'a dahil
 
-- PostgreSQL
BEGIN;
CREATE TABLE new_feature (id serial primary key);
-- Hata olursa CREATE TABLE da geri alınır
ROLLBACK;
-- Tablo YOK
 
-- MySQL
START TRANSACTION;
-- DDL (CREATE, ALTER) implicit commit yapar
-- ROLLBACK işe YARAMAZ

Replikasyon ve Yüksek Erişilebilirlik

// PLAINTEXT //
PostgreSQL:
• Streaming replication (fiziksel) — standby sunucular
• Logical replication — tablo bazlı seçici replikasyon
• Patroni / pg_auto_failover — otomatik failover
• pgBouncer — connection pooling
 
MySQL:
• Master-Slave / GTID tabanlı replikasyon
• Group Replication — çok-master yazma
• ProxySQL — yük dengeleme + connection pool
• MySQL InnoDB Cluster

Yönetim kolaylığı açısından MySQL'in ekosistemi biraz daha olgun, ama PostgreSQL hızla yakalıyor.

Full-Text Search

// SQL //
-- PostgreSQL — native, güçlü
SELECT title, ts_rank(search_vec, query) AS rank
FROM articles, to_tsquery('turkish', 'postgresql & optimizasyon:*') query
WHERE search_vec @@ query
ORDER BY rank DESC;
 
-- Türkçe dil desteği için
CREATE TEXT SEARCH CONFIGURATION turkish_config (COPY = simple);
ALTER TEXT SEARCH CONFIGURATION turkish_config
    ALTER MAPPING FOR word, hword, hword_part WITH turkish_stem, simple;
 
-- MySQL — FULLTEXT index ile
ALTER TABLE articles ADD FULLTEXT INDEX ft_idx(title, body);
SELECT *, MATCH(title, body) AGAINST('postgresql optimizasyon' IN BOOLEAN MODE) AS score
FROM articles
WHERE MATCH(title, body) AGAINST('postgresql optimizasyon' IN BOOLEAN MODE)
ORDER BY score DESC;
-- Türkçe stemming yok, n-gram ile alternatif

Ekosistem ve ORM Desteği

// PLAINTEXT //
ORM                  PostgreSQL  MySQL
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Prisma                ✓           ✓
Eloquent (Laravel)    ✓           ✓ (varsayılan)
TypeORM               ✓           ✓
Django ORM            ✓           ✓
SQLAlchemy            ✓           ✓
ActiveRecord (Rails)  ✓           ✓ (geleneksel)
Drizzle               ✓           ✓

Hosting desteği: MySQL neredeyse her shared hosting'de var. PostgreSQL → Railway, Supabase, Render, Neon ile kolaylıkla kurulabilir.

Hangi Senaryoda Hangisini Seç?

// PLAINTEXT //
PostgreSQL seç:
✓ Karmaşık sorgular ve analitik
✓ JSONB ile esnek veri modeli
✓ Coğrafi veri (PostGIS)
✓ Full-text search kritik
✓ DDL transaction güvenliği önemli
✓ Yeni proje başlıyorsun
 
MySQL seç:
✓ WordPress / Drupal / WooCommerce
✓ Mevcut Laravel projesinde MySQL var
✓ Çok basit CRUD, performans kritik
✓ Yönetilen hosting sınırlı (shared hosting)
✓ Ekip MySQL biliyor, geçiş maliyeti yüksek

Migration: MySQL → PostgreSQL

// BASH //
# pgloader — en kolay geçiş aracı
pgloader mysql://user:pass@localhost/mydb postgresql://user:pass@localhost/mydb
 
# Dikkat: tip farklılıkları
# MySQL tinyint(1) → PostgreSQL boolean
# MySQL text/varchar charset → PostgreSQL utf8 varsayılan
# MySQL ENUM → PostgreSQL CHECK constraint veya custom type
# MySQL AUTO_INCREMENT → PostgreSQL SERIAL / GENERATED ALWAYS AS IDENTITY

2025'te Sonuç

PostgreSQL, genel amaçlı projeler için artık varsayılan tercih haline geldi. Supabase, Neon, Railway gibi platformlar PostgreSQL'i kolaylaştırdı. MySQL, WordPress ekosistemi ve mevcut projeler için güçlü kalmaya devam ediyor.

Yeni proje başlıyorsan: PostgreSQL. Mevcut MySQL projen varsa: geçişin faydası maliyetini karşılıyor mu? Bunu analiz et.