Yavaş WordPress Sorgularını Bulma ve Hızlandırma

Yavaş WordPress sorguları TTFB'nizi şişiriyor. EXPLAIN ile darboğazı bulun, doğru index'i ekleyin ve veritabanı süresini 200 ms altına indirin.
İçindekiler
Makale başlıklarına göz atarak istediğiniz içeriğe kolaylıkla ulaşın.

Önemli Noktalar

  • EXPLAIN komutu, MySQL sorgularının nasıl çalıştığını analiz ederek tam tablo taraması (type: ALL) gibi performans sorunlarını tespit etmeyi sağlar.
  • wp_postmeta tablosuna meta_key ve meta_value sütunlarını kapsayan bileşik bir index eklemek, sorguların taranan satır sayısını yüz binlerden binlere düşürür.
  • WooCommerce ürün verilerini süzmek için wp_postmeta yerine, veritabanı performansını artıran wc_product_meta_lookup tablosu kullanılır.
  • SAVEQUERIES özelliği, WordPress sorgularını süre ve çağıran fonksiyon bilgisiyle kaydederek veritabanı darboğazlarını görünür kılar.
  • Redis veya Memcached gibi nesne önbelleği çözümleri, tekrarlayan sorguları MySQL yerine bellekten sunarak toplam veritabanı süresini optimize eder.

Siteniz 4 saniyede yükleniyor. Her şeyi önbelleğe aldınız. Görseller optimize.

Darboğaz hâlâ veritabanı.

Yavaş SQL Sorguları Neden WordPress’in Gizli Darboğazıdır?

WordPress her sayfa yüklemesinde onlarca SQL sorgusu çalıştırır. Çoğu 1 ms altında biter. Ama wp_postmeta üzerindeki tek bir 800 ms’lik JOIN tüm sayfayı bozuk hissettirir.

Tekrarlayan senaryo: PageSpeed 95 der, kullanıcı “yavaş” der. Ön yüz hızlıdır. Sunucu, HTML göndermeye başlamadan önce 2+ saniye harcar.

En kötüsü şu: WordPress yavaş sorguları varsayılan olarak kaydetmez. Uyarı yok, panel bildirimi yok. Yavaş WordPress sorguları veritabanı büyüdükçe sessizce kötüleşir; siz ancak kullanıcı şikayet edince fark edersiniz.

Yavaş WordPress Sorgularının Nedenleri

1. WooCommerce Postmeta JOIN’leri

WooCommerce ürün verisini wp_postmeta içinde anahtar-değer olarak tutar. Ürünleri fiyat, stok veya niteliğe göre süzmek, index’siz bir tabloda çoklu JOIN gerektirir.

SELECT p.ID FROM wp_posts p
INNER JOIN wp_postmeta pm1 ON p.ID = pm1.post_id
INNER JOIN wp_postmeta pm2 ON p.ID = pm2.post_id
WHERE pm1.meta_key = '_price' AND pm1.meta_value BETWEEN 10 AND 50
AND pm2.meta_key = '_stock_status' AND pm2.meta_value = 'instock'

10.000 ürün ve 500.000 postmeta satırıyla bu sorgu, doğru index olmadan 2–5 saniye sürebilir.

2. Index’siz meta_key Aramaları

Varsayılan wp_postmeta tablosunda yalnızca post_id üzerinde index vardır. meta_key + meta_value ile süzen her sorgu tam tablo taraması yapar.

SELECT post_id FROM wp_postmeta
WHERE meta_key = '_thumbnail_id'
-- 500K+ satırda tam tablo taraması

3. Büyük Metin Sütunlarında LIKE Sorguları

Arama eklentileri ve admin aramaları sıkça post_content üzerinde LIKE '%terim%' çalıştırır. Bu, her index’i atlar ve sütunun tamamını tarar.

SELECT ID FROM wp_posts
WHERE post_content LIKE '%kargo politikası%'
-- Her satırı, her seferinde tarar

4. Karmaşık WHERE’li COUNT Sorguları

Admin liste tabloları, sayfalama için COUNT sorguları çalıştırır. Taksonomi süzgeçleri ve meta sorgularıyla birleşince, büyük sitelerde bunlar şaşırtıcı derecede pahalıdır.

