Site iki yıl önce kurulduğunda uçuyordu. Şimdi hiçbir şey değişmemiş gibi görünüyor: trafik aynı, tema aynı, paket aynı. Ama yönetici paneline girmek 3 saniye sürüyor, yazı listesi geç açılıyor, ön yüzde en boş sayfa bile ağır. Bir önbellek eklentisi kurdunuz, GTmetrix skoru düzeldi ama panel hâlâ hantal. Hosting desteğine yazdınız, "kaynak kullanımınız normal" cevabı geldi.
Buradaki en önemli ipucu genellikle gözden kaçar: yavaşlık sayfaya göre değişmiyor. Ağır bir ürün listesi ile üç satırlık bir "İletişim" sayfası neredeyse aynı sürede açılıyorsa, sorun o sayfanın içeriğinde değildir. WordPress'in her istekte, sayfa ne olursa olsun yaptığı bir işte gizlidir. Bu işlerin en pahalısı ve en sessiz olanı, wp_options tablosundaki autoload verisidir.
Bu rehber tek bir soruna odaklanıyor: her sayfa açılışında belleğe yüklenen seçenek verisinin şişmesi. Önce mekanizmayı, sonra ölçümü (rakam olmadan müdahale etmeyeceğiz), sonra ölçtüğünüz kaydın hangi eklentiye ait olduğunu nasıl bulacağınızı, ardından güvenli temizlik sırasını ve en sonunda "işe yaradı mı" sorusunun cevabını aynı sorguyla nasıl kanıtlayacağınızı göreceğiz. Revizyon, spam yorum ve çöp temizliği gibi genel bakım adımları bu yazının konusu değil; onlar için WordPress veritabanı optimizasyon rehberimiz var.
Autoload Nedir ve Neden Her İsteği Etkiler?#
WordPress ayarlarını wp_options tablosunda tutar. Bu tablonun her satırında bir option_name, bir option_value ve bir de autoload sütunu vardır. Autoload sütunu tek bir soruyu cevaplar: "Bu kayıt, daha kimse istemeden, her sayfa açılışında belleğe yüklensin mi?"
Cevap "evet" ise WordPress önyükleme sırasında wp_load_alloptions() fonksiyonunu çalıştırır. Bu fonksiyon tek bir sorguyla autoload işaretli tüm satırları çeker, hepsini birden PHP dizisine unserialize eder ve alloptions adlı tek bir önbellek anahtarında tutar. Yani autoload verisi bir "sayfa maliyeti" değil, bir istek maliyetidir. Şu isteklerin hepsi bu bedeli öder:
| İstek türü | Autoload bedeli ödenir mi? | Not |
|---|---|---|
| Önbellekten dönen anonim sayfa | Hayır | PHP hiç çalışmaz |
| Önbelleğe girmeyen ön yüz isteği (sepet, ödeme, oturum açmış ziyaretçi) | Evet | Her istekte |
Yönetici paneli (wp-admin) her ekran | Evet | Panelin yavaşlamasının ana nedeni |
admin-ajax.php ve ?wc-ajax= çağrıları | Evet | Arka planda dakikada onlarca kez |
REST API (/wp-json/) istekleri | Evet | Blok editörü sürekli çağırır |
| WP-Cron tetiklemeleri | Evet | Her ziyaretçi bir cron tetikleyebilir |
Buradaki en önemli sonuç şu: önbellek eklentisi bu sorunu çözmez, saklar. Tam sayfa önbelleği anonim ziyaretçiyi kurtarır, ama panel, AJAX, REST ve oturumlu istekler önbellekten geçmez. Bu yüzden "önbellek kurdum, ziyaretçi tarafı hızlandı ama panel hâlâ ağır" tablosu, autoload şişmesinin klasik imzasıdır.
Object Cache Kurmak Kurtarmıyor, Bazen Kötüleştiriyor#
Yaygın bir yanlış inanış, Redis veya Memcached kurulunca autoload verisinin "bedava" hâle geldiğidir. Öyle değil. Harici bir object cache'te alloptions tek bir dev anahtar olarak durur; her istekte bu anahtar ağ soketi üzerinden çekilir ve PHP tarafında baştan unserialize edilir. 3 MB'lık bir autoload yükü, Redis'te de her istekte 3 MB taşınıp açılan bir yüktür.
Memcached'de durum daha da serttir: varsayılan maksimum öğe boyutu 1 MB'tır. alloptions dizisi bu sınırı aşarsa hiç yazılamaz, dolayısıyla her istekte önbellek ıskalar ve veritabanına geri dönülür. Yani object cache kurmak, eşiği aşan bir sitede hiçbir şey kazandırmaz. Object cache'in doğru kurulumu için Redis object cache rehberimize bakabilirsiniz; ama autoload temizliğini onun yerine geçecek bir çözüm olarak görmeyin.
WordPress 6.6 ile autoload Sütunu Değişti: Eski Sorgu Artık Eksik Ölçüyor#
İnternetteki hemen her rehber şu sorguyu verir:
SELECT SUM(LENGTH(option_value)) FROM wp_options WHERE autoload = 'yes';
WordPress 6.6'dan itibaren bu sorgu eksik sonuç döndürür. Options API'si yeniden yazıldı ve autoload sütunu artık sadece yes/no değil, beş değer alabiliyor:
| Değer | Anlamı | Yüklenir mi? |
|---|---|---|
on | Açıkça "autoload edilsin" denmiş | Evet |
off | Açıkça "edilmesin" denmiş | Hayır |
auto | Değer belirtilmemiş, çekirdeğin varsayılanı | Evet |
auto-on | Çekirdek boyuta bakıp "yüklensin" demiş | Evet |
auto-off | Çekirdek boyuta bakıp "yüklenmesin" demiş | Hayır |
yes / no | 6.6 öncesinden kalan eski kayıtlar | yes evet, no hayır |
Çekirdek bu kararı verirken bir boyut eşiği kullanır: varsayılan olarak 150.000 bayt (yaklaşık 146 KB). Bundan büyük bir seçenek, açıkça on denmediyse auto-off olarak yazılır. Eşik wp_max_autoloaded_option_size filtresiyle değiştirilebilir, ama yükseltmenin tek sonucu daha yavaş bir sitedir.
Gerçekten yüklenen değerlerin listesini çekirdek wp_autoload_values_to_autoload() fonksiyonuyla verir ve bu liste yes, on, auto-on, auto şeklindedir. Ölçüm sorgularınızın tamamı bu dört değeri kapsamalı. Aksi hâlde 6.6 sonrası kurulmuş bir sitede "autoload verim 40 KB" gibi sahte bir rahatlama yaşarsınız.
Sitenizin hangi dünyada olduğunu tek sorguyla görün:
SELECT autoload,
COUNT(*) AS kayit,
ROUND(SUM(LENGTH(option_value)) / 1024, 2) AS kb
FROM wp_options
GROUP BY autoload
ORDER BY kb DESC;
Sonuçta yalnız yes/no görüyorsanız site 6.6 öncesinden geliyor demektir; auto ve auto-off da varsa yeni davranış devrede.
Ölçüm 1: Autoload Verisinin Toplam Boyutu ve Eşik Değerleri#
Şimdi asıl rakam. phpMyAdmin'in SQL sekmesinde ya da wp db query ile çalıştırın:
SELECT ROUND(SUM(LENGTH(option_value)) / 1024, 2) AS autoload_kb,
COUNT(*) AS kayit_sayisi
FROM wp_options
WHERE autoload IN ('yes', 'on', 'auto', 'auto-on');
Tablo öneki her kurulumda wp_ olmayabilir; wp-config.php dosyasındaki $table_prefix değerine bakıp sorgudaki tablo adını ona göre düzeltin.
WP-CLI erişiminiz varsa aynı rakamı tek satırda alırsınız:
wp option list --autoload=on --format=total_bytes
Çıkan sayıyı şu ölçekle yorumlayın:
| Toplam autoload | Durum | Yapılacak |
|---|---|---|
| 300 KB altı | Sağlıklı | Bir şey yapmayın |
| 300 - 800 KB | İzlenmeli | En büyük 5 kayda göz atın |
| 800 KB - 1 MB | Sınırda | Temizliği planlayın |
| 1 - 3 MB | Sorunlu | Bu rehberi uygulayın |
| 3 MB üstü | Ağır | Öncelikli müdahale |
Kayıt sayısı da önemlidir. 1.500'ün üzerinde autoload satırı varsa, tek tek küçük olsalar bile her istekte 1.500 elemanlı bir dizinin kurulması ve gezilmesi başlı başına bir maliyettir.
Ölçüm 2: En Büyük Kayıtları Listeleme ve Sahibini Bulma#
Toplam rakam sorunu gösterir, ama çözüm tek tek satırlardadır. En ağır 20 kaydı çıkarın:
SELECT option_name,
ROUND(LENGTH(option_value) / 1024, 2) AS kb,
autoload
FROM wp_options
WHERE autoload IN ('yes', 'on', 'auto', 'auto-on')
ORDER BY LENGTH(option_value) DESC
LIMIT 20;
Çoğu sitede ilk 5 satır toplamın yüzde 70-90'ını oluşturur. Yani 40 kaydı tek tek incelemeniz gerekmez; birkaç dev satırı halletmek yeter.
Şimdi asıl beceri: kayıt adından sahibini okumak. WordPress'te seçenek isimlendirmesi bir sözleşmedir; eklentiler kendi ön eklerini kullanır.
| Kayıt adı deseni | Sahibi / anlamı | İlk değerlendirme |
|---|---|---|
rewrite_rules | Çekirdek, kalıcı bağlantı kuralları | Büyükse silin, kendini yeniden üretir |
_transient_... | Geçici önbellek kaydı | Süresi geçmişse silinir |
_site_transient_... | Çok siteli kurulumda geçici kayıt | Aynı |
wc_..., woocommerce_... | WooCommerce | Dikkatli olun, ayar olabilir |
elementor_... | Elementor | Genelde off yapılabilir |
wpseo_..., yoast_... | Yoast SEO | Ayar kayıtları, silmeyin |
updraft_... | UpdraftPlus yedek günlükleri | Genellikle şişer, off yapılabilir |
jetpack_... | Jetpack | Sık şişen gruplardan |
wpforms_..., cf7_... | Form eklentileri | Form gönderim izleri |
theme_mods_TEMAADI | Tema özelleştirici ayarları | Aktif temaninkini silmeyin |
Ön ek tanıdık gelmiyorsa aramayı sunucuda yapın. Kayıt adının bir eklenti dosyasında geçip geçmediğine bakmak, sahibini bulmanın en kesin yoludur:
cd ~/public_html/wp-content
grep -rn --include='*.php' "ornek_dev_kayit" plugins/ themes/ mu-plugins/ | head
Hiçbir sonuç çıkmıyorsa üç ihtimal vardır: kayıt adı kod içinde dinamik olarak üretiliyordur, kayıt silinmiş bir eklentiden kalmıştır, ya da bir kod parçacığı eklentisinin veritabanındaki koduna gömülüdür. İkinci ihtimal, yani yetim kayıtlar, bu işin en kârlı hedefidir: sahibi olmayan bir veri her istekte bellek işgal ediyordur ve silinmesi hiçbir şeyi bozmaz.
Aktif eklenti listenizi çıkarıp ön eklerle karşılaştırın:
wp plugin list --status=active --field=name
Süresi Geçmiş Transient'ler Neden Kendiliğinden Temizlenmiyor?#
Transient, WordPress'in "şu veriyi şu kadar süre sakla" mekanizmasıdır. Sürenin bitmesi kaydın silinmesi anlamına gelmez; WordPress transient'i yeniden istendiğinde süresine bakar ve geçmişse o an siler. Kimse istemezse satır orada durur.
WordPress 4.9'dan beri bir güvenlik ağı vardır: günlük çalışan wp_scheduled_delete cron olayı delete_expired_transients() fonksiyonunu tetikler ve süresi geçmiş kayıtları toplar. Buna rağmen sahada binlerce transient satırı görmenizin üç somut nedeni olur:
- WP-Cron gerçekte çalışmıyordur. Sanal cron ziyaretçi trafiğine bağlıdır; sayfa önbelleği devredeyse PHP çalışmadığı için tetikleme de olmaz. Bu sorunun kalıcı çözümü için WP-Cron'u kapatıp gerçek cron kurma yazımıza bakın.
- Süresiz transient'ler autoload edilir.
set_transient()fonksiyonuna süre verilmezse kayıt, süre satırı olmadan yazılır ve varsayılan autoload davranışına tabi olur. Yani "süresi geçmiş" sayılmaz, temizlenmez ve her istekte belleğe yüklenir. Autoload listesinde_transient_ile başlayan devler görüyorsanız sebebi budur. - Yetim kalmış çiftler. Her süreli transient iki satırdır: veri ve
_transient_timeout_süresi. Süre satırı bir şekilde silinmişse, veri satırı ebediyen kalır; temizlik fonksiyonu onu bulamaz.
Önce sayın. Alt çizgi karakteri SQL'de joker olduğu için kaçırmayı unutmayın; LIKE '_transient_%' yazarsanız istemediğiniz satırları da yakalarsınız:
SELECT COUNT(*) AS adet,
ROUND(SUM(LENGTH(option_value)) / 1024, 2) AS kb
FROM wp_options
WHERE option_name LIKE '\_transient\_%'
OR option_name LIKE '\_site\_transient\_%';
Sonra asıl zararlıyı, yani autoload edilen transient'leri ayıklayın:
SELECT option_name, ROUND(LENGTH(option_value) / 1024, 2) AS kb
FROM wp_options
WHERE option_name LIKE '\_transient\_%'
AND autoload IN ('yes', 'on', 'auto', 'auto-on')
ORDER BY LENGTH(option_value) DESC
LIMIT 20;
Küçük bir kontrol daha: harici object cache aktifse transient'ler wp_options tablosuna hiç yazılmaz, doğrudan Redis/Memcached'e gider. Redis kurulu olduğunu düşündüğünüz bir sitede binlerce _transient_ satırı görüyorsanız, object cache aslında devrede değildir. Bu tek başına araştırmaya değer bir bulgudur.
Temizlik Sırası: Yedek, Transient, Yetim, autoload=off#
Sıralama önemlidir. En güvenli işlemden en riskliye doğru ilerleyin ve her adımdan sonra siteyi açıp bakın.
1. Yedek alın#
Bu adımı atlamayın. Aşağıdaki DELETE ve UPDATE ifadeleri geri alınamaz.
wp db export ~/yedek-$(date +%F).sql
# WP-CLI yoksa:
mysqldump -u KULLANICI -p VERITABANI > ~/yedek-$(date +%F).sql
Dosyanın gerçekten oluştuğunu ve makul boyutta olduğunu ls -lh ile doğrulayın. Ayrıntılar için mysqldump ile veritabanı yedekleme rehberimize bakabilirsiniz.
2. Süresi geçmiş transient'leri temizleyin#
En güvenli ve en hızlı kazanç burada. WP-CLI varsa tek komut:
wp transient delete --expired
# Çok siteli kurulumda ağ genelindekiler için:
wp transient delete --expired --network
WP-CLI yoksa aynı işi SQL ile yapabilirsiniz. Aşağıdaki sorgu süre satırını ve ona bağlı veri satırını birlikte siler:
DELETE a, b FROM wp_options a
LEFT JOIN wp_options b
ON b.option_name = CONCAT('_transient_', SUBSTRING(a.option_name, 20))
WHERE a.option_name LIKE '\_transient\_timeout\_%'
AND a.option_value < UNIX_TIMESTAMP();
wp transient delete --all komutuna dikkat: süresi dolmamış olanları da siler. Bu genelde zararsızdır (yeniden üretilirler) ama bir mağazada geçici olarak yavaşlamaya yol açar; yoğun saatte çalıştırmayın.
3. Yetim kayıtları silin#
Silinmiş eklentiden kalan kayıtları, sahibini doğruladıktan sonra kaldırın. Önce ne sileceğinizi görün, sonra silin:
-- Önce görün
SELECT option_name, ROUND(LENGTH(option_value)/1024, 2) AS kb
FROM wp_options
WHERE option_name LIKE 'eskiEklenti\_%';
-- Sonucu inceledikten sonra silin
DELETE FROM wp_options WHERE option_name LIKE 'eskiEklenti\_%';
rewrite_rules kaydı yüzlerce kilobayta ulaştıysa onu silmek güvenlidir; WordPress kalıcı bağlantıları bir sonraki ihtiyaçta yeniden üretir. İsterseniz wp rewrite flush komutuyla hemen tazeleyin.
4. Gerekli ama büyük kayıtları autoload dışına alın#
Bir kaydın büyük olması onun gereksiz olduğu anlamına gelmez. Aktif bir eklentinin gerçekten kullandığı 400 KB'lık bir ayar bloğu silinemez, ama her istekte yüklenmesi gerekmiyor olabilir. Eklenti o değeri get_option() ile istediğinde WordPress ayrı bir sorguyla yine getirir; sadece maliyet, ihtiyaç duyan sayfaya kaydırılmış olur.
WordPress 6.4 ile gelen özel fonksiyonun WP-CLI karşılığı bu iş için doğru araçtır, çünkü değere dokunmadan yalnız bayrağı değiştirir ve object cache'i tutarlı bırakır:
wp option get-autoload ornek_dev_kayit
wp option set-autoload ornek_dev_kayit off
Doğrudan SQL kullanacaksanız önbelleği temizlemeyi unutmayın; alloptions anahtarı eski hâliyle durduğu sürece değişiklik hiçbir şeye yaramaz:
UPDATE wp_options SET autoload = 'off' WHERE option_name = 'ornek_dev_kayit';
wp cache flush
Değişikliği yaptıktan sonra siteyi bir gün izleyin: ilgili eklentinin ekranları, ön yüzdeki widget'ları ve varsa zamanlanmış görevleri çalışıyor mu? Sorun çıkarsa aynı komutu on ile geri alırsınız — bu, silmeye göre çok daha ucuz bir denemedir. Kural: önce off, sonra test, en son silme.
Sonucu Ölçün: Önce ve Sonra#
Temizlik bittiğinde ölçüm sorgusunu aynen tekrar çalıştırın. Somut bir örnek, tipik bir kurumsal sitede şöyle görünür:
| Ölçüm | Önce | Sonra |
|---|---|---|
| Autoload toplam | 2.840 KB | 310 KB |
| Autoload kayıt sayısı | 1.960 | 640 |
_transient_ satır sayısı | 7.400 | 90 |
| Panel ana sayfa TTFB | 1,9 sn | 0,7 sn |
TTFB'yi kendiniz ölçerken önbelleğe takılmayan bir uç nokta seçin. Ana sayfa büyük ihtimalle önbellekten döneceği için hiçbir şey göstermez; wp-login.php her zaman PHP çalıştırır:
for i in 1 2 3 4 5; do
curl -o /dev/null -s -w '%{time_starttransfer}\n' https://ornek.com/wp-login.php
done
Rakam kıpırdamadıysa dürüst sonuç şudur: darboğaz autoload değildi. O zaman aramayı eklenti bazında sürdürün — hangi eklentinin siteyi yavaşlattığını bulma ve TTFB'yi düşürme yazıları bir sonraki adımınız olur.
Tekrar Şişmemesi İçin Ne Yapmalı?#
Temizlik kalıcı bir çözüm değil, bir sıfırlamadır. Aynı eklentiler aynı davranışı sürdürecektir. Üç basit alışkanlık işi kalıcı kılar.
Ayda bir ölçün. Sunucuda cron kurabiliyorsanız rakamı bir dosyaya biriktirin; eğilimi görmek tek seferlik rakamdan çok daha kıymetlidir:
0 6 * * 1 cd /home/kullanici/public_html && printf '%s %s\n' "$(date +%F)" "$(wp option list --autoload=on --format=total_bytes)" >> /home/kullanici/autoload.log
WP-Cron'u gerçek crona bağlayın. Böylece günlük transient temizliği trafiğe bağlı olmaktan çıkar.
Eklenti silerken "verileri de kaldır" seçeneğini işaretleyin. Çoğu eklenti bu seçeneği ayar ekranında sunar; işaretlemeden kaldırdığınız her eklenti geride kayıt bırakır. Kendi kodunuzu yazıyorsanız da büyük veriyi add_option( 'ad', $deger, '', false ) şeklinde autoload dışında saklayın.
Barındırma tarafında dikkat edilecek nokta ise şu: autoload şişmesi CPU değil bellek ve serileştirme maliyetidir, bu yüzden pakete kaynak eklemek genelde beklendiği kadar iyileştirme getirmez. Clou.TR paketlerinde de olduğu gibi, PHP bellek limitini yükseltmek siteyi çökmekten korur ama her istekte 3 MB'lık diziyi kurma işini ortadan kaldırmaz; asıl kazanç veriyi küçültmektedir.
Sıkça Sorulan Sorular#
Autoload verisi kaç KB olmalı?#
Kesin bir üst sınır yoktur ama pratik eşik nettir: 300 KB altı sağlıklı, 800 KB üstü incelenmeli, 1 MB üstü sorunlu kabul edilir. Kayıt sayısı da önemlidir; 1.500'ün üzerinde autoload satırı, tek tek küçük olsalar bile her istekte kurulan dizinin maliyetini yükseltir. Hedefiniz belirli bir rakama ulaşmak değil, ölçümü temizlik öncesi ve sonrası karşılaştırıp gerçek kazanç elde ettiğinizi görmek olmalı.
wp_options tablosundaki büyük bir kaydı silmek güvenli mi?#
Kaydın sahibi belirlenmeden silmek risklidir; aktif bir eklentinin ayarını kaldırırsanız o eklenti sıfırlanabilir veya hata verebilir. Güvenli sıra şudur: önce kaydın adını eklenti dosyalarında arayın, sahibi çıkmazsa yetim kabul edin. Emin olamadığınız her kayıtta silmek yerine autoload değerini off yapın, siteyi bir gün izleyin. Sorun çıkmazsa zaten sildiğinizde de çıkmayacaktır.
WordPress 6.6 sonrası neden eski autoload sorgusu yanlış sonuç veriyor?#
Çünkü 6.6 ile autoload sütunu yes ve no dışında on, off, auto, auto-on, auto-off değerlerini de alabiliyor. Yalnızca autoload = 'yes' filtreleyen bir sorgu, yeni yazılan on, auto ve auto-on satırlarını hiç saymaz. Doğru filtre bu dört değeri birlikte kapsamalıdır. Eski sorguyu kullanan bir sitede "autoload verim çok küçük" sonucuna varmak, sorunu görmezden gelmenin en kolay yoludur.
Redis veya Memcached kurarsam autoload sorununu çözer miyim?#
Hayır. Object cache, autoload verisini alloptions adlı tek bir anahtarda tutar; bu anahtar her istekte çekilir ve PHP tarafında yeniden açılır. Büyük bir yük, önbellekte de büyük bir yüktür. Memcached'de varsayılan 1 MB öğe sınırı aşılırsa anahtar hiç yazılamaz ve her istek veritabanına düşer; yani sorun aynen devam eder, üstüne bir de boşuna deneme maliyeti eklenir.
Transient temizliği neden kendiliğinden yapılmıyor?#
Aslında yapılır: WordPress günlük bir cron olayıyla süresi geçmiş transient'leri siler. Ancak bu mekanizma üç durumda çalışmaz. WP-Cron ziyaretçi trafiğine bağlıdır ve sayfa önbelleği devredeyse tetiklenmeyebilir; süresiz olarak yazılan transient'ler hiçbir zaman "süresi geçmiş" sayılmaz; süre satırı silinmiş yetim kayıtları ise temizlik fonksiyonu bulamaz. Bu yüzden gerçek cron kurmak ve arada elle temizlik yapmak gerekir.
Temizlikten sonra hiçbir şey hızlanmadıysa ne yapmalıyım?#
Bu, ölçümün işe yaradığı anlamına gelir: darboğazın autoload olmadığını kanıtladınız. Sıradaki adaylar sırasıyla ağır eklentiler, yavaş veritabanı sorguları, önbelleğe girmeyen AJAX çağrıları ve yetersiz PHP sürümüdür. Değişiklikleri geri almanıza gerek yok; küçültülmüş autoload verisi zararsızdır ve gelecekteki büyümeye karşı size alan kazandırmıştır. Aramayı eklenti devre dışı bırakma yöntemiyle sürdürün.