Tüm barındırma hizmetlerinde 15% tasarruf edin

Becerilerini test et ve herhangi bir hosting planında İndirim kazan

Kodu kullanın: Skills Başlayın
Bölüm
Özel Sunucular Sanal Sunucular Yönetim

MySQL Sorgu Optimizasyon Teknikleri: Daha Hızlı Veritabanı Performansı İçin Tam Rehber

Modern websites and web applications depend on databases more than ever. Whether you're running a small blog or a high-traffic e-commerce platform, MySQL remains one of the most widely deployed relational database systems in the world — and for good reason. It's powerful, flexible, and battle-tested. But as your project scales, poorly optimized queries can silently destroy performance, inflate server costs, and frustrate users with slow load times.

In this comprehensive guide, we'll walk through proven MySQL query optimization techniques used by experienced database administrators and DevOps engineers. Whether you're managing a VPS Hosting environment, a high-performance Dedicated Server, or a shared environment, these strategies will help you extract maximum performance from your MySQL setup.

MySQL Sorgu Optimizasyonunun Neden Önemli Olduğu

Tekniklere dalmadan önce, neyin tehlikede olduğunu anlamak değerlidir. Milyonlarca satıra sahip bir tablodaki tek bir optimize edilmemiş sorgu şunları yapabilir:

  • Aşırı CPU ve bellek kaynaklarını tüketmek
  • Tabloları kilitlemek ve eşzamanlı kullanıcıları engellemek
  • Tüm uygulamanız genelinde basamaklı yavaşlamalara neden olmak
  • Bunu telafi etmek için yatay olarak ölçeklendirirken altyapı maliyetlerini artırmak

Sorgu optimizasyonu tek seferlik bir görev değildir — verileriniz büyüdükçe bileşik temettüler ödeyen devam eden bir disiplindir.

1. Dizinleri Akıllıca Kullanın

Dizinler, tartışmasız MySQL optimizasyon cephaneliğinizdeki en etkili araçtır. Onlar olmadan, MySQL bir tam tablo taraması gerçekleştirir — eşleşen kayıtları bulmak için tablodaki her satırı okur. Büyük veri setlerinde bu felaket derecesinde yavaştır.

Dizinler Nasıl Çalışır

Bir dizin, MySQL’in logaritmik zamanda doğrusal zaman yerine geçebileceği ayrı bir veri yapısı (tipik olarak B-ağacı) oluşturur. Bunu bir ders kitabının arkasındaki dizin gibi düşünün: bir konuyu bulmak için her sayfayı okumak yerine, doğru sayfaya doğrudan atlarsınız.

Dizin Oluşturma En İyi Uygulamaları

  • WHERE, JOIN ve ORDER BY yan tümceleri içinde kullanılan sütunları dizinleyin — bunlar dizinlerden yararlanan en yaygın sorgu desenleridir
  • Bileşik dizinleri kullanın — aynı anda birden fazla sütunda filtre uygulayan sorgular için
  • Aşırı dizin oluşturmaktan kaçının — her dizin INSERT, UPDATE ve DELETE işlemlerine ek yük ekler çünkü MySQL dizini verilerle birlikte güncellemelidir
  • Mümkün olduğunda kapsayan dizinleri kullanın — bir sorgunun ihtiyaç duyduğu tüm sütunları içeren bir dizin, gerçek tablo satırlarına erişme ihtiyacını ortadan kaldırır

Örnek: Tek Sütunlu Dizin Oluşturma

CREATE INDEX idx_email ON users (email);

Örnek: Bileşik Dizin Oluşturma

CREATE INDEX idx_status_created ON orders (status, created_at);

Bu bileşik dizin aşağıdaki gibi sorguları verimli bir şekilde hizmet eder:

SELECT * FROM orders WHERE status = 'pending' ORDER BY created_at DESC;

Mevcut Dizinleri Kontrol Etme

SHOW INDEX FROM users;

Uygun dizin oluşturma tek başına, büyük tablolarda sorgu yürütme süresini saniyelerden milisaniyeye düşürebilir.

2. SELECT İfadelerinizi Optimize Edin

