快訊
2026-07-12
Wordpress教學

WordPress 快取搞不懂?物件快取 vs 頁面快取一次拆解,搞懂再裝外掛

約 12 分鐘閱讀

⚡ 站長快讀:核心重點

  • 文章屬性:觀念拆解 + 教學實戰
  • 適用系統:自架 WordPress 6.x–7.0
  • 難易度 / 耗時:中 / 約 12 分鐘
  • 核心結論:物件快取砍重複資料庫查詢、頁面快取跳過整個 PHP,兩者互補不是二選一
  • 適用對象:裝了快取外掛還是覺得慢、或被 Site Health 叫去裝快取的站長

📌 快速答案

一句話答案:WordPress 快取分成多層,物件快取把貴的資料庫查詢結果存進記憶體、頁面快取把整頁 HTML 存起來跳過 PHP;前者加速動態頁,後者加速訪客頁,正確做法是分層一起用而不是二選一。

廣告

🧰 開始前的準備

  • 適用系統:自架 WordPress(本文以目前穩定版 WordPress 7.0、2026 年上半年為準;快取機制自 6.x 以來一致)。
  • 權限需求:要動 wp-config.php 或裝持久物件快取,需要主機管理權限(FTP/SSH 或主機商後台)。
  • 需要工具:除錯用 Query Monitor 外掛(看每頁跑幾條查詢);持久物件快取需要主機提供 Redis 或 Memcached 伺服器。
  • 預計耗時:讀懂觀念約 12 分鐘;實際套用依主機環境而定。
  • 難度門檻:看得懂「一個網頁請求怎麼被組出來」就能吸收,不需要會寫 PHP。

🔍 為什麼你需要搞懂快取分層?

先講一個很多站長的共同困惑:明明裝了「最好用的快取外掛」,首頁是變快了,但一登入後台、或會員登入後的頁面還是慢吞吞;更煩的是 WordPress 後台「網站健康狀況」還跳一條「你應該使用持久物件快取」,可是你不是已經裝快取了嗎?

會有這種矛盾,是因為「快取」不是一種東西,而是好幾層。你裝的那個外掛多半只做了其中一層(頁面快取),而 Site Health 在念你的是另一層(物件快取)。兩層解決的問題不一樣、加速的對象也不一樣,搞混了就會出現「裝了還是慢」的錯覺。

想判斷自己站上那條健康狀況警告要不要理、哪些能忽略,可以搭配這篇一起看:WordPress 網站健康狀況完整教學:哪些嚴重問題該修、哪些警告能忽略。這篇則專門把「快取到底分幾層、各層在幹嘛」講清楚,讓你之後看任何快取外掛的設定頁都不再霧煞煞。


🗂️ WordPress 的四層快取地圖(先建立全貌)

一個訪客打開你的文章,資料其實是「由外往內」穿過好幾道快取,越外層越快、越省你的伺服器。由外到內大致是:

  1. 瀏覽器快取(Browser Cache):訪客自己電腦上存的圖片、CSS、JS。靠 HTTP 標頭(Cache-ControlExpires)控制,回訪時連你的伺服器都不用連。
  2. CDN / 邊緣快取(Edge Cache):Cloudflare 這類節點,在全球各地幫你存靜態檔甚至整頁 HTML,就近吐給訪客;回訪的靜態資源常常連你主機都碰不到。
  3. 頁面快取(Page Cache):在你自己的主機上,把整頁算好的 HTML 存起來,下次同一頁直接回,不再驚動 PHP。
  4. 物件快取(Object Cache):在最裡層,把 PHP 執行過程中「貴的資料庫查詢結果」暫存在記憶體,少跑幾趟 MySQL。

本文重點是站長最常搞混、也最常設定錯的第 3 層(頁面快取)與第 4 層(物件快取)。先記一句話:頁面快取是「這頁不要再算一次」,物件快取是「這條查詢不要再問資料庫一次」。


🧠 物件快取(Object Cache):把貴的查詢結果記在記憶體

官方定義:它到底存什麼

