網站愈用愈慢,外掛裝了又刪、佈景換了好幾套,後台明明沒幾篇文章,每一頁卻像背著沙包跑。很多人第一時間怪主機、怪 PHP 版本,卻忽略了資料庫裡一張不起眼的表:wp_options。更精確地說,是這張表裡被標記成「自動載入」的那一堆資料,正在每一次請求都被整批撈進記憶體。
WordPress autoload 優化,講的就是把這份「每頁都要扛」的隱形負擔減到合理範圍。這篇會先解釋 autoload 為什麼會拖慢站台、多大算太肥、怎麼動手檢查與清理,並說明 WordPress 6.6、6.7 之後核心對自動載入做了哪些調整,讓你不必再靠土法煉鋼。
autoload 是什麼?為什麼它會拖慢每一頁
autoload 是 wp_options 表裡的一個欄位,值為 on 或 off(舊版是 yes 或 no),用來標記某筆選項要不要在每次請求時自動載入。標記為自動載入的選項,會在 WordPress 啟動時被一次性、整批地從資料庫撈出來放進記憶體,之後程式碼用 get_option() 讀取時就直接從記憶體拿,不再多打一次資料庫查詢。
這個設計本身是為了效能。WordPress 光是核心就有上百筆選項,外加佈景與外掛的設定,若每筆都各打一次資料庫查詢,一個頁面動輒上百次查詢,反而更慢。把常用選項合併成「一次大查詢」載入,是合理的取捨。
問題出在「整批」這兩個字。自動載入清單沒有上限,也沒人保證清單裡每一筆都真的會被用到。當外掛把根本只在後台才需要的設定也標成自動載入,當已經刪掉的外掛留下一堆孤兒資料,這張清單就會愈養愈大。原本要省查詢的那一次大查詢,反而變成每頁都要搬一大箱用不到的東西,搬運與反序列化的成本拖累了伺服器回應時間。
對速度的影響不只是「資料庫慢一點」。伺服器回應變慢會直接推高 TTFB(首位元組時間),而 TTFB 又是 Core Web Vitals 裡 LCP(最大內容繪製)的上游因素。換句話說,autoload 肥大不是後台自己慢爽的,它會一路傳導到訪客看到的載入速度,進而影響搜尋排名訊號。
自動載入資料多大算太肥?
一個常被引用的安全範圍是:總量控制在 1MB 以內通常沒事,理想值落在 300KB 到 800KB 之間。當數字逼近 3 到 5MB,幾乎可以確定有東西該被清掉或改成不自動載入;超過 10MB 就屬於該立刻處理的狀況。
WordPress 6.6 之後把這個判斷直接做進了核心。網站健康狀態(Site Health)多了一項檢查,當自動載入選項的總大小超過 800KB,後台會跳出「自動載入的選項可能影響效能」的警示。這讓不熟資料庫的站長也能在後台第一眼看到問題,不必先會下 SQL。
要提醒的是,這些數字是經驗門檻,不是硬性紅線。同樣 1.5MB 的自動載入資料,在一台規格充裕、又有持久物件快取的主機上可能無感;在共享主機上就可能明顯卡頓。門檻的意義是「超過這個量就值得花時間查」,而不是「沒超過就完全不用管」。
還有一個容易被忽略的陷阱:如果站台用 Memcache 當持久物件快取,單一快取值常有大小上限(例如 1MB)。自動載入資料若累積到超過這個上限,整包就可能永遠存不進快取,導致那次大查詢每一頁都重打一次。對高流量站台來說,這種情況比單純的肥大更傷。
怎麼檢查站台的 autoload 大小與兇手
最直接的方法是下 SQL。登入 phpMyAdmin、選到資料庫、切到 SQL 分頁,跑這一句就能看到自動載入資料的總位元組數:
SELECT SUM(LENGTH(option_value)) AS autoload_size FROM wp_options WHERE autoload IN ('yes','on','auto','auto-on');
回傳的是位元組(byte),除以 1024 是 KB,再除以 1024 是 MB。要特別注意 WHERE 條件:WordPress 6.6 之後資料庫裡的自動載入值不再只有 yes,還有 on、auto、auto-on 等新值,舊查詢只比對 yes 會漏算,把這些值一起列進去才準。如果你的資料表前綴不是 wp_,記得一併替換。
光看總量還不夠,要揪出兇手得把最肥的幾筆排出來:
SELECT option_name, LENGTH(option_value) AS size FROM wp_options WHERE autoload IN ('yes','on','auto','auto-on') ORDER BY size DESC LIMIT 20;
排在前面的選項名稱通常會透露來源。看到陌生的 option_name,可以到外掛或佈景資料夾用 grep 搜尋字串,確認是哪支程式寫的;找不到,多半就是已經刪掉的外掛留下的孤兒資料。在 phpMyAdmin 裡按該筆的編輯鈕,有時也能從內容看出開發商或外掛名稱。
如果伺服器能跑 WP-CLI,檢查會更輕鬆。下面這行會列出所有自動載入的選項並照大小排序,不必進資料庫:
wp option list --autoload=on --fields=option_name,size_bytes --orderby=size_bytes --order=desc
不想碰指令也行。Advanced Database Cleaner、WP-Optimize 這類外掛,以及效能團隊維護的 Performance Lab,都提供圖形介面檢視自動載入清單。Performance Lab 還會強化網站健康狀態那項檢查,直接列出可以關閉自動載入的候選選項,對純後台操作的站長最友善。
autoload 為什麼會養出一堆肥肉?
肥大的來源大致可以歸成三類,知道源頭才知道該往哪裡清。
第一、外掛把不該每頁載入的資料標成自動載入。 最典型的例子是聯絡表單外掛——它的設定其實只在聯絡頁或後台才用得到,卻被預設成每頁載入。這類「該設 off 卻設成 on」的選項,是最常見也最值得優先處理的對象。
第二、刪掉的外掛與佈景留下孤兒資料。 WordPress 移除外掛時不會自動清掉它寫進 wp_options 的選項。用過一陣子又刪掉的外掛,設定常常原封不動留在表裡,而且還維持自動載入,等於每頁都在搬一個早就用不到的箱子。老站累積個兩三年,這類殘留往往是肥大的主力。
第三、開發者把大量資料塞進 wp_options 而不另建資料表。 wp_options 當初不是設計來放上千筆資料的。有些外掛為了省事,把快取、紀錄、甚至像 301 轉址清單這種會持續長大的資料都丟進選項表並自動載入。轉址這類功能其實更適合在伺服器層處理,留在選項表裡只會持續膨脹。
除了上述三類,還有兩種會把整張表撐大、但未必都標自動載入的常客要一起留意:過期的暫存資料(transient)與 session 紀錄。沒有物件快取時,transient 會存進 wp_options,理論上會過期消失,實際上常有大量過期紀錄賴著不走。session 則更誇張,曾有站台因排程沒正常觸發,累積出數百萬筆 wp_session 紀錄、整張表脹到數百 MB 的案例。
怎麼安全地幫 wp_options 瘦身
動手前先講最重要的一句:改資料庫之前一定要備份,最好在測試站(staging)上先試。下面的操作都會直接改寫資料表,沒備份就出錯等於沒有退路。WooCommerce 這類交易型站台尤其要謹慎,選項裡可能混著金流或訂單相關設定,誤刪會出事。
清理可以照「由穩到險」的順序走:
第一步、先把確定不該自動載入、但又不想刪的選項改成不載入。針對某筆已知的選項,可以這樣關掉它的自動載入:
UPDATE wp_options SET autoload = 'off' WHERE option_name = '要關閉的選項名稱';
這一步最安全,因為資料還在,只是不再每頁載入。改完那筆就退出自動載入清單,大查詢立刻變輕。
第二步、清掉已刪外掛留下的孤兒資料。先用 SELECT 配合 LIKE 確認範圍,看清楚要刪哪些再下 DELETE。例如清掉某支已移除外掛殘留的選項:
DELETE FROM wp_options WHERE option_name LIKE '某外掛前綴_%';
務必先用 SELECT 把同一條件的結果看過一遍,確定每一筆都真的是該外掛的殘留、不是還在用的選項,再換成 DELETE。
第三步、處理過期的暫存與 session。過期 transient 建議用專門的清理外掛來刪,只清掉確實過期的那些,比手動下指令安全。失控的 wp_session 紀錄則可以先查再刪。清完這些之後,對 wp_options 跑一次 OPTIMIZE TABLE,回收刪除留下的空間與碎片。
最後一招,是在 autoload 欄位上加索引。當表很大、查詢仍偏慢時,替自動載入欄位建立索引能讓篩選更有效率。不過這屬於進階優化,前面幾步把肥肉清掉後,多數站台其實用不到這一步。
整個流程的重點不是把所有東西都關掉或刪光,而是判斷「這筆資料是不是每頁都需要」。需要的留著自動載入,不需要的改成 off 或清掉,這才是 WordPress autoload 優化的核心。
WordPress 6.6 與 6.7 對自動載入做了哪些改變
如果你還在用「把 autoload 全部設 yes」的舊思維,這兩個版本帶來的調整值得認識,因為核心已經開始幫你做一部分判斷。
最關鍵的一項,是 add_option() 與 update_option() 的 $autoload 參數預設值從 yes 改成了 null。現在這個參數有三種建議寫法:傳 true 代表一律自動載入,用在每頁都要的選項;傳 false 代表永不自動載入,用在很少用到的選項;傳 null(或不傳)則交給 WordPress 依內建規則動態決定。為了向下相容,舊的 yes 與 no 仍然有效,會分別對應成 true 與 false。
資料庫裡儲存的值也跟著變多。新版寫入的選項,autoload 欄位可能是 on、off、auto、auto-on、auto-off 其中之一,而不再只有 yes 或 no。核心沒有規劃升級程序去改寫舊資料,所以舊選項仍會以 yes 或 no 存著,被當成 on 與 off 看待。這也是前面提醒「查詢條件不能只比對 yes」的原因。
針對過大的選項,核心新增了一道自動防線。當某筆選項的值超過約 150KB(150000 位元組),而開發者又沒有明確傳 true 要求自動載入時,WordPress 會自動不把它設為自動載入。這個門檻可以用 wp_max_autoloaded_option_size 篩選器調整,但官方建議不要調高,調高只會讓效能變差。若你確實有一筆大選項非得每頁載入,則可以透過 wp_default_autoload_value 篩選器個別處理,且要謹慎使用。
WordPress 6.6 同時補上了前面提過的網站健康狀態檢查(超過 800KB 警示),6.7 則讓核心自己所有的選項都明確設定了 autoload 值,把過去一些不必要的自動載入清掉。對開發者來說,這代表一件事:不要再依賴預設行為,每次 add_option()、update_option() 都明確傳入該選項該不該自動載入。
寫外掛或經營 WooCommerce 站該注意什麼
對外掛開發者而言,判斷邏輯其實很單純:一筆選項如果在每個請求都會跑到的邏輯裡用到,就該自動載入;如果只在特定頁面、特定條件或只在後台才用到,就不該自動載入。怕拖慢自己後台頁面的效能?核心早就準備好對策。
需要在後台一次讀好幾筆「不自動載入」的選項時,可以用 wp_prime_option_caches() 把它們一次撈進記憶體,之後各自 get_option() 就不會再各打一次查詢。這個函式只負責預載、不回傳值,適合掛在自家後台頁面的 load 鉤子上,做到「後台快、又不拖累整站」。
當外掛被停用時,把原本自動載入的選項用 wp_set_options_autoload() 改成不載入,是負責任的做法——資料保留下來,使用者重新啟用時再切回自動載入即可,既不會丟設定,也不會在停用期間繼續拖累每一頁。
WooCommerce 站台則要特別盯著交易過程產生的暫存與 session。購物車、結帳流程會寫入大量 transient 與 session 紀錄,沒有物件快取時這些全擠在 wp_options 裡,是這類站台 autoload 與整表肥大的常見來源。建議搭配持久物件快取,並定期檢查過期暫存有沒有正常清除。涉及金流的選項只做客觀檢視、確認來源,不要看到不認得就刪。
從檢查到清理,怎麼讓 wp_options 長期維持輕盈
autoload 肥大是時間累積出來的隱形負擔,處理它的節奏也該是長期的,不是清一次就一勞永逸。先用 SQL 或 WP-CLI 量出目前的自動載入總量,對照 800KB 到 1MB 的門檻判斷要不要動手;接著從最肥的選項往下查來源,把該關的改成不載入、該刪的孤兒資料清掉、過期暫存與 session 一併處理,最後視情況優化資料表。
往後每次安裝或刪除外掛,順手回頭看一眼網站健康狀態那項檢查,就能在肥肉養大前先發現。把這個動作變成維護習慣,wp_options 就不會再悄悄變成拖慢每一頁的沙包。現在就先打開 phpMyAdmin 或網站健康狀態,量一下你站台的自動載入資料到底有多大——數字會告訴你接下來該不該動手。