WordPress’te Yavaş Sorgular Nasıl Bulunur?

  1. SAVEQUERIES’i etkinleştirin. wp-config.php‘ye define('SAVEQUERIES', true); ekleyin. WordPress her sorguyu süre ve çağıran fonksiyonla kaydeder. Sayfa sonrası $wpdb->queries‘e bakın.
  2. MySQL yavaş sorgu kaydını açın. Sunucu erişiminiz varsa SET GLOBAL slow_query_log = 'ON'; ve SET GLOBAL long_query_time = 0.5; ile 500 ms üstü sorguları yakalayın.
  3. Şüpheli sorgularda EXPLAIN kullanın. Yavaş sorgunun başına EXPLAIN ekleyin. type: ALL (tam tarama) ve yüz binlerce rows: değerine dikkat edin.
  4. Belirli bir sayfayı profilleyin. Query Monitor kullanın veya geçici olarak SAVEQUERIES ekleyin. Süreye göre sıralayın. İlk 3 sorgu genelde TTFB‘nin %80’ini oluşturur.
  5. Yoğun trafikte test edin. 10 kullanıcıda “sorunsuz” bir sorgu 100 kullanıcıda felakete döner. Sadece geliştirme ortamında değil, yük altında test edin.

Gerçek Bir WordPress Sorgusunda EXPLAIN Planı Okuma

EXPLAIN, MySQL’in hata ayıklayıcıya en yakın aracıdır. Bir SELECT’in başına eklersiniz ve MySQL nasıl çalıştıracağını söyler. Hangi tabloyu tarar, hangi index’i kullanır, kaç satıra dokunur.

İşte yukarıdaki WooCommerce süzme sorgusu, gerçek bir mağaza sayfasının çalıştırdığı gibi ORDER BY eklenmiş hali:

EXPLAIN SELECT p.ID FROM wp_posts p
INNER JOIN wp_postmeta pm1 ON p.ID = pm1.post_id
INNER JOIN wp_postmeta pm2 ON p.ID = pm2.post_id
WHERE pm1.meta_key = '_price' AND pm1.meta_value BETWEEN 10 AND 50
  AND pm2.meta_key = '_stock_status' AND pm2.meta_value = 'instock'
ORDER BY p.post_date DESC LIMIT 20;

~800 bin postmeta satırlı bir mağazada plan şöyle döner:

idselect_typetabletypekeyrowsExtra
1SIMPLEpm1ALLNULL812441Using where; Using temporary; Using filesort
1SIMPLEpeq_refPRIMARY1Using where
1SIMPLEpm2refpost_id4Using where

İlk satır sorunun tamamıdır. Nasıl okunacağı şöyle:

  • type: ALL — tam tablo taraması. MySQL her satırı okur ve WHERE’i tek tek kontrol eder. 812 bin satırda, her sayfa yüklemesinde. EXPLAIN’in gösterebileceği en kötü erişim türüdür.
  • key: NULL — hiçbir index kullanılmadı. Index var ama MySQL reddetti. Çünkü ‘_price’ tablonun büyük kısmıyla eşleşir; optimize edici taramayı daha ucuz buldu. Index eksik değil, bu sorgu için işe yaramaz.
  • Using temporary — MySQL sıralamadan önce ara sonuçları tutmak için geçici tablo kurar. Büyük sonuçlarda bu tablo diske taşar ve süre milisaniyeden saniyeye çıkar.
  • Using filesort — ORDER BY hiçbir index ile karşılanamaz. 812 bin taranmış satırla birleşince her istekte devasa bir yığın sıralanır.

Çözüm, optimize edicinin gerçekten isteyeceği bir index’tir. meta_key ve meta_value‘yu birlikte süzen bir index, ‘_price’ + değer aralığını yarım tablo yerine birkaç bine indirir.

ALTER TABLE wp_postmeta
ADD INDEX wpmt_key_value (meta_key(191), meta_value(32));

EXPLAIN’i tekrar çalıştırın; ilk satır tamamen değişir:

idtabletypekeyrowsExtra
1pm1rangewpmt_key_value2874Using where
1peq_refPRIMARY1Using where
1pm2refwpmt_key_value2Using where

type: range, MySQL’in yalnızca iki fiyat sınırı arasındaki index kayıtlarını gezdiği anlamına gelir. 812.441 yerine 2.874 satır. Sıralamaya dokunmadan önce 280 kat daha az iş.

Beceri budur: EXPLAIN çalıştır, her tablo için type, key ve rows‘a bak, en çok iş yapan satırı düzelt.

WordPress Sorgu Performansı Kıyasları

Her yavaş sorgu eşit değildir. Hedefleyeceğiniz eşikler şunlardır:

  • <50 ms — sorgu başına (sağlıklı)
  • <30 — sayfa başına sorgu sayısı
  • <200 ms — toplam veritabanı süresi

