web-dev-qa-db-ja.com

30 000件の投稿があるWordPressブログ:低い検索パフォーマンス

WordPressのブログは、約3万件の投稿をインポートするまでは問題なく動作していました。その後、Webサイトの検索は非常に遅くなりました。

今それはかかります:
- 検索とフィルタウィジェットが表示されたページを4秒間ロードします。
- 検索結果を返すまで18秒。

私たちが使用する主なプラグイン:
カスタム投稿タイプ - ブログで使用されているカスタム投稿タイプは1つだけです。
高度なカスタムフィールド - 検索可能かつフィルタ可能な一連のカスタムフィールドがあります。

私たちが使用している検索プラグイン:
すべて検索 - タグ、著者、コメントが検索可能になりました。投稿コンテンツ、タイトル、カスタムフィールドはデフォルトで検索可能です。
Search&Filter Pro - 検索およびフィルタウィジェットを作成し、フィルタルールを設定するために使用されます。

キャッシング:
WPのプラガブルキャッシュおよび永続キャッシュソリューションとして Memcache を使用しています。

環境:
物理サーバー:AWS t2.small; 2 GBのメモリ。最大3.3 GHzのCPU 1コア
OS:Windows Server 2012
ウェブサーバー:IIS 8.5
PHP 5.6.22
Wordpress 4.6.1 MySQL 5.6.27(専用RDSインスタンス)

ユーザー数はかなり限られており、アプリケーションサーバーとデータベースサーバーの両方でサーバーリソースの使用量が大幅に急増することはありません。

これは、ユーザーがWebサイトで検索を実行したときに実行される、実行時間が最も長いSQLクエリです。

SELECT SQL_CALC_FOUND_ROWS distinct wp_posts.ID
FROM   wp_posts
       LEFT JOIN wp_postmeta
              ON wp_posts.id = wp_postmeta.post_id
       LEFT JOIN wp_term_relationships AS trel
              ON ( wp_posts.id = trel.object_id )
       LEFT JOIN wp_term_taxonomy AS ttax
              ON ( ( ttax.taxonomy = 'post_tag' )
                   AND trel.term_taxonomy_id = ttax.term_taxonomy_id )
       LEFT JOIN wp_terms AS tter
              ON ( ttax.term_id = tter.term_id )
       LEFT JOIN wp_comments AS cmt
              ON ( cmt.comment_post_id = wp_posts.id )
       LEFT JOIN wp_users AS u
              ON ( wp_posts.post_author = u.id )
WHERE  1 = 1
       AND ( ( wp_posts.id IN (<LIST_OF_POST_IDS>)
               AND (( (( ( wp_posts.post_title LIKE '%searchterm%' )
                          OR ( wp_postmeta.meta_value LIKE '%searchterm%' )
                          OR ( wp_posts.post_content LIKE '%searchterm%' ) ))
                       OR (( tter.name LIKE '%searchterm%' ))
                       OR ( (( cmt.comment_content LIKE '%searchterm%' ))
                            AND cmt.comment_approved = '1' )
                       OR (( u.display_name LIKE '%searchterm%' )) ))
               AND wp_posts.post_type = 'generalpost'
               AND (( wp_posts.post_status = 'publish' )) )
             AND post_type != 'revision' )
       AND post_status != 'future'
ORDER  BY wp_posts.post_date DESC
LIMIT  0, 15;

スキーマリファレンスについては Wordpress DBのドキュメント をご覧ください。

このクエリは、検索結果ページの読み込み時間の約65%(18秒のうち12秒)を担当します。

現時点では1つのカスタム投稿タイプしかありませんが、それが検索可能である必要があるだけです。各カスタム投稿タイプには、wp_postmeta内に18のレコードがあります。これら18のフィールドのうち4つだけが検索可能である必要があります - そしてそれは検索をスピードアップするための1つの潜在的な方法です。

私のテストではこの句を追加しています

`AND meta_key in ('cust_field1', 'cust_field2', 'cust_field3', 'cust_field4',)`

実際にはクエリをほぼ2倍高速化しました。プラグイン開発者は、メタフィールドの除外をサポートする機能を実装するために連絡を取りました。

また、post_id、meta_key、meta_value列に複合インデックスを作成しました。これにより、クエリ時間がさらに5〜10%短縮されました。

ユーザーエクスペリエンスが損なわれないように、この量のデータで検索をより効率的にするための他の方法は何ですか?

7
slav_gcm

インデックスが追加され、クエリが調整されているので、すでに正しい方向に進んでいるようです。私は MySQLのEXPLAIN構文が役に立つことを発見しました 、クエリ内のどこに問題があるのか​​をよく理解してくれました。

大まかに言うと、クエリには結合テーブル、LIKE比較(ワイルドカードを含む)、およびOR比較子が多数含まれているようです。これらはすべて、パフォーマンスが低下する可能性があるクエリの症状です。私はそれらの各列が適切に索引付けされていることを確認し(特に、通常は照会されていないものは特に)、そこで何かを見逃していないかどうかを確認します。

データベース全体のサイズは、環境によっては要因になることがあります。ある時点で、クライアントサイトがパフォーマンスの低下を訴えていた(検索だけではなく)、データベースの約20%がポストリビジョンで構成されているという事実に基づいてインデックスが詰まっていることがわかりました6か月前の投稿にはあまり意味がありませんでした)。 Revision Strike はその必要性から生まれたもので、検索サイトのパフォーマンスだけでなく全般にも大きな影響を与えました。

考慮すべきもう1つの選択肢は、より専用の検索テクノロジに基づくものです。 ElasticPress (完全な開示:私は10up、ElasticPressのメンテナとして働いています)ElasticsearchをWordPressクエリに結び付け、あなたのWebサーバーの負荷を大幅に減らしながら、より複雑な検索を可能にします。検索プラグイン).

1
Steve Grunwell