根據 WordPress 官方開發文件,WP_Object_Cache 這個核心類別的用途是「省下往返資料庫的次數」——把運算成本高、例如複雜資料庫查詢的結果,以一組 key 存進記憶體,之後用同一個 key 取回。程式碼裡不直接碰這個類別,而是用一組 wp_cache_* 函式操作,最常見的是官方文件示範的這個模式:

廣告
// 官方文件示範:先問快取,沒有再查資料庫,查完存回去
$result = wp_cache_get( 'my_result' );
if ( false === $result ) {
    $result = $wpdb->get_results( $query ); // 這行是「貴」的資料庫查詢
    wp_cache_set( 'my_result', $result );
}
// 接下來用 $result…

關鍵中的關鍵:預設「非持久」

這是最多人踩的一格。官方文件白紙黑字寫著:物件快取預設是「非持久(non-persistent)」的——資料只存在記憶體、而且只活在「這一次請求」的期間內。也就是說,同一次請求裡重複用到的查詢,第二次會命中快取;但請求一結束,這些快取就全部丟掉,下一位訪客、下一次載入完全從零開始。

換句話說,原生 WordPress 的物件快取只幫你省「單一頁面組裝過程中的重複查詢」,不會跨請求累積。要讓它「跨頁面、跨訪客都記得」,你得幫它接上一個持久後端。

怎麼變成「持久」:drop-in + Redis/Memcached

官方的做法是在 wp-content/ 放一個叫 object-cache.php特殊 drop-in 檔。WordPress 啟動時如果偵測到這個檔,就會改用它指定的外部快取,而不是預設的記憶體陣列。這個 drop-in 通常由外掛自動幫你放,主流選擇有:

  • Redis Object Cache:最常見,需要主機提供 Redis 伺服器。
  • Memcached Object Cache:需要 Memcached 伺服器與對應 PHP 擴充。
  • SQLite Object Cache:主機沒有 Redis/Memcached 但有 SQLite3 擴充時的替代方案。

💡 順帶更正一個老迷思:早年在 wp-config.phpdefine('WP_CACHE', true) 就能開持久快取,這在 WordPress 2.5 之後早就沒用了——沒裝持久快取外掛的話,這行完全不會生效。官方文件有特別註明這點。

transients:其實是物件快取的「有期限版」

如果你翻過資料庫,可能看過 wp_options 表裡一堆 _transient_ 開頭的資料。Transients API 是 WordPress 給的一套「有到期時間的暫存」機制,寫法跟物件快取很像:

// 官方文件示範:featured 文章查詢,快取 12 小時
if ( false === ( $featured = get_transient( 'foo_featured_posts' ) ) ) {
    $featured = new WP_Query( array( 'category' => 'featured', 'posts_per_page' => 5 ) );
    set_transient( 'foo_featured_posts', $featured, 12 * HOUR_IN_SECONDS );
}

重點來了:transients 的存放位置,取決於你有沒有持久物件快取。 官方說明得很清楚——沒有持久物件快取時,transients 存進 wp_options 資料表(每筆佔兩列:值一列、到期時間一列);一旦裝了持久物件快取,transients 就改存進 Redis/記憶體,讀取快上一個數量級,而且到期清理也交給快取層,wp_options 不會被一堆過期暫存養肥。

這也是為什麼「autoload 選項爆肥、transients 塞滿 wp_options」會拖慢每一個請求——這塊我在資料庫最佳化那篇拆得更細:WordPress 資料庫最佳化:清修訂版本、transients,還要盯住 autoload 這塊隱形肥肉。裝持久物件快取,等於順手把這個肥肉問題也一起解了。

廣告

📄 頁面快取(Page Cache):整頁 HTML 存起來,直接跳過 PHP

物件快取再怎麼快,PHP 還是得從頭跑一遍:載入外掛、跑佈景主題、組出 HTML。頁面快取的想法更暴力——第一次算好整頁 HTML 就存成靜態檔,之後同一個網址的訪客直接吐那份 HTML,PHP 和資料庫連碰都不碰。

這就是為什麼頁面快取對「未登入訪客看文章」的加速最有感:一個原本要跑幾十條查詢、上百毫秒的頁面,命中頁面快取後可能只剩「讀一個檔案吐出去」的時間。

