Sql & Veritabanı İle Performans Odaklı Veri Sorgulama Optimizasyonu Nasıl Yapılır?

Sql & Veritabanı İle Performans Odaklı Veri Sorgulama Optimizasyonu Nasıl Yapılır?
Sql & Veritabanı İle Performans Odaklı Veri Sorgulama Optimizasyonu Nasıl Yapılır?

Gereksinimler ve Ön Hazırlık

Performans odaklı bir çalışma ortamı için aşağıdaki araçların güncel sürümlerine sahip olmanız gerekmektedir. 2026 yılı itibarıyla PostgreSQL 17+ veya MySQL 9.0+ sürümleri, gelişmiş sorgu planlayıcıları ile optimizasyon süreçlerini kolaylaştırmaktadır.

  • Veritabanı Yönetim Sistemi: PostgreSQL veya MySQL (Yerel veya bulut tabanlı).
  • İnceleme Aracı: EXPLAIN ANALYZE komutunu destekleyen bir SQL istemcisi (DBeaver, pgAdmin veya MySQL Workbench).
  • Veri Seti: Performans testleri için en az 100.000 satırlık örnek bir tablo yapısı.

Adım 1: Sorgu Planlayıcıyı Anlamak ve EXPLAIN Kullanımı

Bir sorgunun neden yavaş çalıştığını anlamanın ilk yolu, veritabanının o sorguyu nasıl işlediğini görmektir. EXPLAIN ANALYZE komutu, sorgunun çalışma planını, hangi indekslerin kullanıldığını ve işlemin ne kadar sürdüğünü detaylandırır.

EXPLAIN ANALYZE 
SELECT * FROM siparisler 
WHERE musteri_id = 4521 
AND siparis_tarihi > '2026-01-01';

Bu kod bloğu, veritabanının ilgili tabloyu tararken bir "Sequential Scan" (tüm tabloyu satır satır okuma) mı yoksa "Index Scan" mi yaptığını gösterir. Eğer "Seq Scan" görüyorsanız, sorgunuz indekslenmemiş bir sütun üzerinde çalışıyor demektir.

Adım 2: İndeksleme Stratejileri ve Doğru Kullanım

İndeksler, veritabanının veriye ulaşma hızını artıran birer yol haritasıdır. Ancak gereğinden fazla indeks, veri ekleme (INSERT) ve güncelleme (UPDATE) işlemlerini yavaşlatır. İhtiyaca yönelik, seçici indeksler oluşturmak esastır.

-- İndeks oluşturma örneği
CREATE INDEX idx_musteri_siparis_tarih 
ON siparisler (musteri_id, siparis_tarihi);

Bu örnekte, hem musteri_id hem de siparis_tarihi sütunlarını kapsayan bir "Composite Index" (bileşik indeks) oluşturduk. Bu, özellikle WHERE koşulunda bu iki sütunu birlikte kullanan sorgular için performansı dramatik şekilde artırır.

Adım 3: SELECT * Kullanımından Kaçınmak

Yeni başlayanların yaptığı en yaygın hata, ihtiyaç duyulmayan tüm sütunları çekmek için SELECT * kullanmaktır. Bu durum, ağ trafiğini artırır ve veritabanının gereksiz veri okumasına neden olur. Sadece gerekli sütunları belirtmek, "Covering Index" (kapsayıcı indeks) kullanımına da olanak tanır.

-- Yanlış kullanım
SELECT * FROM kullanicilar WHERE aktif = 1;

-- Doğru kullanım
SELECT id, ad, soyad FROM kullanicilar WHERE aktif = 1;

Sadece ihtiyaç duyulan sütunları çekmek, veritabanı belleğinin (RAM) daha verimli kullanılmasına ve sorgu yanıt süresinin azalmasına yardımcı olur.

Adım 4: JOIN Operasyonlarında Performans

