这个问题是所有使用 WordPress 建站到一定规模之后都会碰到的问题,一般人的回答都是泛泛而谈,都是那些常见的处理方式,没有具体怎么去定位 WordPress 慢这个问题的方法,定位之后怎么解决也没有。我也接过很多 WordPress 优化的单子,所以我结合自己经验决定讲讲自己是怎么处理的。
基础优化
首先提供三点简单的优化建议:
- 将 WordPress 更新到 6.1,因为 WordPress 6.1 无需插件即可实现站点 0 SQL,这个操作是最直接最有效的。
- WordPress 性能优化的基础是一款速度够快的主题,很多 WordPress 站点速度很慢,绝大部分原因就是主题。
- 对 WordPress 进行基本的优化,WordPress 性能优化:为什么我的博客比你的快,我这篇文章已经做了非常详细的介绍,主要是两点:使用 CDN 对动静态资源进行分离和使用 Memcached 来缓存 WordPress 数据。
可能的原因
做了上面三点简单的基础优化的操作之后,速度还是很慢,那应该怎么办?根据我的经验,WordPress 速度太慢,一般来说可能是下面这些原因:
- 页面的 SQL 请求太多了,把数据库的请求池耗尽了。
- HTTP 请求太多,并且都没有做缓存,占用了太多的服务器资源。
- 主题或者插件的 PHP 程序代码没写好,甚至有死循环,直接卡死。
Log 程序
怎么定位这些问题呢?工欲善其事,必先利其器,所以我写了一个 WordPress 各种 Log 记录的插件,专门来定位这些问题:
如上图所示,首先这个插件会每天孜孜不倦记录程序的错误或者警告,这样我就可以根据这个错误来优化和健壮程序,很多时候,用户是无法清洗反馈清楚自己的错误的,只是说程序有问题,通过 Log 反而容易定位代码的,比如上面的 PHP log :
我截取其中一段,就可以记录一个 PHP Warning 信息,PHP 数组 Undefined index 的问题,具体发生在哪个文件哪一行,具体的回调过程,请求的时间,地址,来源,Post 提交的数据都记录一下,对解决问题是帮助非常大。
上图中还有 weapp 和 weixin 相关的 log,是我为了区分方便处理,把微信公众号和微信小程序插件相关的错误拆分到不同的文件,然后每个文件都加上日期,这样每天的 log 都会被记录下来。
定位问题
你肯定会问,这个 log 记录系统和 WordPress 慢有什么关系?
其实大有关系了,通过 Log 是定位问题最好的方法,为了解决程序慢的问题,我还专门对超过5秒才能打开页面的做了详细的记录。
我会记录这个页面,调用的时间,地址,传递的 POST 数据(如有),来源和具体耗时多少秒:
这个慢查询 Log 会记录这个页面的所有 SQL 请求,共有多少条 SQL 请求,每条 SQL 具体是什么,耗时以及调用栈:
如果有 HTTP 请求,慢查询 Log 也会记录所有的 HTTP 请求,每条 HTTP 请求的链接,参数,耗时和调用栈:
解决问题
定位了问题之后,解决起来就非常方便了。
如果是 SQL 请求太多,是不是在 for 循环里面做了 SQL 请求?如果是,就应该在 for 循环之前,就应该通过所有 id 一次获取数据,这样就不会一次耗尽数据库线程。
如果是 HTTP 请求太慢,是不是可以把请求的结果缓存到 Memcached 中,这样下次就无需远程的 HTTP 请求,直接从内存中获取即可。
举个具体的例子,一般来说相关文章是通过文章的标签的相关来生成的,这样就需要使用到文章和标签的关联表(wp_term_relationships)和文章表(wp_posts)进行连表查询,根据文章相关度进行排序,我见过一些文章数和标签数多的站点,这样的一条 SQL 查询经常会 5-10 秒,这样的慢查询经常把站点搞挂。
我是怎么优化的呢?放弃连表的,首先获取当前文章的标签,然后从文章和标签的关联表(wp_term_relationships)根据这些标签获取最相关的文章 ID,并且多获取一些,比如要获取5篇,我就至少获取10篇,然后把获取的文章 ID,从文章表(wp_posts)中获取具体的数据,舍弃到那些不符合文章类型和状态的,剩下的就符合要求了,剩下的不够,就继续上述的方法在找一些直至数量够了。这样通过 PHP 脚本进行优化。相关文章造成的性能问题就能得到完美的解决。