Tek bir sorgu 100 ms’yi aşıyorsa incelemeye değer. Toplam veritabanı süresi 500 ms’yi geçerse, sayfa önbelleğiniz olsa bile kullanıcı bunu hisseder.

Yavaş WordPress Sorgularını Hızlandırma (Pratik Çözümler)

Yavaş sorguyu bulmak işin yarısıdır. Bir kural: belirtiyi değil, sorguyu optimize edin. Körlemesine index eklemeyin; sorgunun neden yavaş olduğunu anlayın.

1. EXPLAIN Planının İstediği Index’leri Ekleyin

İlk eklediğim index, yukarıdaki EXPLAIN’in işaret ettiğidir. Meta sorgularının süzdüğü iki sütunu birlikte kapsayan bileşik bir index.

ALTER TABLE wp_postmeta
ADD INDEX wpmt_key_value (meta_key(191), meta_value(32));

İki koşulu tek index gezişinde daraltır. Yukarıda type: ALL’ı type: range’e çevirdi ve taranan satırı 812.441’den 2.874’e indirdi. Önek uzunlukları index’i kompakt tutar. İnançla index eklemeyin: önce EXPLAIN, sonra eksik olanı ekleyin.

2. WooCommerce Ürün ve Sipariş Sorgularını Hızlandırın

Her meta_query koşulu, 4 sütunlu bir EAV tablosuna JOIN ekler. Yapabildiğinizde postmeta üzerinden süzmeyi bırakın. Sürekli süzdüğünüz fiyat, stok, puan gibi alanları uygun sütun ve index’li bir arama tablosuna kopyalayın.

WooCommerce tam bu yüzden wc_product_meta_lookup tablosunu sunar; onu kullanın ya da kendi alanlarınız için aynı deseni kurun.

3. LIKE ‘%terim%’ ve Sınırsız WP_Query Çağrılarını Durdurun

Baştaki joker karakter hiçbir B-tree index’ini kullanamaz; MySQL her zaman her satırı tarar. post_content‘e FULLTEXT index ekleyip MATCH() AGAINST() ile sorgulayın veya aramayı özel bir arama motoruna taşıyın.

posts_per_page => -1 ile asla sorgu yapmayın. Sınırsız sorgular 200 yazıyla iyi çalışır, 20.000’de çöker. Gerçek bir limit koyup sayfalayın.

meta_query OR yığınlarından kaçının. Birden çok meta anahtarı üzerinde iç içe OR, MySQL’i geniş taramalara ve geçici tablolara zorlar. Tek hedefli bir sorgu veya PHP’de birleştirdiğiniz iki ucuz sorgu tercih edin.

4. Toplamları Önbellekleyin ve N+1 Meta Döngülerini Kesin

Nesne önbelleğiyle başlayın. Redis veya Memcached sorgu sonuçlarını bellekte tutar; tekrar eden sorgular MySQL yerine önbelleğe gider. Çoğu site için en yüksek etkili değişiklik budur.

Pahalı toplamları kendiniz önbellekleyin. Karmaşık WHERE’li COUNT() veya “bu ayki yazılar” widget’ları her istekte taze olmak zorunda değildir. Bir kez hesaplayın, transient’te saklayın, zamanlamayla yenileyin.

WP_Query’nin çektiğini kısın. Sadece ID gerekiyorsa 'fields' => 'ids' deyin. Sayfalamıyorsanız 'no_found_rows' => true kullanın. Meta okumayacaksanız cache hazırlığını kapatın; ama döngüde meta okuyacaksanız açık bırakın.

Son olarak WordPress’in her şeyden önce çalıştırdığı sorguyu kesin. Her istek, ilk sorgunuz bile ateşlenmeden tüm autoload seçeneklerini yükler. Autoload şişkinliğini düzeltmek her sayfayı hızlandırır.

5. “Daha Hızlı” Neye Benzer? (Her Çözümden Sonra Kıyas)

Tek seferde tek çözüm uygulayın ve her birinden sonra yeniden ölçün: EXPLAIN artı bir süre kontrolü. Hedefler yukarıdaki kıyaslardır; sorgu başına 50 ms altı, sayfa başına toplam 200 ms altı.

EXPLAIN’de tek bir bileşik index taranan satırı 812.441’den 2.874’e indirdi. Doğru bir index’in değişim ölçeği budur. Bir çözüm planı veya süreyi değiştirmiyorsa geri alın ve sıradakine geçin.