Çoklu tablo birleştirmelerinde (JOIN), tabloların birbirine bağlandığı sütunların indeksli olması zorunludur. Ayrıca, INNER JOIN ile LEFT JOIN arasındaki mantıksal farkı iyi gözetmeli ve gereksiz birleştirme işlemlerinden kaçınmalısınız.

SELECT k.ad, s.tutar 
FROM kullanicilar k
INNER JOIN siparisler s ON k.id = s.kullanici_id
WHERE s.tutar > 500;

Burada kullanici_id sütununun siparisler tablosunda indeksli olduğundan emin olmalısınız. Aksi takdirde, veritabanı her bir kullanıcı için tüm siparişler tablosunu taramak zorunda kalacaktır.

Adım 5: Veritabanı Optimizasyon Yöntemleri Karşılaştırması

Yöntem Avantajı Dezavantajı
İndeksleme Okuma hızını artırır. Yazma işlemlerini yavaşlatır.
Sütun Seçimi Bellek tasarrufu sağlar. Kodun güncellenmesini gerektirir.
Partitioning Büyük veride hızlı erişim. Karmaşık yönetim yapısı.

Adım 6: Güvenlik ve Performans Dengesi

Kritik Uyarı: Performans artırımı yaparken güvenlikten ödün vermeyin. Asla kullanıcıdan gelen veriyi doğrudan sorguya eklemeyin. SQL Injection saldırılarına karşı her zaman "Prepared Statements" veya "Parameterized Queries" kullanın.

-- Güvenli sorgu örneği (PHP/PDO yaklaşımı)
$stmt = $pdo->prepare('SELECT ad FROM kullanicilar WHERE id = :id');
$stmt->execute(['id' => $kullaniciGirdisi]);
$kullanici = $stmt->fetch();

Bu yöntem, hem veritabanı sorgusunun önbelleğe alınmasını (query cache) sağlayarak performansı artırır hem de uygulamanızı SQL Injection saldırılarına karşı korur.

Sıkça Sorulan Sorular

İndeksler her zaman performansı artırır mı?

Hayır. Çok sık güncellenen tablolarda aşırı indeksleme, yazma işlemlerini yavaşlatır. İndeksler, okuma ağırlıklı işlemler için tasarlanmalıdır.

Sorgu planını nasıl okumalıyım?

EXPLAIN ANALYZE çıktısında "cost" değerlerine ve "rows" tahminlerine bakın. Eğer tahmin edilen satır sayısı ile gerçek satır sayısı çok farklıysa, istatistikleriniz güncel değildir.

İstatistikler neden önemlidir?

Veritabanı, sorguyu nasıl işleyeceğine tablodaki veri dağılımına bakarak karar verir. ANALYZE komutunu düzenli çalıştırarak istatistikleri güncel tutmalısınız.

Neden JOIN yerine Subquery kullanmamalıyım?

Modern veritabanı motorları JOIN işlemlerini optimize etmekte daha başarılıdır. Subquery (alt sorgu) kullanımı bazen veritabanı motorunun yanlış bir plan seçmesine neden olabilir.

Veritabanı sunucusu ile uygulama sunucusu aynı yerde mi olmalı?

Gecikmeyi (latency) azaltmak için veritabanı ve uygulama sunucularının aynı veri merkezi içerisinde olması, ağ performansını doğrudan iyileştirir.

İleri Düzey Teknikler: Veritabanı Partitioning ve Sharding Stratejileri

Veri setleriniz milyonlarca satıra ulaştığında, standart indeksleme yöntemleri bile sorgu sürelerini kısaltmada yetersiz kalabilir. Bu noktada, veritabanı mimarisini yatay veya dikey olarak parçalamak (Partitioning & Sharding) kaçınılmaz hale gelir. Partitioning, büyük bir tabloyu mantıksal parçalara bölerek sorgu motorunun sadece ilgili veri kümesini taramasını sağlar.

Partitioning Uygulama Örneği (PostgreSQL)

