搜索全站
插件 12 分钟阅读

WordPress 插件装多少个才合适?别再数数量了

插件装 30 个就一定慢吗?本文从加载机制、autoload 数据、HTTP 外链请求三个真实瓶颈讲清插件数量与性能的关系,给出可执行的量化排查 SQL 与优化顺序。

U
UFO_PF 2017-07-24 · 阅读 12 分钟
Wo 插件
阅读提示
本文约 4,525 字,预计阅读 12 分钟。文中命令与配置均经过实测,可直接参考执行。

引言:20 个插件的站比 60 个插件的站还慢

「插件不要装太多」是 WordPress 圈流传最广的建议之一,但它几乎是错的。真正决定站点速度的,从来不是插件数量这个数字,而是每个插件在每次请求里做了什么。

一个只注册了一个短代码、只在特定页面输出内容的插件,装上它对首页速度的影响接近于零——它的 PHP 文件会被加载、解析,但也就仅此而已,几百微秒的事。而一个在 init 钩子里做三次外部 API 请求、每次都要等 200ms 超时的插件,哪怕你只装它一个,首页也快不了。

所以真实世界里经常出现这种情况:A 站装了 60 个插件,TTFB 400ms;B 站装了 20 个插件,TTFB 1.8 秒。差别不在数量,在于 B 站那 20 个插件里,有几个是重量级的、有几个在每次页面加载时都发起了外部请求、有几个往 wp_options 里塞了几兆的 autoload 数据。

本文拆开讲清楚插件到底在哪些环节消耗性能,以及怎么用几条命令把这些消耗量化出来,最后给出优化优先级。

原理分析:插件影响性能的三个真实通道

通道一:PHP 文件加载与解析。

每次请求,WordPress 会读取 wp_options 中 active_plugins 记录,依次 include 每个插件的主文件。这部分开销是「文件数 × 单文件解析成本」。开启 OPcache 后,解析成本被大幅摊薄,30 个插件和 60 个插件的实际差异通常只有几毫秒。这是《插件越多越慢》这条说法里最不成立的那一半。

通道二:数据库查询与 autoload 数据。

这是真正的大头,而且经常被忽略。WordPress 在启动时会执行 wp_load_alloptions(),把 wp_options 表里所有 autoload = yes 的记录一次性读进内存,每个请求都读一次。很多插件把配置、缓存、甚至整段 HTML 塞进 autoload 选项里,装十个这样的插件,每次请求就要白白拉取几 MB 数据。

-- 查看 autoload 数据的总量与最大的几条
SELECT option_name, LENGTH(option_value) AS bytes
FROM wp_options
WHERE autoload IN ('yes','on','auto-on')
ORDER BY bytes DESC
LIMIT 20;

-- 总量
SELECT SUM(LENGTH(option_value))/1024 AS total_kb, COUNT(*) AS cnt
FROM wp_options
WHERE autoload IN ('yes','on','auto-on');

经验阈值:autoload 数据总量超过 800KB 就要开始查是谁贡献的;超过 2MB 时,TTFB 通常会出现肉眼可见的劣化。

通道三:外部 HTTP 请求。

插件调用 wp_remote_get() 去请求第三方 API(更新检查、字体、统计、授权校验)。这类请求是同步阻塞的,一次 300ms 的外部请求会直接加到 TTFB 上。如果对方服务抖动或超时,你的页面就跟着卡死。

性能通道 与插件数量的关系 典型量级 可观测位置
PHP 文件加载 弱相关(有 OPcache 时几乎无关) 几 ms ~ 十几 ms Query Monitor Overview
数据库查询 中等相关 每插件 0–20 条查询 Query Monitor Queries by Component
autoload 数据 无关数量,只看总量 几十 KB ~ 数 MB 上述 SQL
外部 HTTP 无关数量,只看有没有 每次 0–1000+ ms Query Monitor HTTP API Calls
前端 JS/CSS 中等相关 每插件 0–2 个请求 Query Monitor Scripts & Styles

结论很清楚:插件数量是一个糟糕的性能代理指标。真正该监控的是三个数字——autoload 总量、每次请求的数据库查询数、每次请求的外部 HTTP 请求数。

保姆级实操

第一步:先量化现状,不要凭感觉

# 1) autoload 数据总量
wp db query "SELECT SUM(LENGTH(option_value))/1024 AS total_kb FROM wp_options WHERE autoload IN ('yes','on','auto-on')"

# 2) 前端真实耗时(跑 3 次取中位数)
for i in 1 2 3; do
  curl -s -o /dev/null -w "TTFB=%{time_starttransfer}s 总计=%{time_total}s\n" https://example.com/