Yavaş Sorgu Kaydı, Query Monitor ve Otomatik Tespit

Yavaş sorgu yakalamanın üç yolu vardır. Her biri farklı bir soruya cevap verir:

YaklaşımSunucu erişimiSürekli çalışırÇağrı yığınıÜretim güvenli
Manuel (SAVEQUERIES / MySQL yavaş kayıt)EvetKayıt tutar ama kimse okumazHayır — SQL’i verir, PHP’yi değilSAVEQUERIES hayır; MySQL kaydı evet (makul eşikle)
Query Monitor eklentisiHayırHayır — sadece o an baktığınız sayfaEvet — tam çağrı yığını, en iyi özelliğiGeliştirme için; 3’teki ani yükü yakalamaz
Sürekli izlemeHayırEvet — gerçek trafikte 7/24Evet — çağıran dosyaEvet — canlı sitelerde düşük yükle

Query Monitor yaptığı işte gerçekten iyidir; ben de kullanıyorum. Ama farklı bir soruya cevap verir. Siz bakarken bu sayfanın ne yaptığını söyler; sitenizin geçen salı yük altında ne yaptığını söyleyemez.

Yavaş Sorgular Neden Geri Gelir?

Yavaş sorguları bir kez bulmak yetmez. Geri gelirler:

  1. Eklenti güncellemeleri yeni sorgular getirir veya mevcutları değiştirir
  2. Veritabanınız büyür — 10K satırda hızlı sorgu, 500K’da yavaşlar
  3. Yeni içerik türleri postmeta ve taksonomi satırı ekler
  4. WooCommerce satışları aynı tablolarda sipariş verisi biriktirir

Manuel SAVEQUERIES kontrolleri yorucu ve unutması kolaydır. Yavaş sorgular aynı zamanda yönetici panelinizi de yavaşlatıyorsa, sorun katlanır. Kullanıcı şikayet etmeden regresyonu yakalayan sürekli izlemeye ihtiyacınız var.

Yavaş WordPress Sorguları SSS

Üç yol: MySQL yavaş sorgu kaydını ~0,5 sn eşikle açın (sunucu erişimi gerekir), Query Monitor kurup giriş yaparken sayfaları inceleyin ya da gerçek trafikte sürekli kaydeden bir çözüm kullanın. İlk ikisi sadece sizin tetiklediklerinizi yakalar; ziyaretçinizin yaşadığını yalnızca sürekli izleme yakalar.
Yeniden yazmaya gerek yok; çoğu çözüm hedeflidir. Önce EXPLAIN çalıştırın: MySQL tüm tabloyu mu tarıyor (type: ALL, key: NULL) görürsünüz. Çoğu yavaş sorgu, wp_postmeta üzerinde meta_key + meta_value kapsayan doğru bileşik index ile düzelir.
Tekil sorgular 50 ms altında kalmalı; iyi index’lenmiş çoğu sorgu 5 ms altında çalışır. Tipik bir sayfa 30’dan az sorgu ve toplam 200 ms altı veritabanı süresi ister. Tek bir sorgu 500 ms’yi geçerse EXPLAIN’e değer.
Hayır, gizler. Önbellekli ziyaretçi hızlı HTML alır; ama her cache miss, giriş yapmış kullanıcı, sepet ve admin isteği tam sorgu maliyetini öder. Trafik yükseldiğinde veya önbellek temizlendiğinde yavaş sorgu geri gelir.

Hiçbir güncellemeyi kaçırma!

bw/a web sitesini Tercih Edilen Kaynak olarak Google'a ekleyin
ve arama sonuçlarında daha fazla görün.

⭐ Tercih Edilen Kaynak Olarak Ekle

Yazar Hakkında

Tolga Altaş fotoğrafı
‎Dijital Pazarlama Uzmanı · ‎bw/a (better with agency) · 11 yıl deneyim

Tolga Altaş, Samsun merkezli dijital pazarlama ajansı bw/a (better with agency) bünyesinde Dijital Pazarlama Uzmanı olarak görev yapıyor. Yerel işletmeler için SEO, Google Ads, sosyal medya yönetimi ve web tasarımı alanlarında uçtan uca dijital pazarlama stratejileri geliştiriyor. Veri odaklı yaklaşımıyla markaların organik görünürlüğünü ve dönüşüm oranlarını artırmaya odaklanıyor.

Dijital PazarlamaSEOGoogle AdsSosyal Medya Yönetimiİçerik PazarlamasıWeb TasarımıYerel SEO