SQL geliştirmede en yaygın ve zararlı anti-patternlerden biri SELECT * kullanımıdır. Uygun görünse de, MySQL’i tablodaki her sütunu — ihtiyaç duymayabileceğiniz büyük TEXT veya BLOB alanları da dahil olmak üzere — almaya zorlar ve gereksiz verileri ağ üzerinden aktarır.

Temel Optimizasyon İlkeleri

  • Yalnızca ihtiyaç duyduğunuz sütunları seçin — bu, veri aktarımını, bellek kullanımını ve işlem süresini en aza indirir
  • Sonuçları sayfalandırmak için LIMIT kullanın — yalnızca bir alt kümeye ihtiyaç duyduğunuzda sınırsız sonuç kümeleri döndürmeyin
  • Toplama işlevlerini dikkatli bir şekilde uygulayınCOUNT(), SUM() ve AVG() verimlidir, ancak bunları dizine alınmamış sütunlarla birleştirmek pahalı olabilir
  • Gerekli olmadığı sürece DISTINCT kullanmaktan kaçının — bu, büyük veri setlerinde pahalı olabilecek bir yinelenenleri kaldırma adımı ekler

Optimizasyondan Önce

SELECT * FROM users WHERE status = 'active';

Optimizasyondan Sonra

SELECT user_id, name, email FROM users WHERE status = 'active' LIMIT 100;

Bu görünüşte küçük değişiklik, özellikle düzinelerce sütuna veya milyonlarca satıra sahip tablolarda bellek tüketimini ve sorgu yürütme süresini dramatik olarak azaltabilir.

3. EXPLAIN ve EXPLAIN ANALYZE ile Sorguları Analiz Edin

EXPLAIN ifadesi en güçlü tanı aracınızdır. MySQL’in sorgu yürütme planını — MySQL’in verilerinizi almak için kullandığı dahili stratejiyi — sorguyu gerçekten yürütmeden ortaya koymaktadır.

EXPLAIN Size Ne Söyler

SütunAnlamı
typeBirleştirme türü — ALL tam tablo taraması anlamına gelir (kötü); ref veya eq_ref iyidir
keyMySQL’in hangi indeksi kullandığı (veya hiçbiri kullanılmıyorsa NULL)
rowsMySQL’in inceleyeceği tahmini satır sayısı
ExtraEk bilgi — Using filesort veya Using temporary için dikkat edin

Temel EXPLAIN Örneği

EXPLAIN SELECT address FROM employees WHERE status = 'active';

EXPLAIN ANALYZE (MySQL 8.0+)

EXPLAIN ANALYZE SELECT address FROM employees WHERE status = 'active';

EXPLAIN ANALYZE sorguyu gerçekten yürütür ve tahmini yürütme planı ile birlikte gerçek zamanlama verilerini döndürür — zamanın gerçekten nerede harcandığını belirlemek için çok değerlidir.

Dikkat Edilmesi Gereken Uyarı İşaretleri

  • type: ALL — büyük bir tabloda tam tablo taraması
  • key: NULL — hiçbir indeks kullanılmıyor
  • Extra: Using filesort — MySQL sonuçları indeks kullanmak yerine diskte sıralanıyor
  • Extra: Using temporary — MySQL geçici bir tablo oluşturuyor, bu bellek ve CPU yoğundur

Bu uyarı işaretlerini gördüğünüzde, indeks eklemenin, sorguyu yeniden yazmanın veya şemanızı yeniden yapılandırmanın zamanı gelmiştir.

4. JOIN İşlemlerini Optimize Edin

JOINler ilişkisel veritabanları için gereklidir, ancak aynı zamanda performans sorunlarının yaygın bir kaynağıdır. İki büyük tablo arasında optimize edilmemiş bir JOIN, bir sunucuyu çökertebilir.