done

第二步:定位 autoload 的主要贡献者

SELECT option_name,
       LENGTH(option_value)/1024 AS kb,
       CASE
         WHEN option_name LIKE '%transient%' THEN 'transient(可清)'
         WHEN option_name LIKE 'widget_%'    THEN '小工具历史数据'
         ELSE '插件配置'
       END AS kind
FROM wp_options
WHERE autoload IN ('yes','on','auto-on')
ORDER BY kb DESC
LIMIT 15;

看到 transient 类的过期缓存直接清掉;看到某个插件贡献了几百 KB 且无法关闭,就该考虑替换它。

第三步:清理过期 transient

wp transient delete --expired --all
wp db query "DELETE FROM wp_options WHERE option_name LIKE '\_transient\_timeout\_%' AND option_value < UNIX_TIMESTAMP()"
wp db query "DELETE FROM wp_options WHERE option_name LIKE '\_site\_transient\_timeout\_%' AND option_value < UNIX_TIMESTAMP()"

第四步:把不需要的选项改成非 autoload

-- 把某个大选项改为不自动加载
UPDATE wp_options SET autoload = 'no' WHERE option_name = 'some_plugin_big_cache';

注意:如果这个选项在每次请求里都要用到,改成 no 只是把成本从「一次批量读」变成「一次单独查询」,不一定更快。只对「后台才会用到」的选项做这个操作。

第五步:加一个轻量性能日志

在 wp-content/mu-plugins/ 下建一个文件,把每次请求的核心指标写进错误日志,跑一天就能看出波动:

<?php
// mu-plugins/perf-log.php
add_action( 'shutdown', function () {
    if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
        return;
    }
    error_log( sprintf(
        '[perf] %s | %.3fs | %d queries | %.1fMB',
        $_SERVER['REQUEST_URI'] ?? '-',
        timer_stop( false, 3 ),
        get_num_queries(),
        memory_get_peak_usage( true ) / 1048576
    ) );
} );

timer_stop() 与 get_num_queries() 都是 WordPress 核心函数,前者返回本次请求的执行耗时,后者返回累计数据库查询数。

第六步:按优先级优化

优化顺序固定为:外部 HTTP 请求 → autoload 数据 → 数据库查询 → 插件数量。前三项处理完,你会发现根本不需要删插件。

第七步:清理真正无用的插件

最后才是删。判定标准是三条:功能已不再使用、有更轻的替代、或者它同时属于 识别已弃用插件 中描述的情况。删除前先备份数据库,因为删除会触发 uninstall.php。

常见踩坑

  1. 为降数量把多个小插件合并成一个大插件:合并后的插件功能更重,往往更慢。

  2. 装「插件性能监控插件」本身:这类插件自己也会消耗资源,测量完就该停用。

  3. 忽略 OPcache 的作用:没开 OPcache 时,插件数量的影响会被放大。检查 phpinfo() 里的 opcache.enable。

  4. 盲目清空所有 transient:有些 transient 是插件的工作缓存,清掉后第一次访问会更慢。

  5. 只看首页:后台页面、WooCommerce 的购物车页、搜索页的插件参与度完全不同,要分别测。

  6. 案例: 某外贸站 42 个插件,站点很慢,站长一直想删插件但不知道删哪个。跑上面的 SQL 后发现 autoload 总量 3.4MB,其中单个 slider_revolution_cache 占了 1.9MB,另有 900KB 来自一个统计插件的历史数据。清理并把大选项改为非 autoload 后,autoload 降到 480KB,TTFB 从 1.6s 降到 520ms,一个插件都没删。教训是:先测再动,性能问题几乎从来不是靠删插件解决的。

  7. 在高峰期做批量清理:删除大量 transient 会造成数据库写压力,选在低峰执行。

总结

记住三条结论:插件数量与性能弱相关;autoload 总量、数据库查询数、外部 HTTP 请求数才是强相关指标;优化顺序永远是前三者优先于删插件。

可以固化的月度检查:查一次 autoload 总量(阈值 800KB)、清一次过期 transient、看一次 TTFF 趋势、复查一次有没有新增的外部请求插件。

如果你想知道怎么把性能开销定位到单个插件身上,Query Monitor 测量插件开销 给出了逐插件量化的方法;而在不动生产站的前提下确认到底是哪个插件在捣乱,则需要 Health Check 排障模式。

U
UFO_PF作者

专注 WordPress 生态的实战作者,内容以「可复制、可验证」为第一原则。

留下你的想法

邮箱地址不会被公开。带 * 的为必填项。