Örneğin, satış verilerini tutan bir tablonuz varsa, bu tabloyu tarih bazlı bölümlere ayırarak sorgu performansını ciddi oranda artırabilirsiniz:

CREATE TABLE satislar (
    id SERIAL,
    tarih DATE NOT NULL,
    tutar DECIMAL
) PARTITION BY RANGE (tarih);

CREATE TABLE satislar_2023 PARTITION OF satislar
    FOR VALUES FROM ('2023-01-01') TO ('2024-01-01');

CREATE TABLE satislar_2024 PARTITION OF satislar
    FOR VALUES FROM ('2024-01-01') TO ('2025-01-01');

Bu yapı sayesinde, 2024 yılına ait verileri sorguladığınızda veritabanı motoru 2023 tablosunu tamamen görmezden gelir (Partition Pruning), bu da I/O maliyetini minimuma indirir.

Performans İzleme ve Hata Ayıklama (Query Profiling)

Sorgu optimizasyonu sadece kod yazarken değil, canlı sistemlerdeki darboğazları tespit ederken de devam eder. Yavaş sorguları tespit etmek için veritabanının sunduğu "Slow Query Log" özelliklerini aktif etmelisiniz.

Yavaş Sorguları Tespit Etme ve İyileştirme

MySQL üzerinde yavaş sorguları loglamak için aşağıdaki konfigürasyon adımlarını izleyebilirsiniz. Bu, uygulama performansını düşüren gizli "katil sorguları" bulmanıza yardımcı olur:

-- Yavaş sorgu logunu aktif et
SET GLOBAL slow_query_log = 'ON';
-- 2 saniyeden uzun süren sorguları kaydet
SET GLOBAL long_query_time = 2;
-- Hangi sorguların indeks kullanmadığını belirle
SET GLOBAL log_queries_not_using_indexes = 'ON';

Performans Metrikleri Tablosu

Sorgu iyileştirme sürecinde hedeflemeniz gereken temel metrikler şunlardır:

Metrik Hedef Değer Açıklama
Query Latency < 100ms Standart bir okuma sorgusu için ideal süre.
Index Hit Rate > 95% Verinin disk yerine bellekten okunma oranı.
Deadlock Sayısı 0 Eşzamanlı işlemlerde çakışma olmamalıdır.

Unutmayın ki, veritabanı optimizasyonu bir "kur ve unut" süreci değildir. Uygulamanız büyüdükçe veri dağılımı değişir; bu nedenle düzenli olarak ANALYZE komutunu çalıştırarak veritabanı istatistiklerini güncel tutmak, sorgu planlayıcının her zaman en verimli yolu seçmesini sağlar.

Sonuç

Sql & Veritabanı ile performans odaklı veri sorgulama optimizasyonu, sürekli takip ve iyileştirme gerektiren bir süreçtir. EXPLAIN ANALYZE ile sorgularınızı analiz etmeyi, doğru indeksleme stratejileri kurmayı ve her zaman güvenli kod yazmayı alışkanlık haline getirmelisiniz. Bir sonraki adım olarak, veritabanı "Caching" (önbellekleme) mekanizmalarını (Redis gibi) araştırmanızı ve sorgu sonuçlarını uygulama katmanında nasıl daha verimli saklayacağınızı öğrenmenizi öneririm.

Yasal Uyarı: Bu rehberdeki kod örnekleri eğitim amaçlıdır. Üretim ortamında (production) herhangi bir değişiklik yapmadan önce mutlaka veritabanı yedeği alınız ve değişiklikleri önce bir test ortamında doğrulayınız.

Bu yazıya tepkinizi paylaşın:
Mert Çelik

Hobi ve teknik beceriler üzerine eğitici içerikler kurguluyorum. Okuyucuların günlük hayatta karşılaştığı sorunlara uygulanabilir çözümler sunmayı hedefliyorum.

Yorumlar (16)