JOIN Optimizasyonu En İyi Uygulamalar

  • JOIN koşullarında kullanılan sütunları her zaman indeksleyin — bu, en önemli JOIN optimizasyonudur
  • Yalnızca eşleşen satırlara ihtiyacınız olduğunda INNER JOIN kullanın — NULL dolgulu sonuçlara ihtiyacınız olmadığında LEFT JOIN daha verimlidir
  • WHERE cümleleriyle erken filtreleyin — birleştirmeye dahil olan satır sayısını mümkün olduğunca erken azaltın
  • Birleştirme sırasına dikkat edin — MySQL’in sorgu optimize edicisi genellikle bunu yönetir, ancak karmaşık sorgularda, daha küçük sonuç kümelerini önce birleştirmek performansı iyileştirebilir

Optimize Edilmiş JOIN Örneği

SELECT c.name, o.order_date, o.total_amount
FROM customers c
INNER JOIN orders o ON c.id = o.customer_id
WHERE c.country = 'Germany'
  AND o.status = 'completed'
ORDER BY o.order_date DESC
LIMIT 50;

Bu örnekte:

  • Hem c.id hem de o.customer_id indekslenmelidir (yabancı anahtar ilişkileri InnoDB’de bunu otomatik olarak işler)
  • c.country ve o.status indekslerden yararlanır
  • LIMIT 50 sınırsız sonuç kümelerini önler

Örtülü JOINlerden Kaçının

Eski stil virgülle ayrılmış birleştirmeler okunması ve optimize edilmesi daha zordur:

-- Avoid this
SELECT * FROM customers, orders WHERE customers.id = orders.customer_id;

-- Prefer this
SELECT * FROM customers INNER JOIN orders ON customers.id = orders.customer_id;

5. İşlenen Veri Hacmini Minimize Edin

Bireysel sorgu optimizasyonunun ötesinde, MySQL’in herhangi bir zamanda işlemesi gereken veri miktarını azaltmak yüksek etkili bir stratejidir.

Pratik Teknikler

  • WHERE filtrelerini agresif bir şekilde kullanın — filtrelediğiniz her satır, MySQL’in işlemesi, sıralaması veya döndürmesi gereken bir satır değildir
  • İlişkili alt sorguları önleyin — bunlar dış sorgudaki her satır için bir kez yürütülür ve korkunç derecede yavaş olabilir; mümkün olduğunda bunları JOIN’ler olarak yeniden yazın
  • Uygulama düzeyinde önbelleğe alma uygulayın — Redis veya Memcached gibi araçlar, veritabanına hiç ulaşmadan sık erişilen verileri sunabilir
  • Büyük tabloları bölümlendirin — MySQL’in tablo bölümlendirme özelliği, sorguların tüm tablo yerine yalnızca ilgili bölümü taramasına izin verir
  • Eski verileri arşivleyin — geçmiş kayıtları arşiv tablolarına taşımak, etkin tablolarınızı yalın ve hızlı tutar

İlişkili Alt Sorgu (Önleyin)

SELECT name FROM employees e
WHERE salary > (SELECT AVG(salary) FROM employees WHERE department_id = e.department_id);

JOIN Olarak Yeniden Yazılmış (Tercih Edilen)

SELECT e.name
FROM employees e
INNER JOIN (
    SELECT department_id, AVG(salary) AS avg_salary
    FROM employees
    GROUP BY department_id
) dept_avg ON e.department_id = dept_avg.department_id
WHERE e.salary > dept_avg.avg_salary;

JOIN sürümü, departman ortalamalarını her çalışan satırı için bir kez yerine bir kez hesaplar.

6. MySQL Server Yapılandırmasını İnce Ayarla

Sorgu düzeyinde optimizasyon denklemin yalnızca yarısıdır. MySQL’in sunucu yapılandırma parametreleri performans üzerinde derin bir etkiye sahiptir ve varsayılan ayarlar kasıtlı olarak muhafazakardır — minimal donanımda çalışmak için tasarlanmıştır, verimlilik maksimize etmek için değil.

Kritik Yapılandırma Parametreleri

innodb_buffer_pool_size

Bu, en önemli InnoDB yapılandırma parametresidir. MySQL’in bellekte veri ve dizinleri önbelleğe almak için ne kadar RAM kullandığını kontrol eder. Bellekten okumalar diskten okumalardan büyüklük sırasında daha hızlıdır.