頁面快取住在哪一層

  • 外掛層:在 PHP 裡攔截、把輸出存成 HTML。免費的有 WP Super Cache、W3 Total Cache、LiteSpeed Cache;付費以 WP Rocket 為代表。想看實際一步步設定,可參考:WP Rocket 外掛教學:WordPress 最好用的快取外掛詳細設定
  • 伺服器層:更前面就攔下來,例如 Nginx FastCGI Cache、Varnish,或 LiteSpeed 主機內建的 LSCache。這層連 PHP 都不用啟動,效率最高,但要主機支援。

頁面快取的代價:它是「靜態」的

天下沒有白吃的午餐。頁面快取存的是某一個時間點算好的死 HTML,所以:

  • 會員 / 登入者、購物車、即時庫存、依人顯示的內容不能直接吃頁面快取,不然 A 會員會看到 B 會員的購物車。這些頁面必須繞過(bypass)頁面快取
  • 內容一更新(發新文、改價格),對應的快取要清掉重算,否則訪客看到舊的。

而這些「不能被頁面快取」的動態頁,PHP 還是得老老實實跑一遍——這時候墊在底層的物件快取,就是它們唯一的加速來源。看懂這句,你就懂為什麼兩層要一起上了。


🔬 底層機制:一次請求到底省在哪(沙箱可重現示範)

光講觀念容易空,我在沙箱裡用 Python + SQLite 寫了一支小程式,重現「一個 WordPress 首頁請求」的查詢與組裝流程,量化三種情況的差別。

⚠️ 誠實聲明(請務必看): 以下是沙箱環境對快取「機制」的可重現示範,不是 adersaytech.com 生產站的實測,也不是任何快取外掛的效能跑分。標【實測】的是沙箱真的量到的值(查詢次數);標【模型】的是用公開揭露的假設換算出來的示意時間,不是實測秒數。目的是把「省在哪」講清楚,不是報跑分。

🧪 沙箱環境:Ubuntu 22.04(aarch64)、Python 3.10.12、SQLite 3.37.2。程式建立 500 篇文章 + postmeta + 250 個 autoload 選項,模擬首頁載入 10 篇文章(含經典 N+1 的 postmeta 查詢)。

【實測】每次請求實際打出去的資料庫查詢數:

廣告
情境每請求查詢數說明
A 無任何快取14 次每位訪客都重跑全部查詢
B 持久物件快取(暖)2 次重複查詢被記憶體擋下,只剩動態查詢
C 頁面快取(命中)0 次整頁存好直接回,PHP/DB 全跳過

【模型】把查詢數與算繪換算成示意頁面時間(假設:單次資料庫往返 0.4 ms、PHP 算繪一次 80 ms、頁面快取回應 2 ms;皆為公開假設,非實測):

  • A 無快取 ≈ 14 × 0.4 + 80 = 85.6 ms
  • B 物件快取 ≈ 2 × 0.4 + 80 = 80.8 ms(省下的是資料庫那段)
  • C 頁面快取 ≈ 直接回靜態 = 2 ms

這張表告訴你的三件事

  1. 物件快取砍的是「資料庫時間」,PHP 照樣要跑。 在這個查詢不多的首頁,它只把 14 條查詢降到 2 條,省的時間有限。但關鍵是它會「隨查詢量放大」——WooCommerce 商品頁、會員頁、外掛多的站,一頁動輒上百條查詢,這時物件快取省下的就非常可觀。
  2. 頁面快取砍的是「幾乎全部」,因為連 PHP 都不啟動,所以在模型裡快到跟前兩者不是同一個量級。但它的前提是「這頁可以是靜態的」。
  3. 兩者互補:訪客看文章走頁面快取(最快);登入者、購物車這種繞過頁面快取的動態頁,就靠物件快取在底層墊。少了任一層,都會有一塊使用者體驗掉在地上。

🧭 那我到底該裝哪一種?(情境決策)

