MySQL Query Cache Nedir? Performansa Etkisi ve Doğru Kullanım

MySQL Query Cache Nedir? Performansa Etkisi ve Doğru Kullanım
Yazı Özetini Göster

MySQL Query Cache Nedir? Performansa Etkisi ve Doğru Kullanım

Query Cache (QC), MySQL 5.6/5.7 sürümlerinde SELECT sorgularının sonuç setlerini bellekten tekrar sunarak okuma odaklı iş yüklerinde gecikmeyi azaltmayı amaçlayan bir özelliktir. Aynı metinle (byte-by-byte eşleşen) gelen sorgular ve aynı oturum parametreleri için (ör. SQL_SMALL_RESULT vb.) sonuç seti diske gitmeden hızlıca döner. Ancak tabloya yapılan her INSERT/UPDATE/DELETE işlemi, ilgili tablonun QC’deki tüm girdilerini geçersiz kılar; bu da yazma trafiği yüksek sistemlerde QC’nin kilitlenme ve parçalanma nedeniyle yarardan çok zarar vermesine yol açabilir. Not: Query Cache, MySQL 8.0’da tamamen kaldırılmıştır.

Ne Zaman İşe Yarar, Ne Zaman Zarar Verir?

  • İşe yarar: Okuma ağırlıklı, nadiren güncellenen tablolar; aynı SELECT ifadelerinin sık tekrarlandığı (örn. ana sayfa listeleri).
  • Yarar sağlamaz / zarar verir: Yazma oranı yüksek OLTP sistemleri; çok sayıda farklı, parametrik veya dinamik sorgu metni; büyük sonuç setleri.

Temel Değişkenler ve Durum Metrikleri

SHOW VARIABLES LIKE 'query_cache%';
SHOW STATUS    LIKE 'Qcache%';
  • query_cache_size: Ayrılan bellek (MB). Aşırı büyük değerlerde parça yönetimi ve global mutex maliyeti artar.
  • query_cache_type: 0 (kapalı), 1 (açık), 2 (demand; sadece SQL_CACHE ile).
  • query_cache_limit: Tek sorgu için en fazla cache’lenecek sonuç boyutu.
  • Qcache_hits: Önbellekten karşılanan istek sayısı.
  • Qcache_lowmem_prunes: Bellek yetersizliğinden atılan girdiler; yüksekse boyut küçük veya parçalanma vardır.

Basit Hit Oranı Hesabı

-- Yaklaşık hit oranı
SELECT
  @@global.version                           AS version,
  (SUM(IF(variable_name='Qcache_hits', variable_value, 0))) /
  NULLIF(
    (SUM(IF(variable_name='Qcache_hits', variable_value, 0)) +
     SUM(IF(variable_name='Com_select',  variable_value, 0))), 0
  ) AS approx_qc_hit_ratio
FROM performance_schema.global_status
WHERE variable_name IN ('Qcache_hits','Com_select');

Genel kural: Hit oranı düşük (<%20) ve Qcache_lowmem_prunes yüksekse ya boyutu/tipini ayarlayın ya da QC’yi kapatın.

Önerilen Konfigürasyon (MySQL 5.6/5.7)

-- my.cnf / my.ini (örnek başlangıç değerleri)
query_cache_type  = 2        # demand: sadece SQL_CACHE işaretlileri cache'lenir
query_cache_size  = 64M      # çoğu senaryo için 32–128M aralığında tutun
query_cache_limit = 2M       # büyük setler cache’i şişirmesin

Sunucuyu yeniden başlatın veya aşağıdaki gibi dinamik değiştirin:

SET GLOBAL query_cache_type  = 2;
SET GLOBAL query_cache_size  = 64*1024*1024;
SET GLOBAL query_cache_limit = 2*1024*1024;

Uygulama Tarafında Kullanım

-- Sadece belirlediğiniz sorguları cache'lemek için
SELECT SQL_CACHE  col1, col2 FROM products WHERE category_id=10 ORDER BY created_at DESC LIMIT 20;

-- Cache dışı bırakmak için
SELECT SQL_NO_CACHE * FROM large_reporting_view WHERE date=CURDATE();

İpucu: Parametrik sorguların metni farklılaştığında QC işe yaramaz. Aynı metin ve aynı sıralama/limit ile tekrarlanan sorgularda değeri artar.

Yaygın Sorunlar ve Teşhis

  • Global mutex beklemesi: Yüksek eşzamanlılıkta QC kilidi tıkanır; slow log ve performance_schema ile bekleme analiz edin.
  • Parçalanma: Qcache_free_blocks ve Qcache_total_blocks anormalse FLUSH QUERY CACHE veya yeniden boyutlandırma gerekebilir.
  • Sık invalidation: Güncelleme yoğun tablolarda QC verimsizdir; bu tabloların sorgularını SQL_NO_CACHE ile işaretleyin.

MySQL 8.0 ve Alternatifler

  • Query Cache kaldırıldı: 8.0’da QC yoktur. Önerilen yaklaşım: InnoDB Buffer Pool boyutunu artırmak (genellikle RAM’in %60–70’i).
  • Uygulama/katman önbelleği: Redis/Memcached ile sık kullanılan SELECT sonuçlarını TTL’li tutun.
  • HTTP katmanı: Statik sayfalar için CDN/Varnish; API/uygulama için reverse proxy cache.
  • İndeks ve sorgu optimizasyonu: Kapsayıcı indeksler (covering), uygun EXPLAIN, LIMIT/OFFSET yerine seek-based sayfalama.

Karar Matrisi (Özet)

  • 5.6/5.7, okuma ağır, veri nadiren değişiyor: QC = demand (type=2), 32–128MB deneyin, sadece seçili sorguları cache’leyin.
  • Yazma ağır / yüksek eşzamanlılık: QC kapalı tutun (query_cache_type=0).
  • 8.0 ve sonrası: QC yok; Buffer Pool + uygulama/HTTP cache kullanın.

Sonuç

MySQL Query Cache, doğru senaryoda gecikmeyi azaltabilir; yanlış senaryoda ise global kilit ve invalidation nedeniyle performansı düşürür. 5.6/5.7’de demand modunda, seçici ve küçük boyutlarla kullanın; 8.0’da ise katmanlı önbellek ve indeks optimizasyonuna odaklanın.

Bir Yorum Yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Benzer Yazılar