16
okuyucu bu yazı hakkında yorum yaptı. Siz de deneyiminizi paylaşarak diğer okuyuculara yardımcı olabilirsiniz.
Caner Yılmaz
Caner Yılmaz 30 Temmuz 2026

Eline sağlık Mert, execution plan okumayı yeni yeni öğreniyorum, bu yazı çok aydınlatıcı oldu. Özellikle indeksleme kısmındaki püf noktalar tam aradığım şeydi.

Mert Çelik
Mert Çelik 01 Ağustos 2026

Çok teşekkürler Caner, execution plan konusu başta karmaşık gelse de mantığını kavrayınca vazgeçilmez oluyor.

Selin_Dev
Selin_Dev 01 Ağustos 2026

Ya indexleri kurdukta bazen sorgu hızı hiç değişmiyor, neden oluyo bu? Bide sürekli optimize etmek çok zaman alıyor, bunun pratik bi yolu yok mu?

Burak Şen
Burak Şen 02 Ağustos 2026

Selin, bazen indexler parçalanmış oluyor, rebuild etmeyi denedin mi? Genelde o çözüyor sorunu.

Hakan Aras
Hakan Aras 02 Ağustos 2026

İçerik güzel ama keşke biraz daha fazla örnek kod bloğu ekleseydin. Yine de genel mantığı oturtmak adına gayet başarılı bir yazı.

Mert Çelik
Mert Çelik 03 Ağustos 2026

Haklısın Hakan, bir sonraki yazıda daha detaylı kod örnekleri ve senaryolar üzerinden gideceğim. Geri bildirimin için teşekkürler.

Mehmet Fırat
Mehmet Fırat 03 Ağustos 2026

Abi anlatım harika olmuş, ben uzun zamandır bu performans sorunlarıyla uğraşıyodum. Özellikle joinlerdeki gereksiz veri çekme işini çözdükten sonra sistem kendine geldi.

Mert Çelik
Mert Çelik 04 Ağustos 2026

Harika bir haber Mehmet! Join optimizasyonu çoğu zaman en büyük kazancı sağlıyor zaten, sevindim işine yaramasına.

Zeynep Kılıç
Zeynep Kılıç 03 Ağustos 2026

SQL tuning üzerine Türkçe kaynak bulmak gerçekten zor, bu seri çok işime yarayacak. Teşekkürler paylaşım için.

Emre Demir
Emre Demir 04 Ağustos 2026

Veritabanı tasarımından mı kaynaklanıyor yoksa sadece indeks mi? Bizde çok fazla kayıt var, select * atmaktan kaçınıyoruz ama yine de yavaş.

Deniz A.
Deniz A. 05 Ağustos 2026

Emre sadece indeks değil, veritabanı şemanın normalization durumu da çok etkiliyor bence bir göz at.

Ayşegül Tatlı
Ayşegül Tatlı 05 Ağustos 2026

Bu kadar karmaşık bir konuyu bu kadar sade anlatman çok iyi. Başka platformlarda çok teknik terime boğuyorlar, okuması çok keyifliydi.

Mustafa K.
Mustafa K. 05 Ağustos 2026

Benim veritabanında çok fazla 'fragmentation' var, bunları nasıl temizlerim? Otomatik bi işlem mi yapmalı yoksa manuel mi?

Mert Çelik
Mert Çelik 06 Ağustos 2026

Mustafa, bakım planları üzerinden otomatikleştirmek en sağlıklısı. Manuel işler hata payını artırır.

Kerem Tekin
Kerem Tekin 06 Ağustos 2026

PostgreSQL mi yoksa MySQL mi kullanıyosun? İndeksleme mantığı temelde aynı olsa da motorlar arası farklar var, ona da değinsen süper olur.

Melis Yıldırım
Melis Yıldırım 06 Ağustos 2026

Sonunda şu 'query execution plan' olayını anlayabileceğim bir kaynak buldum. Ellerinize sağlık, çok faydalı bi yazı olmuş.

Yorum Yaz