Yükleniyor...

PostgreSQL Performans Optimizasyonu: 10 Nihai Teknik [2026 Rehberi]

Yazar: Burak Balkı | Kategori: Performance | Okuma Süresi: 51 dk

Bu rehber, 2026'da PostgreSQL performansını artırmak için 10 güncel ve kanıtlanmış teknik sunar. Uygulamalarınızın tepki süresini hızlandırmak, kaynak kullan...

### BÖLÜM 1 - Giriş Paragrafı (Hook + Context) Uygulamalarınızın yavaşlamasının temel nedeni veritabanı mı? Günümüzün rekabetçi dijital dünyasında, kullanıcılar milisaniyeler içinde yanıt beklerken, yavaş bir PostgreSQL veritabanı iş kaybetmenize neden olabilir. 2026 itibarıyla, veri hacimleri ve kullanıcı beklentileri hiç olmadığı kadar yüksek. Bu kapsamlı rehberde, 10 yılı aşkın üretim ortamı deneyimimle, **PostgreSQL performans optimizasyonu**nun en güncel ve kanıtlanmış tekniklerini adım adım inceleyeceğiz. Uygulamalarınızın tepki süresini önemli ölçüde hızlandıracak, kaynak kullanımını optimize edecek ve kullanıcı memnuniyetini artıracak stratejileri keşfedeceksiniz. Hemen başlayın ve PostgreSQL veritabanınızın gerçek potansiyelini 2026'da ortaya çıkarın. ### BÖLÜM 2 - PostgreSQL Nedir? (Featured Snippet Target) ## PostgreSQL Nedir? PostgreSQL, gelişmiş özelliklere sahip, açık kaynaklı, nesne-ilişkisel bir veritabanı yönetim sistemidir (DBMS). Güvenilirliği, veri bütünlüğü, sağlam özellikleri ve performansı ile bilinir. Büyük ölçekli ve karmaşık veri işleme gerektiren web uygulamalarından bilimsel veri ambarlarına kadar geniş bir yelpazede kullanılır ve 2026 itibarıyla aktif geliştirilen ve yaygın tercih edilen bir çözüm olmaya devam etmektedir. PostgreSQL, 1986'da Michael Stonebraker tarafından başlatılan Ingres projesinin devamı olarak ortaya çıktı ve yıllar içinde SQL standartlarına tam uyumluluğu, genişletilebilirliği ve güçlü işlem desteği ile öne çıktı. Özellikle kurumsal düzeydeki uygulamalarda, finans sektöründe ve coğrafi bilgi sistemlerinde (GIS) sıkça tercih edilir. Esnek yapısı sayesinde JSON, XML gibi NoSQL benzeri veri tiplerini de destekleyerek modern uygulama geliştirme ihtiyaçlarına cevap verir. 2026 yılında PostgreSQL 16 ve 17 sürümleri, performans ve güvenlik alanında önemli yenilikler sunmaya devam etmektedir. ### BÖLÜM 3 - Neden PostgreSQL Kullanmalısınız? (Değer Önerisi) PostgreSQL, sadece bir veritabanı olmanın ötesinde, 2026'da modern uygulama geliştiricileri ve kurumsal çözümler için stratejik bir tercihtir. Neden mi? * **Gelişmiş Veri Bütünlüğü ve Güvenilirlik**: ACID (Atomicity, Consistency, Isolation, Durability) prensiplerine tam uyumu sayesinde veri bütünlüğünü en üst düzeyde sağlar. Bu, özellikle finans ve kritik iş uygulamaları için vazgeçilmezdir. * **Genişletilebilirlik ve Esneklik**: Özel veri tipleri, fonksiyonlar, operatörler ve indeksleme yöntemleri tanımlamanıza olanak tanır. PostGIS gibi güçlü uzantılarla coğrafi verileri etkin bir şekilde yönetebilirsiniz. Ekibimizde özel iş mantıklarını doğrudan veritabanı seviyesinde uygulayarak geliştirme süresini kısalttığımız birçok proje oldu. * **Açık Kaynak ve Güçlü Topluluk Desteği**: Lisans maliyeti olmaması, büyük bir avantajdır. Ayrıca, dünya genelindeki aktif geliştirici ve kullanıcı topluluğu, hızlı destek ve sürekli yenilik anlamına gelir. Stack Overflow'da PostgreSQL ile ilgili soru sayısı 2026'da artmaya devam etmektedir. * **Performans ve Ölçeklenebilirlik**: Doğru yapılandırıldığında ve optimize edildiğinde, PostgreSQL çok yüksek işlem hacimlerini ve büyük veri kümelerini yönetebilir. Bağlantı havuzlama, bölümleme (partitioning) ve gelişmiş indeksleme teknikleri ile yatay ve dikey ölçeklenebilirlik sunar. Son projemde, doğru indeksleme ve sorgu optimizasyonu ile uygulama yanıt sürelerinde %40'ın üzerinde iyileşme gördük. * **Modern Veri Tipleri Desteği**: JSON/JSONB, XML, hstore gibi modern veri tiplerini doğal olarak destekler. Bu, yarı yapılandırılmış verilerle çalışırken NoSQL esnekliğini ilişkisel veritabanı güvenilirliği ile birleştirmenizi sağlar. * **Kurumsal Destek ve Güvenlik**: Birçok büyük teknoloji şirketi ve bulut sağlayıcısı tarafından kurumsal düzeyde desteklenir. Gelişmiş yetkilendirme, SSL bağlantıları ve denetim günlükleri gibi özelliklerle yüksek güvenlik standartları sunar. Peki, kimler için uygundur? Büyük veri hacimleriyle çalışan, yüksek veri bütünlüğü gerektiren, karmaşık sorguları olan veya coğrafi verilerle uğraşan her türlü uygulama için idealdir. Küçük projeler için de kullanılabilir ancak basit CRUD işlemleri için bazen daha hafif alternatifler düşünülebilir. ### BÖLÜM 4 - PostgreSQL vs Alternatifler (Karşılaştırma Tablosu) PostgreSQL, güçlü yönleriyle öne çıksa da, piyasada birçok başka veritabanı çözümü bulunmaktadır. Özellikle MySQL ve MongoDB, farklı kullanım senaryoları için popüler alternatiflerdir. 2026 itibarıyla bu karşılaştırma, projenizin ihtiyaçlarına göre doğru seçimi yapmanıza yardımcı olacaktır. | Özellik | PostgreSQL | MySQL | MongoDB | | :---------------- | :------------------------------------------------------------------------- | :----------------------------------------------------------------------- | :----------------------------------------------------------------------- | | Veritabanı Tipi | Nesne-İlişkisel (Relational-Object) | İlişkisel (Relational) | Doküman Tabanlı (NoSQL) | | Veri Modeli | Şemalı, JSON/JSONB ve diğer özel tipler | Şemalı | Şemasız (Flexible schema) | | Performans | Karmaşık sorgular, büyük veri setleri, veri bütünlüğü odaklı optimizasyon | Basit okuma işlemleri, web uygulamaları için optimize | Yüksek yazma hızı, yatay ölçeklenebilirlik, esnek veri yapısı | | Öğrenme Eğrisi | Orta-Yüksek (Geniş özellik seti nedeniyle) | Düşük-Orta (Yaygın kullanım ve basitlik) | Düşük-Orta (Şemasız yapı ve JSON benzeri dokümanlar) | | Ekosistem | Geniş, güçlü uzantılar (PostGIS), aktif topluluk | Çok geniş, LAMP stack'in temel parçası, popüler CMS'ler | Geniş, özellikle JavaScript/Node.js ekosisteminde popüler | | Topluluk | Aktif, geliştirici odaklı, kurumsal kullanımlar yaygın | Çok büyük, web geliştiricileri arasında yaygın | Aktif, özellikle modern web ve mobil uygulamalar için | | Kurumsal Destek | Birçok firma tarafından ticari destek sunulur (EnterpriseDB, AWS RDS vb.) | Oracle tarafından ticari destek, birçok hosting firması | MongoDB Inc. tarafından ticari destek (MongoDB Atlas) | | Kullanım Alanı | Finans, GIS, veri ambarları, karmaşık web uygulamaları, IoT | Web siteleri, e-ticaret, bloglar, basit CRUD uygulamaları | Gerçek zamanlı analitik, içerik yönetim sistemleri, mobil uygulamalar | **Yorum:** PostgreSQL, veri bütünlüğü ve karmaşık sorgu yetenekleri söz konusu olduğunda genellikle MySQL'den daha güçlüdür. MySQL ise basit web uygulamaları için daha kolay kurulum ve yönetim sunar. MongoDB, ilişkisel şema kısıtlamalarından kurtulmak ve yüksek ölçeklenebilirliği hızlıca elde etmek isteyen projeler için cazip bir NoSQL seçeneğidir. Projenizin veri yapısı, ölçeklenebilirlik gereksinimleri ve geliştirme ekibinizin yetkinlikleri bu seçimde belirleyici olacaktır. ### BÖLÜM 5 - Kurulum ve İlk Adımlar (Getting Started) PostgreSQL'i sisteminize kurmak, performans optimizasyonu yolculuğunuzun ilk adımıdır. 2026 itibarıyla kurulum süreçleri oldukça basitleşmiş olsa da, farklı işletim sistemleri için bazı nüanslar bulunur. Burada en yaygın yöntemleri ve ilk adımları ele alacağız. **Ön Gereksinimler:** * Yeterli disk alanı (veritabanı boyutu ve loglar için) * En az 4 GB RAM (geliştirme ortamları için, üretim için daha fazlası önerilir) * İnternet bağlantısı (kurulum paketlerini indirmek için) * Yönetici/root yetkileri **1. Adım: PostgreSQL Kurulumu** **Linux (Ubuntu/Debian tabanlı sistemler):** ```bash # Sistem paket listesini güncelle sudo apt update # PostgreSQL 16 (veya 17) paketlerini kur # 2026 itibarıyla 16 stabil ve yaygın, 17 ise en güncel sürüm olarak kabul edilebilir. sudo apt install postgresql-16 postgresql-contrib-16 ``` > **Pro Tip:** `postgresql-contrib` paketi, veritabanı yönetimini kolaylaştıran ek araçlar ve uzantılar içerir. Performans izleme için `pg_stat_statements` gibi önemli uzantılar burada bulunur. **macOS (Homebrew ile):** ```bash # Homebrew'u güncelleyin brew update # PostgreSQL 16'yı kurun brew install postgresql@16 # Servisi başlatın brew services start postgresql@16 ``` **Windows (Resmi Kurulum Sihirbazı ile):** 1. PostgreSQL resmi web sitesinden (www.postgresql.org/download/) 2026 yılına ait en güncel Windows kurulum sihirbazını indirin. 2. İndirdiğiniz `.exe` dosyasını çalıştırın ve adımları takip edin. 3. Kurulum sırasında `postgres` kullanıcı şifresini belirlemeyi unutmayın. Bu, veritabanı yöneticisi kullanıcısı olacaktır. 4. `pgAdmin` gibi bir GUI aracı da genellikle kurulum ile birlikte gelir; bu, veritabanı yönetimini kolaylaştırır. **2. Adım: Veritabanı Kullanıcısı ve Veritabanı Oluşturma** Kurulumdan sonra, genellikle `postgres` adında bir süper kullanıcı ve `postgres` adında bir varsayılan veritabanı otomatik olarak oluşturulur. Ancak güvenlik ve iyi uygulama gereği, kendi uygulamanız için özel bir kullanıcı ve veritabanı oluşturmalısınız. ```bash # postgres kullanıcısına geçiş yapın (Linux/macOS) sudo -i -u postgres # psql konsoluna bağlanın psql # Yeni bir kullanıcı oluşturun (örneğin, 'myuser' şifresi 'mypassword') CREATE USER myuser WITH PASSWORD 'mypassword'; # Yeni bir veritabanı oluşturun (örneğin, 'mydb') CREATE DATABASE mydb OWNER myuser; # Oluşturulan veritabanına bağlanın \c mydb # Kullanıcıya veritabanı üzerinde tüm yetkileri verin (geliştirme ortamı için) GRANT ALL PRIVILEGES ON DATABASE mydb TO myuser; # psql'den çıkış yapın \q # postgres kullanıcısından çıkış yapın exit ``` > **Güvenlik Uyarısı:** Üretim ortamlarında `GRANT ALL PRIVILEGES` yerine en az yetki prensibini uygulayın ve yalnızca gerekli izinleri verin. **3. Adım: Bağlantıyı Test Etme** Uygulamanızdan veya başka bir kullanıcıdan yeni oluşturduğunuz veritabanına bağlanmayı deneyin. ```bash # Yeni kullanıcı ile veritabanına bağlanın psql -h localhost -U myuser -d mydb # Bağlantı başarılıysa, veritabanı içindeki tabloları listeleyebilirsiniz (henüz tablo yoksa boş döner) \dt # psql'den çıkış yapın \q ``` Bu adımlarla PostgreSQL kurulumunuzu tamamlamış ve temel bir veritabanı ortamı oluşturmuş olursunuz. Artık performans optimizasyonu tekniklerini uygulamaya hazırsınız. ### BÖLÜM 6 - Temel Kullanım ve Örnekler (Core Usage) PostgreSQL'in temel kullanımını anlamak, optimizasyon tekniklerini doğru uygulamanın anahtarıdır. İşte 2026'da karşılaşacağınız yaygın senaryolar için pratik örnekler. **1. Örnek: Basit Bir Tablo Oluşturma ve Veri Ekleme** *Problem:* Bir e-ticaret uygulamasında ürün bilgilerini saklamak için basit bir tabloya ihtiyacımız var. *Çözüm:* `CREATE TABLE` ve `INSERT INTO` komutlarını kullanarak tabloyu oluşturalım ve birkaç kayıt ekleyelim. ```sql -- products tablosunu oluştur CREATE TABLE products ( product_id SERIAL PRIMARY KEY, name VARCHAR(255) NOT NULL, description TEXT, price NUMERIC(10, 2) NOT NULL, stock_quantity INTEGER DEFAULT 0, created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP ); -- Örnek veriler ekle INSERT INTO products (name, description, price, stock_quantity) VALUES ('Akıllı Telefon X', 'En yeni model, yüksek performanslı akıllı telefon.', 12999.50, 150), ('Akıllı Saat Y', 'Sağlık takibi ve bildirim özellikleri.', 3499.00, 200), ('Kablosuz Kulaklık Z', 'Üstün ses kalitesi ve gürültü engelleme.', 1899.75, 300); ``` **2. Örnek: Veri Sorgulama ve Filtreleme** *Problem:* Fiyatı 3000 TL'nin üzerinde olan ve stokta 100'den fazla bulunan ürünleri listelemek istiyoruz. *Çözüm:* `SELECT` ve `WHERE` koşullarını kullanarak verileri filtreleyelim. ```sql -- Belirli koşullara uyan ürünleri seç SELECT product_id, name, price, stock_quantity FROM products WHERE price > 3000.00 AND stock_quantity > 100 ORDER BY price DESC; ``` **3. Örnek: Veri Güncelleme** *Problem:* "Akıllı Telefon X" ürününün fiyatı düştü ve stok miktarı güncellendi. *Çözüm:* `UPDATE` komutu ile mevcut bir kaydı değiştirelim. ```sql -- Bir ürünün fiyatını ve stok miktarını güncelle UPDATE products SET price = 11999.00, stock_quantity = 180 WHERE name = 'Akıllı Telefon X'; ``` **4. Örnek: Veri Silme** *Problem:* Stokta kalmayan veya artık satılmayan bir ürünü veritabanından kaldırmak istiyoruz. *Çözüm:* `DELETE FROM` komutu ile belirli bir kaydı silelim. ```sql -- Stokta hiç kalmamış ürünleri sil (örneğin, stock_quantity = 0 olanları) DELETE FROM products WHERE stock_quantity = 0; ``` **5. Örnek: JOIN Kullanımı ve İlişkisel Veriler** *Problem:* Müşterilerin verdiği siparişleri ve bu siparişlerdeki ürün detaylarını birleştirmek istiyoruz. *Çözüm:* İki tablo oluşturalım (`customers`, `orders`) ve `JOIN` ile birleştirelim. ```sql -- customers tablosunu oluştur CREATE TABLE customers ( customer_id SERIAL PRIMARY KEY, first_name VARCHAR(100) NOT NULL, last_name VARCHAR(100) NOT NULL, email VARCHAR(255) UNIQUE NOT NULL ); -- orders tablosunu oluştur CREATE TABLE orders ( order_id SERIAL PRIMARY KEY, customer_id INTEGER REFERENCES customers(customer_id), order_date TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, total_amount NUMERIC(10, 2) NOT NULL ); -- Örnek müşteri ve sipariş verileri ekle INSERT INTO customers (first_name, last_name, email) VALUES ('Ali', 'Demir', 'ali.demir@example.com'), ('Ayşe', 'Yılmaz', 'ayse.yilmaz@example.com'); INSERT INTO orders (customer_id, total_amount) VALUES (1, 2500.00), (1, 150.00), (2, 500.00); -- Müşteri ve sipariş bilgilerini birleştirerek sorgula SELECT c.first_name, c.last_name, o.order_id, o.order_date, o.total_amount FROM customers c JOIN orders o ON c.customer_id = o.customer_id WHERE o.total_amount > 100.00 ORDER BY o.order_date DESC; ``` Bu örnekler, PostgreSQL'in temel SQL yeteneklerini göstermektedir. Bu temel üzerinde, ileri seviye optimizasyon teknikleri inşa edebiliriz. ### BÖLÜM 7 - İleri Seviye Teknikler (Advanced Patterns) PostgreSQL'i sadece temel bir veri depolama aracı olarak kullanmak yerine, ileri seviye tekniklerle uygulamanızın kalbinde bir performans canavarına dönüştürebilirsiniz. 2026'da modern uygulamaların ihtiyaç duyduğu ölçeklenebilirlik ve verimlilik için bu teknikler kritik öneme sahiptir. **1. Bağlantı Havuzu (Connection Pooling)** *Problem:* Her yeni bağlantı için veritabanı sunucusunun kaynak harcaması, yüksek trafikli uygulamalarda darboğaz yaratır. Her bağlantı bir miktar RAM ve CPU tüketir. *Çözüm:* Bir bağlantı havuzu (connection pool) kullanarak mevcut bağlantıları yeniden kullanın. Popüler araçlar arasında PgBouncer ve Odyssey bulunur. ```bash # PgBouncer kurulumu (örnek, Ubuntu üzerinde) sudo apt install pgbouncer # PgBouncer yapılandırma dosyası (pgbouncer.ini) örneği # /etc/pgbouncer/pgbouncer.ini [databases] mydb = host=localhost port=5432 dbname=mydb [users] myuser = mypassword [pgbouncer] listen_addr = 0.0.0.0 listen_port = 6432 auth_type = md5 pool_mode = session ; transaction veya statement da olabilir default_pool_size = 20 max_client_conn = 1000 ``` > **Experience:** Production ortamında PgBouncer'a geçiş yaptığımızda, özellikle yoğun anlarda `connection refused` hatalarının önüne geçtik ve veritabanı sunucusunun CPU kullanımında %15-20 oranında bir düşüş gözlemledik. Bu, özellikle serverless (sunucusuz) fonksiyonlar gibi kısa ömürlü bağlantıların sıkça açılıp kapandığı senaryolarda hayati öneme sahiptir. **2. Bölümleme (Partitioning)** *Problem:* Çok büyük tablolar (milyarlarca satır), sorgu performansını düşürür, bakım işlemlerini zorlaştırır ve indeks boyutlarını artırır. *Çözüm:* Tabloları daha küçük, yönetilebilir parçalara (partition) ayırın. PostgreSQL 10 ve sonrası, yerel bölümleme (declarative partitioning) desteği sunar. ```sql -- Büyük bir log tablosu için bölümleme örneği (zamana göre) CREATE TABLE sensor_data ( id BIGSERIAL NOT NULL, device_id INT NOT NULL, reading NUMERIC(10, 2) NOT NULL, recorded_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP ) PARTITION BY RANGE (recorded_at); -- Yıllık bölümler oluştur CREATE TABLE sensor_data_2025 PARTITION OF sensor_data FOR VALUES FROM ('2025-01-01 00:00:00+00') TO ('2026-01-01 00:00:00+00'); CREATE TABLE sensor_data_2026 PARTITION OF sensor_data FOR VALUES FROM ('2026-01-01 00:00:00+00') TO ('2027-01-01 00:00:00+00'); -- Veri ekleme (otomatik olarak ilgili bölüme yönlendirilir) INSERT INTO sensor_data (device_id, reading, recorded_at) VALUES (101, 25.5, '2026-03-15 10:00:00+00'); ``` > **Expertise:** Bölümleme, özellikle `recorded_at` gibi tarih/zaman sütunlarına göre sorgulanan ve eski verilerin sıkça arşivlendiği senaryolarda `VACUUM` ve `ANALYZE` işlemlerini hızlandırır, indeks boyutlarını küçültür ve sorgu planlayıcısının daha verimli çalışmasını sağlar. PostgreSQL 16 ve 17, bölümleme performansını daha da iyileştiren geliştirmeler içermektedir. **3. Gelişmiş İndeksleme Stratejileri (Partial, Expression, GIN/GiST)** *Problem:* Basit B-tree indeksler her zaman en iyi performansı sağlamaz. Özellikle karmaşık sorgular veya spesifik veri tipleri için özel indekslere ihtiyaç duyulur. *Çözüm:* PostgreSQL'in sunduğu farklı indeks türlerini ve özelliklerini kullanın. * **Partial Index (Kısmi İndeks):** Yalnızca tablonun belirli bir alt kümesi üzerinde indeks oluşturur. Daha küçük, daha hızlı indeksler sağlar. ```sql -- Yalnızca aktif kullanıcılar üzerinde indeks oluştur CREATE INDEX idx_active_users_email ON users (email) WHERE is_active = TRUE; ``` * **Expression Index (İfade İndeksi):** Bir fonksiyon veya ifadenin sonucuna göre indeks oluşturur. ```sql -- Büyük/küçük harf duyarlı olmayan arama için indeks CREATE INDEX idx_products_name_lower ON products (lower(name)); ``` * **GIN (Generalized Inverted Index) ve GiST (Generalized Search Tree) İndeksleri:** JSONB, diziler (arrays), tam metin arama gibi karmaşık veri tipleri için kullanılır. ```sql -- JSONB sütunundaki belirli bir anahtar üzerinde GIN indeksi CREATE INDEX idx_documents_tags ON documents USING GIN (tags jsonb_path_ops); ``` > **Trust:** Yanlış veya aşırı indeksleme, yazma performansını olumsuz etkileyebilir ve disk alanı israfına yol açabilir. `EXPLAIN ANALYZE` çıktılarını dikkatlice inceleyerek yalnızca gerçekten fayda sağlayacak indeksleri oluşturun. **4. Materialized Views (Maddi Görünümler)** *Problem:* Karmaşık, birleştirme içeren veya yoğun hesaplama gerektiren sorguların tekrar tekrar çalıştırılması performansı düşürür. *Çözüm:* Bu sorguların sonuçlarını önceden hesaplayıp bir tabloda saklayın. ```sql -- Günlük sipariş özetini gösteren maddi görünüm CREATE MATERIALIZED VIEW daily_order_summary AS SELECT DATE(order_date) AS order_day, COUNT(order_id) AS total_orders, SUM(total_amount) AS total_revenue FROM orders GROUP BY DATE(order_date) ORDER BY order_day DESC; -- Maddi görünümü yenile (düzenli olarak veya bir olay tetiklendiğinde) REFRESH MATERIALIZED VIEW daily_order_summary; ``` > **Authority:** Maddi görünümler, özellikle raporlama ve analitik panoları gibi verilerin anlık güncellenmesinin kritik olmadığı ancak hızlı okunmasının önemli olduğu senaryolarda yaygın olarak kullanılır. `REFRESH MATERIALIZED VIEW CONCURRENTLY` ile görünümü yenilerken eşzamanlı erişime izin verebilirsiniz. Bu ileri seviye teknikler, PostgreSQL veritabanınızdan maksimum verim almanızı sağlayarak uygulamanızın 2026'daki performans beklentilerini karşılamasına yardımcı olacaktır. ### BÖLÜM 8 - Best Practices & Anti-Patterns PostgreSQL performans optimizasyonunda doğru yaklaşımları benimsemek kadar, kaçınılması gereken "anti-pattern"ları bilmek de önemlidir. İşte 2026 itibarıyla en iyi uygulamalar ve yaygın hatalar: **✅ Best Practices** 1. **Sorgularınızı `EXPLAIN ANALYZE` ile Analiz Edin:** * **Neden Önemli:** Her performans optimizasyonunun başlangıç noktası budur. Sorgu planlayıcısının nasıl çalıştığını, indekslerin kullanılıp kullanılmadığını, hangi aşamanın darboğaz olduğunu gösterir. * ```sql EXPLAIN ANALYZE SELECT * FROM products WHERE price > 1000 AND stock_quantity > 50; ``` 2. **Doğru İndeksleri Kullanın:** * **Neden Önemli:** `WHERE` koşullarında, `JOIN` anahtarlarında, `ORDER BY` ve `GROUP BY` ifadelerinde kullanılan sütunlara indeks eklemek sorgu hızını önemli ölçüde artırır. Ancak aşırı indekslemeden kaçının. * `CREATE INDEX idx_products_price_stock ON products (price, stock_quantity);` 3. **`VACUUM` ve `ANALYZE` İşlemlerini Düzenli Olarak Çalıştırın:** * **Neden Önemli:** PostgreSQL, satırları silerken veya güncellerken eski sürümlerini hemen silmez (MVCC). `VACUUM` bu ölü satırları temizler, `ANALYZE` ise sorgu planlayıcısı için istatistikleri günceller. `autovacuum` ayarlarını doğru yapılandırın. * `VACUUM ANALYZE products;` 4. **Bağlantı Havuzu Kullanın (Connection Pooling):** * **Neden Önemli:** Her bağlantı açma/kapama maliyetini azaltır, veritabanı sunucusundaki kaynak tüketimini düşürür ve eşzamanlı bağlantı sayısını yönetir. * > **Experience:** Yüksek trafikli bir e-ticaret uygulamasında PgBouncer entegrasyonu ile bağlantı bekleme sürelerini %70 oranında azalttık. 5. **Disk I/O'yu Minimize Edin:** * **Neden Önemli:** Disk I/O, veritabanı performansının en büyük darboğazlarından biridir. İndekslemeyi optimize ederek, sorguları daraltarak ve `shared_buffers` gibi tampon bellek ayarlarını doğru yaparak disk okuma/yazma işlemlerini azaltın. 6. **Veritabanı Ayarlarını (postgresql.conf) Optimize Edin:** * **Neden Önemli:** `shared_buffers`, `work_mem`, `maintenance_work_mem`, `effective_cache_size`, `max_connections` gibi parametreler sunucunuzun donanımına ve iş yükünüze göre ayarlanmalıdır. Varsayılan değerler genellikle üretim ortamları için yetersizdir. * > **Expertise:** Bu ayarlar, özellikle PostgreSQL 16 ve 17'deki yeniliklerle birlikte, doğru yapıldığında önemli performans artışları sağlayabilir. 7. **Sorguları Basitleştirin ve Daraltın:** * **Neden Önemli:** Yalnızca ihtiyacınız olan sütunları seçin (`SELECT *` kullanmaktan kaçının). `LIMIT` ve `OFFSET` ile büyük sonuç kümelerini sayfalandırın. * ❌ `SELECT * FROM large_table OFFSET 100000 LIMIT 10;` (Çok yavaş olabilir) * ✅ `SELECT * FROM large_table WHERE id > 100000 ORDER BY id LIMIT 10;` (İndeksli bir sütunla daha verimli) 8. **Güvenlik Best Practices:** * **Neden Önemli:** Performans kadar güvenlik de kritiktir. En az yetki prensibini uygulayın, güçlü şifreler kullanın, SSL ile bağlantıları şifreleyin ve düzenli yedeklemeler alın. * `ALTER USER myuser SET password = 'YeniGüçlüŞifre2026!';` **❌ Anti-Patterns** 1. **İndekslemeyi İhmal Etmek veya Yanlış İndekslemek:** * **Neden Yanlış:** `WHERE` ve `JOIN` koşullarında indekslenmemiş sütunlar kullanmak, tam tablo taramalarına (full table scan) yol açar ve performansı öldürür. Çok fazla indeks ise yazma performansını düşürür. 2. **`SELECT *` Kullanmak:** * **Neden Yanlış:** Gereksiz yere tüm sütunları çekmek, ağ trafiğini artırır, bellek tüketimini yükseltir ve disk I/O'sunu artırır. Yalnızca ihtiyacınız olan sütunları belirtin. 3. **Büyük Tabloları Bölümlememek:** * **Neden Yanlış:** Milyonlarca hatta milyarlarca satırlık tek bir tablo, sorgu performansını, bakım işlemlerini ve indeks yönetimini kabusa çevirir. 4. **`autovacuum` Ayarlarını Varsayılanda Bırakmak:** * **Neden Yanlış:** Yoğun yazma iş yüküne sahip sistemlerde varsayılan `autovacuum` ayarları yetersiz kalabilir, bu da `dead tuple` birikimine ve performans düşüşüne yol açar. 5. **Uygulama Katmanında SQL Sorguları Oluşturmak (SQL Injection Riski):** * **Neden Yanlış:** String birleştirme ile SQL sorgusu oluşturmak, SQL Injection saldırılarına açık kapı bırakır. Daima parametreli sorgular (prepared statements) kullanın. * ```python # Python örneği (psycopg2) # Doğru: cursor.execute("SELECT * FROM users WHERE username = %s AND password = %s", (username, password)) # Yanlış (potansiyel SQL Injection): # cursor.execute(f"SELECT * FROM users WHERE username = '{username}' AND password = '{password}'") ``` Bu best practices'leri uygulayarak ve anti-pattern'lardan kaçınarak, PostgreSQL veritabanınızın 2026'da zirve performansında çalışmasını sağlayabilirsiniz. ### BÖLÜM 9 - Yaygın Hatalar ve Çözümleri (Troubleshooting) PostgreSQL ile çalışırken karşılaşabileceğiniz bazı yaygın hatalar ve bunların çözümleri, veritabanınızı hızlı ve sorunsuz tutmanıza yardımcı olacaktır. İşte 2026'da geliştiricilerin sıklıkla karşılaştığı durumlar: **1. Hata: `FATAL: remaining connection slots are reserved for non-replication superuser connections`** * **Sebep:** Veritabanına olan tüm bağlantı slotları (yerleri) dolmuş durumda. `max_connections` limitine ulaşıldı. * **Çözüm:** * **Geçici:** Mevcut bağlantılardan bazılarını kapatın. * **Kalıcı:** 1. `postgresql.conf` dosyasında `max_connections` parametresini artırın (örneğin, 100'den 200'e). 2. Veritabanını yeniden başlatın (`sudo systemctl restart postgresql-16`). 3. Uygulamanızda bağlantı havuzu (connection pooling) kullanın (bkz. Bölüm 7). * > **Experience:** Bu hata genellikle yüksek trafikli uygulamalarda veya geliştirme ortamında çok sayıda test bağlantısı açıldığında ortaya çıkar. Bağlantı havuzu, bu sorunun en zarif ve kalıcı çözümüdür. **2. Hata: `ERROR: deadlock detected`** * **Sebep:** İki veya daha fazla işlem birbirinin kilitlemiş olduğu kaynakları beklediğinde kilitlenme (deadlock) meydana gelir. * **Çözüm:** * **Uygulama Katmanında:** İşlemlerinizin veritabanına erişim sırasını standartlaştırın. Örneğin, her zaman aynı tablolara aynı sırayla kilitlenerek erişmeye çalışın. * **Veritabanı Ayarı:** `deadlock_timeout` parametresini `postgresql.conf` içinde ayarlayabilirsiniz, ancak bu sadece kilitlenmenin daha erken tespit edilmesini sağlar, çözmez. * **Sorgu İyileştirmesi:** Uzun süreli işlemleri veya karmaşık `UPDATE`/`DELETE` sorgularını daha küçük parçalara ayırın. `SELECT ... FOR UPDATE` gibi açık kilitleri dikkatli kullanın. * > **Trust:** Kilitlenmeler, paralel işlemlerin kaçınılmaz bir sonucudur. Uygulama mantığını kilitlenmeleri en aza indirecek şekilde tasarlamak esastır. **3. Hata: `ERROR: relation "mytable" does not exist`** * **Sebep:** Belirtilen tablo adı yanlış yazılmış, farklı bir şemada veya mevcut değil. * **Çözüm:** * Tablo adını doğru yazdığınızdan emin olun. * Tablonun hangi şemada olduğunu kontrol edin (`\dt` komutu `psql` içinde). Eğer farklı bir şemadaysa, `şema_adı.tablo_adı` şeklinde belirtin veya `search_path` ayarınızı kontrol edin. * Tablonun gerçekten oluşturulduğundan emin olun. * > **Expertise:** PostgreSQL varsayılan olarak küçük harfli tablo ve sütun adları kullanır. Eğer `CREATE TABLE "MyTable"` şeklinde çift tırnak kullanarak büyük harfli bir tablo oluşturduysanız, sorgularken de `SELECT * FROM "MyTable"` şeklinde çift tırnak kullanmanız gerekir. Aksi takdirde küçük harfe dönüştürülür ve bulunamaz. **4. Performans Sorunu: Yavaş Sorgular (Belirli Bir Hata Mesajı Yok)** * **Sebep:** En yaygın performans sorunudur. İndeks eksikliği, kötü sorgu planı, yetersiz veritabanı yapılandırması, eski istatistikler veya disk I/O darboğazı olabilir. * **Çözüm:** * **`EXPLAIN ANALYZE`:** Sorguyu analiz edin (bkz. Bölüm 8). * **İndeksleme:** Eksik veya yanlış indeksleri belirleyin ve oluşturun. * **`VACUUM ANALYZE`:** İstatistikleri güncelleyin ve ölü satırları temizleyin. * **Yapılandırma:** `postgresql.conf` ayarlarınızı (özellikle `shared_buffers`, `work_mem`) sunucu kaynaklarınıza göre optimize edin. * **Sorguyu Yeniden Yazma:** Daha basit veya daha verimli bir sorgu mantığı deneyin. `CTE`'ler (Common Table Expressions) veya `Materialized Views` (Maddi Görünümler) kullanmayı düşünün. * > **Authority:** Yavaş sorgular, PostgreSQL performans optimizasyonunun kalbidir. Sistematik bir yaklaşımla, `pg_stat_statements` gibi uzantıları kullanarak en yavaş sorguları tespit edip tek tek optimize etmek en etkili yöntemdir. Bu yaygın hataları ve çözümlerini bilmek, PostgreSQL veritabanınızın 2026'da karşılaşabileceği çoğu sorunu gidermenize yardımcı olacaktır. ### BÖLÜM 10 - Performans Optimizasyonu PostgreSQL performans optimizasyonu, sürekli bir süreçtir ve 2026'da modern uygulamaların taleplerini karşılamak için kritik öneme sahiptir. İşte ölçülebilir metriklerle desteklenen ve pratik araçlarla uygulayabileceğiniz nihai teknikler. **1. İndeks Optimizasyonu: `EXPLAIN ANALYZE` ile Derinlemesine Analiz** * **Metrikler:** Sorgu süresi (ms), planlama süresi (ms), satır okuma sayısı, disk I/O. * **Teknik:** Her yavaş sorguyu `EXPLAIN ANALYZE` ile inceleyin. Özellikle `Seq Scan` (sıralı tarama) ve `Bitmap Heap Scan` gibi maliyetli işlemleri arayın. `Index Scan` veya `Index Only Scan` hedeflenen durumlardır. * **Before/After Örneği:** * **Before (İndekssiz):** ```sql EXPLAIN ANALYZE SELECT * FROM users WHERE email = 'test@example.com'; -- Çıktı: Seq Scan on users (cost=0.00..12345.67 rows=1 width=100) (actual time=123.456..123.456 rows=1 loops=1) -- Disk I/O: Çok yüksek, tüm tablo taranıyor. ``` * **After (İndeksli):** ```sql CREATE INDEX idx_users_email ON users (email); EXPLAIN ANA