不用背,對號入座就好:

  • 純內容型部落格 / 形象官網(幾乎都是未登入訪客):頁面快取就吃掉九成效益。裝一個好的快取外掛把頁面快取開起來,CP 值最高。物件快取有更好,沒有也不致命。
  • 有會員、論壇、大量登入者、或 WooCommerce 商店:物件快取幾乎是必需品。因為你一堆頁面天生不能被頁面快取,PHP 一定要跑,這時持久物件快取(Redis)是它們唯一的加速來源;再加上頁面快取處理未登入訪客。
  • 中大型 / 高流量站:四層全上——瀏覽器快取 + CDN + 頁面快取 + 物件快取,由外往內層層擋掉負載。

關於 Site Health 那條「你應該使用持久物件快取」(WordPress 6.1 起加入的檢查):它是建議、不是錯誤。如果你的站是純靜態部落格、主機也沒 Redis,忽略它沒問題;但如果你站上動態頁很多又剛好有 Redis 可用,那就是它在提醒你有免費效能可撿。要不要理,看你屬於上面哪一種。

⚠️ 動手前的提醒:裝持久物件快取或改快取設定,建議先在測試站(staging)試,並確認外掛有「內容更新自動清快取」的機制。快取最常見的翻車不是變慢,而是「改了看不到」——清掉對應快取就好,別急著懷疑人生。


💡 總結:站長的分層思路

講到這,分享一下站長我自己看快取的思路。以前也覺得「快取外掛裝一裝就好」,直到被一個會員站的後台慢到受不了——首頁明明秒開,登入後台卻要等三四秒。後來才想通:首頁那是頁面快取的功勞,而後台是動態頁、根本吃不到頁面快取,慢的根源在資料庫,那台主機當時也沒開 Redis。補上持久物件快取後,動態頁才真正順起來。

這次為了把「省在哪」講清楚,我特地在沙箱(Python 3.10.12 + SQLite 3.37.2、2026-07-05 執行)重現了首頁請求的查詢流程,才有上面那張 14 → 2 → 0 的查詢數對照。它不是生產站跑分,但足以說明一件事:快取不是一個開關,是好幾層各司其職。 你要做的不是「找最強的那一個」,而是「看自己是哪種站,把對的層補齊」。

一句話收尾:頁面快取讓訪客爽,物件快取讓你自己(和會員)爽,CDN 讓全世界都爽——它們是隊友,不是替代品。


❓ 常見問題

Q:我已經裝了 WP Rocket / LiteSpeed Cache,還需要另外裝物件快取嗎?

看你的站。這些外掛主要做的是頁面快取(W3 Total Cache、LiteSpeed 也能兼做物件快取後端)。如果你的站動態頁多(會員、商店),而且主機有 Redis,補上持久物件快取通常仍有感;純靜態部落格則多半頁面快取就夠。

Q:Site Health 一直叫我「使用持久物件快取」,不理會怎樣嗎?

不會怎樣,它是建議不是錯誤。它只是偵測到你沒有跨請求的持久物件快取。純訪客型的小站可以忽略;動態頁多又有 Redis 可用的站,理它能撿到效能。

Q:物件快取和頁面快取,哪個對「訪客看文章」比較有感?

頁面快取。因為未登入訪客看文章這種情境,整頁可以被存成靜態直接回,連 PHP 都不用跑,加速最直接。物件快取的舞台是那些「不能被頁面快取」的動態頁。

Q:transients 到底算資料庫還是算快取?

兩者都可能。沒有持久物件快取時,transients 存在 wp_options 資料表(等於還是資料庫);裝了持久物件快取後,它們改存進記憶體/Redis,讀取快很多。所以官方才提醒:永遠不要假設 transient 一定在資料庫裡


🔗 延伸閱讀

📎 參考資料來源

📖 第一級|WordPress 官方文件與外掛目錄:

📖 第二級|權威技術媒體 / 廠商指南:

⚠️ 本文核心事實(物件快取/頁面快取機制、transients 行為)以第一級官方文件為準,第二級為外掛現況補充。沙箱示範僅說明機制與量級,非生產站實測。

📅 本文查證戳記:2026-07-05 依據 WordPress 官方開發文件撰寫,沙箱示範同日於 Ubuntu 22.04 / Python 3.10.12 / SQLite 3.37.2 執行。
若你在後續版本遇到步驟失效,歡迎在留言區回報,站長會更新文章。

廣告