MySQL Query Cache Nedir? Performansa Etkisi ve Doğru Kullanım
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; sadeceSQL_CACHEile).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_blocksveQcache_total_blocksanormalseFLUSH QUERY CACHEveya yeniden boyutlandırma gerekebilir. - Sık invalidation: Güncelleme yoğun tablolarda QC verimsizdir; bu tabloların sorgularını
SQL_NO_CACHEile 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/OFFSETyerine 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.