Öneri: Bunu adanmış bir veritabanı sunucusunda toplam kullanılabilir RAM’in %50–70’i olarak ayarlayın.

innodb_buffer_pool_size = 4G  # For an 8GB RAM server

innodb_log_file_size

Daha büyük günlük dosyaları, diske yazılmadan önce daha fazla işlemin toplu olarak işlenmesine izin vererek yazma performansını iyileştirir.

innodb_log_file_size = 512M

query_cache_size (MySQL 5.x)

Not: Sorgu önbelleği ölçeklenebilirlik sorunları nedeniyle MySQL 8.0’da kaldırılmıştır. MySQL 5.7’deyseniz, bunu dikkatli kullanın — okuma yoğun iş yükleri için yardımcı olabilir ancak yüksek yazma yükleri altında bir darboğaz haline gelir.

max_connections

Bunu uygulamanızın bağlantı havuzu yapılandırmasına göre ayarlayın. Çok yüksek olursa bellek tükenmesi riski; çok düşük olursa “çok fazla bağlantı” hataları göreceksiniz.

max_connections = 200

slow_query_log

Belirtilen yürütme süresi eşiğini aşan sorguları otomatik olarak günlüğe kaydetmek için bunu etkinleştirin — üretimde optimizasyon hedeflerini belirlemek için gerekli bir araç.

slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1  # Log queries taking longer than 1 second

Bu Ayarların Uygulanacağı Yer

Bu parametreler MySQL yapılandırma dosyasında yapılandırılır, genellikle /etc/mysql/my.cnf veya /etc/my.cnf konumunda bulunur. Değişiklik yaptıktan sonra MySQL hizmetini yeniden başlatın:

sudo systemctl restart mysql

Kendi sunucu ortamınızı yönetiyorsanız, Adanmış Sunucu ile elde ettiğiniz tam kök erişimi, bu sistem düzeyindeki yapılandırmalar üzerinde tam kontrol sağlar.

7. Ek Gelişmiş Optimizasyon Teknikleri

Hazırlanmış İfadeleri Kullanın

Hazırlanmış ifadeler, MySQL’in bir sorguyu bir kez ayrıştırmasına ve derlemesine izin verir, ardından farklı parametrelerle birden çok kez yürütür. Bu, ayrıştırma yükünü azaltır ve ayrıca SQL enjeksiyonundan korur.

PREPARE stmt FROM 'SELECT name, email FROM users WHERE id = ?';
SET @id = 42;
EXECUTE stmt USING @id;

Şemanızı Normalleştirin — Ancak Ne Zaman Denormalleştireceğinizi Bilin

Veritabanı normalleştirmesi fazlalığı ortadan kaldırır ve veri bütünlüğünü sağlar. Ancak, yüksek oranda normalleştirilmiş şemalar, yaygın sorgular için karmaşık çok tablolu JOIN’ler gerektirebilir. Okuma ağırlıklı uygulamalarda, stratejik denormalleştirme — pahalı JOIN’lerden kaçınmak için fazlalık veri depolama — geçerli bir performans değiş tokuşu olabilir.

COUNT(1) veya COUNT(column) Yerine COUNT(*) Kullanın

Modern MySQL, InnoDB için COUNT(*) verimli bir şekilde optimize etse de, COUNT(1) kullanmak veya belirli bir dizinlenmiş sütunu saymak bazı senaryolarda marjinal olarak daha hızlı olabilir ve niyeti daha açık bir şekilde iletir.

Performance Schema ile İzleyin

MySQL’in yerleşik Performance Schema, sorgu yürütme, bekleme olayları ve kaynak tüketimi hakkında ayrıntılı görünürlük sağlar — yalnızca yavaş sorgu günlüğünden çok daha ayrıntılı.

SELECT * FROM performance_schema.events_statements_summary_by_digest
ORDER BY sum_timer_wait DESC
LIMIT 10;

MySQL Performansı için Doğru Hosting Ortamını Seçmek

