小さなイノベーションの連続が未来を創る

ソナーリズム株式会社

wordpress カスタマイズ システム開発

wordpress の投稿ループ内で使用されている post_class 関数の遅さに悩んでいたのでクエリで書き換えた話

更新日:

どんなシステムを wordpress で制作したのですか

LMS(学習プラットフォーム)系のシステムにおいて全てのコースを関連する情報も含めて表示して絞り込みをするというなかなか挑戦的な事例に取り組みました。
400くらいの投稿を一気に表示させる、しかも今後増える・・・という状況において、Wordpress の投稿ループを普通に回していると15秒とかありえない時間が表示にかかっていました。
レッスン、コース、クイズなどなど、全て別々の投稿タイプが複雑に絡み合い、その上にクラスもカテゴリやタグなどたくさんぶら下がっている状態。
ループ内で一つ一つビルドすると、クエリの数がなんと!! 2000本を軽く超え収集つかない状況に。
これは遅い。普通の状態では使えない。

であればクエリを独自に書いて、キャッシュをすれば良いのだ!という結論に至りました。今回はその一部をこちらにて共有させて頂きます。

そうだ! MySQL の必要な情報だけを取れる様に SQL でクエリを書こう!

WordPress には MySQL に直接アクセスする機構も用意されています。具体的な方法は調べれば出てくるのでここでは省略します。
ここでも色々と実験を行いました。投稿のクエリ、レッスンのクエリ、動画のクエリ、色々書いて
アクセスするユーザーが常に必要で共有される情報はキャッシュを使う(またいつか書きます)
順調に 6〜8秒までの短縮には成功しました。

あとは・・なんだ・・・
これ以上速くできるのか?

wordpress の post_class 関数遅いよ

この関数の内容を見ていたら、

  • カテゴリを見て category- を追加してクラスとして使う。
  • タグを見て post_tagとなっているのを tag- にしてクラスとして使う。
  • その他いろいろな属性からクラス値を拾ってくる

となっており(ざっくり)
最終的にループ内で書き出す。
つまり、ループの数だけ DBアクセスとクラスリストの構築が繰り返されるという仕様でした。

詳細は Codex 参照

wordpress の post_class 関数のどこがいけないの?

おすすめ投稿を5個表示したい!とかであれば、この方法で良いので、ほとんどのサイトでは問題なく動作します。
しかし、一度に構築する投稿数が 400以上ともなるとそうもいきません。

数が増えれば増えるほど重たくなるのは避けられず、これが終わるまで描画もされないので、
画面はくるくる回り続け(そういう処理がしてあれば・・)コーヒーがいっぱい飲めてしまうなんてことになりかねない。

これでは、せっかくお客さんになってくれた人たちも逃げていく・・・
どうしたものか。

post_class 関数の内容って SQL クエリで書けないのだろうか?

今回は400以上の投稿を JavaScript を使ってフロントエンドでフィルターするというものがあり、クラスと言いますか投稿にフィルターのキーになる情報をつけておけば良いという要件でした。
つまり、必要なものがあれば良い。その必要なものは、カテゴリとタグのスラッグが、カテゴリなのか、タグなのかも含めて判別できれば良いので、それだけを投稿IDと紐づけられる様にすれば解決です。
投稿ブジェクトもどき(上記クエリで作ったもの)にくっつけても良いのですが、

  • こちらの JOIN がすでに3つほどあり、すでに複雑すぎる
  • 後からクラスだけ取得して何かしたいかもしれない

という事情もありましたので、切り分けて PHP 側で制御することにしました。

SQL 実装内容

[code language="plain"]SELECT
t.object_id AS ID,
GROUP_CONCAT(DISTINCT d.term_info SEPARATOR ' ') AS post_class
FROM wp_term_relationships t
LEFT JOIN (
SELECT
tt.term_taxonomy_id,
REPLACE(
CONCAT_WS('-', tt.taxonomy, dd.slug) ,
'post_',
'') AS term_info
FROM wp_term_taxonomy tt
LEFT JOIN wp_terms dd
ON tt.term_id = dd.term_id
) d
ON t.term_taxonomy_id = d.term_taxonomy_id
GROUP BY t.object_id
[/code]

これを実行すれば ID とカテゴリ、タグのクラスが紐づけられた結果が返されます。

[code language="plain"]D | category-hogehoge tag-fugafuga
ID | category-hoge tag-hoge
[/code]

クラスの指定でそのまま使える様な文字列連結も完了しております。
CONCAT, GROUP_CONCAT, REPLACE という関数がポイントですね。

結果発表 「post_class 関数を削除して SQL クエリで WordPress サイトを高速化する」

なんと!!!

2秒!!!

まで短縮しました。
15秒 > 2秒 約13秒ほどの短縮です!!

これなら耐えられますね。
快適すぎて満足いく結果になりました。

WordPress もチューニング次第で色々と面白いことができますね。
もちろん SQL や PHP の知識、サーバーの知識などは必要になってきますので、ご自身では難しいという方は一度ご相談いただけましたら幸いです。

オススメ記事

-wordpress カスタマイズ, システム開発
-, , , , , , , ,

Copyright© ソナーリズム株式会社 , 2018 All Rights Reserved Powered by AFFINGER5.

X