WooCommerce メンバーのクエリ速度を向上させるためのヒント: MySQL インデックスを最適化する
P粉333186285
2023-08-26 11:09:08
<p>Teams for WooCommerce メンバーシップ拡張機能を使用して、WooCommerce メンバーシップ ベースの Web サイトを運営しています。巨大なユーザー ベース (ユーザー数 70,000 人以上) があるにもかかわらず、95% の確率で非常に優れたパフォーマンスを発揮します。 1 日あたり約 10,000 件のアクセスがあり、応答時間は 1 秒未満です。 </p>
<p>ユーザーがトレーニングを完了する必要があるピークシーズンには、キャッシュされていない同時リクエストの負荷によりサイトがクラッシュする可能性があります。 </p>
<p>クエリ モニター ツールを使用すると、0.0375 秒 (平均 0.0050 秒未満) という 1 つのクエリが注目されました。このクエリは次のことをチェックします: </p>
<ol>
<li><p>現在のユーザーは、アクティブなサブスクリプションを持つチームのメンバーですか? </p>
</li>
<li><p>この記事を閲覧する許可はありますか? </p>
</li>
</ol>
<p>クエリ自体は次のとおりです: </p>
<pre class="brush:php;toolbar:false;">SELECT wp_posts.*
wp_posts から
左結合 wp_postmeta _teams_pm
ON wp_posts.ID = _teams_pm.post_id
かつ _teams_pm.meta_key = '_member_id'
AND _teams_pm.meta_value = 2
左結合 wp_usermeta_teams_um
オン _teams_um.user_id = _teams_pm.meta_value
AND _teams_um.meta_key = CONCAT( '_wc_memberships_for_teams_team_', wp_posts.ID, '_role' )
ここで 1=1
AND ((wp_posts.post_type = 'wc_memberships_team'
AND (wp_posts.post_status = '公開'
または wp_posts.post_status = 'acf-disabled'
または wp_posts.post_status = 'プライベート')))
AND (_teams_um.meta_value IN('マネージャー', 'メンバー')
または wp_posts.post_author = 2 )
wp_posts.post_date DESC</pre> で注文
<p>これは次のように呼び出されます: </p>
<pre class="brush:php;toolbar:false;">"WP_Query->get_posts()
wp-includes/class-wp-query.php:3111
WP_Query->query()
wp-includes/class-wp-query.php:3542
WP_Query->__construct()
wp-includes/class-wp-query.php:3653
SkyVergeWMTTeams_Handler->get_teams()
wp-content/plugins/woocommerce-memberships-for-teams/src/Teams_Handler.php:446
wc_memberships_for_teams_get_teams()
wp-content/plugins/woocommerce-memberships-for-teams/src/Functions/Teams.php:100
ctz_membership_get_user_team_id()
wp-content/plugins/core-functionity/temp/wc_teams.php:603"</pre>
<p>このクエリを高速化するためのインデックス作成について何かアイデアを持っている人はいますか?私は SQL にあまり詳しくないので、最適なインデックス配置がどこにあるのかを知ることができません。 </p>
<p>月曜日には大幅な急増が予想されているので、サイトが静かになる今週末に備えておきたいと思います。</p>
<p>よろしくお願いします! </p>
<p>編集: 匿名化された Explain、プレフィックス、およびデータベース名の出力: </p>
<pre class="brush:php;toolbar:false;"> ---- ------------- --------------- - ---------- ------- ----------------------------- -- ---------------- -------------------------------------- --------------------- ------ ---------- ------------- ------------------------
| id | select_type | テーブル | パーティション | タイプ | possible_keys | キー | key_len | ref | 行 | フィルター | 追加 |
---- ------------- --------------- ------------ ------ ------------------------------ ------------------ - - -------------------------------------------------- -- ---- ------ ---------- ---------------------------- --- ----------
| 1 | SIMPLE | wp_posts | NULL | range | type_status_date,post_author | type_status_date | 164 | NULL | 5556 | 100.00 | インデックス条件を使用する; filesort を使用する |
| 1 | SIMPLE | _teams_pm | NULL | ref | PRIMARY,meta_key,meta_value | PRIMARY | 1030 | dbname.wp_posts.ID,const | 1 | 100.00 | where の使用 |
| 1 | SIMPLE | _teams_um | NULL | ref | PRIMARY,meta_key | PRIMARY | 1030 | dbname._teams_pm.meta_value,func | 1 | 100.00 | where の使用 |
---- ------------- --------------- ------------ ------ ------------------------------ ------------------ - - -------------------------------------------------- -- ---- ------ ---------- ---------------------------- --- ----------
セットに 3 行、警告 4 回 (0.00 秒)</pre>
<p><br /></p>
そのプラグインはいくつかのクエリに役立つはずです。
これは役に立つかもしれません
リーリーwp_posts
テーブルに複数のインデックスがあることに関しては...クエリが異なれば、異なるインデックスが必要になります。 MySQL は、テーブル参照ごとに 1 つのインデックスのみを使用します (まれな例外を除きます)。実際にはクエリ内に 3 つのクエリがあり、1 つは投稿用、2 つは postmeta 用です。
あなたが提供した
EXPLAIN
は矛盾しているようです。何が起こっているのかを理解できるように (そしてオリバーの質問にもっとよく答えられるように)、両方のテーブルのSHOW CREATE TABLE
を提供してください。INDEX
内の列の順序は重要ですが、WHERE
句内の順序は重要ではありません。クエリには問題のある箇所が 2 つあります。これらを避けると、CONCAT と
OR
というパフォーマンスが向上する可能性があります。これはOR
:リーリー
インデックスは役に立ちません。ただし、アプリケーションの要件により改善できない場合があります。