Optimizasyon çabalarınız, altında yatan altyapı kadar etkilidir. Ağır yüklü bir MySQL veritabanını yetersiz paylaşımlı hosting üzerinde çalıştırmak, bir yarış arabası motorunu ayarlamak ve ardından düz lastikleri olan bir araca koymak gibidir.

Farklı hosting ortamlarının MySQL performansını nasıl etkilediği aşağıda verilmiştir:

  • Paylaşımlı Web Hosting — Küçük web siteleri ve düşük trafikli uygulamalar için uygun. MySQL kaynakları diğer kullanıcılarla paylaşılır ve sunucu düzeyinde yapılandırabileceğiniz ve optimize edebileceğiniz şeyleri sınırlar.
  • VPS Hosting — Büyüyen uygulamalar için ideal seçim. Adanmış kaynaklar, MySQL yapılandırmasını ayarlamak için root erişimi ve özel MySQL sürümleri ile eklentileri yükleme yeteneği elde edersiniz. Grafik yönetim arayüzünü tercih eden takımlar için, cPanel ile VPS veritabanı yönetimini önemli ölçüde daha erişilebilir hale getirir.
  • Dedicated Servers — Yüksek trafikli uygulamalar ve büyük veritabanları için, adanmış bir sunucu tüm donanım kaynaklarına özel erişim, maksimum I/O verimliği ve MySQL’i her düzeyde optimize etme özgürlüğü sağlar.

Doğru altyapı katmanını seçmek, sorgularınız ne kadar iyi yazılırsa yazılsın, MySQL performansınızın tavanını belirleyen temel bir karardır.

MySQL Sorgu Optimizasyonu Kontrol Listesi

Veritabanı performansınızı denetlerken bu kontrol listesini hızlı bir referans olarak kullanın:

  • [ ] Sık sorgulanan sütunlar dizinlenmiş mi?
  • [ ] Çok sütunlu filtreler için bileşik dizinler kullanılıyor mu?
  • [ ] SELECT * ifadeleri belirli sütun listeleriyle değiştirilmiş mi?
  • [ ] Sonuç kümeleri LIMIT ile sayfalandırılmış mı?
  • [ ] Yavaş sorgular yavaş sorgu günlüğü ile tanımlanmış mı?
  • [ ] Tüm kritik sorgularda EXPLAIN çalıştırılmış mı?
  • [ ] JOIN sütunları dizinlenmiş mi?
  • [ ] innodb_buffer_pool_size kullanılabilir RAM’in %50–70’ine ayarlanmış mı?
  • [ ] Yavaş sorgu günlüğü üretimde etkinleştirilmiş mi?
  • [ ] İlişkili alt sorgular mümkün olduğunda JOIN’ler olarak yeniden yazılmış mı?

Sonuç

MySQL sorgu optimizasyonu tek bir çözüm değildir — uygulamanız ve verilerinizle birlikte gelişen sürekli bir mühendislik disiplinidir. Bu kılavuzda ele alınan teknikler — stratejik indeksleme, seçici SELECT ifadeleri, EXPLAIN-odaklı sorgu analizi, verimli JOIN desenleri, veri hacmi azaltma ve sunucu düzeyinde ayarlama — yüksek performanslı veritabanı ortamları oluşturmak ve sürdürmek için kapsamlı bir çerçeve oluşturur.

Bu optimizasyonların kümülatif etkisi önemlidir: daha hızlı sayfa yüklemeleri, daha duyarlı uygulamalar, daha düşük altyapı maliyetleri ve platformunuzla etkileşime giren her kullanıcı için daha iyi bir deneyim.

Paylaşımlı Web Barındırma ile yeni başlıyor olsanız da ya da Özel Sunucu üzerinde görev açısından kritik bir uygulamayı ölçeklendiriyor olsanız da, MySQL optimizasyonuna zaman yatırmak, herhangi bir geliştirici veya sistem yöneticisinin yapabileceği en yüksek ROI etkinliklerinden biridir. Yavaş sorgu günlüğüyle başlayın, EXPLAIN çıktısını gözden geçirin ve baştan itibaren verimli SQL yazma alışkanlığını geliştirin — kullanıcılarınız, sunucunuz ve altyapı faturanız hepsi bunu takdir edecektir.