私は最近不動産業者である顧客のためのウェブサイトを開発しました。このプロジェクトに含まれているのはlisting
という投稿タイプです。この投稿タイプはすべてのリストに使用され、追加情報はAdvanced Custom Fields Pro
を使用してpostmeta
テーブルに格納されます。
サイトのフロントエンドで、私はユーザーがいくつかのフィルターを通して選択してフォームを送信することができるフィルターバーを開発しました。そしてそれは順番にマッチするリストを返すために複雑なWP_Queryを生成します。とてもシンプル!ほとんどの検索は完璧に機能しますが、より複雑な検索ではスレッドを占有するSQLクエリが生成されます。データベースがすべてをフラッシュする必要があるとき、誰かがプロセスを殺すまでサーバーは本質的にフリーズします。これは本番環境だけでなく、すべての環境で発生します。
たとえば、価格、寝室、浴室の間隔、リストに家具、どの場所(post_id)、および投稿タイトル "1"が含まれているかを確認するクエリがあります。超高度な検索のように聞こえないでしょうか。 (これは生成されたSQLです)
SELECT DISTINCT 4x5LbPZ_posts.* FROM 4x5LbPZ_posts LEFT JOIN 4x5LbPZ_term_relationships ON (4x5LbPZ_posts.ID = 4x5LbPZ_term_relationships.object_id) INNER JOIN 4x5LbPZ_postmeta ON ( 4x5LbPZ_posts.ID = 4x5LbPZ_postmeta.post_id ) INNER JOIN 4x5LbPZ_postmeta AS mt1 ON ( 4x5LbPZ_posts.ID = mt1.post_id ) INNER JOIN 4x5LbPZ_postmeta AS mt2 ON ( 4x5LbPZ_posts.ID = mt2.post_id ) INNER JOIN 4x5LbPZ_postmeta AS mt3 ON ( 4x5LbPZ_posts.ID = mt3.post_id ) INNER JOIN 4x5LbPZ_postmeta AS mt4 ON ( 4x5LbPZ_posts.ID = mt4.post_id ) INNER JOIN 4x5LbPZ_postmeta AS mt5 ON ( 4x5LbPZ_posts.ID = mt5.post_id ) INNER JOIN 4x5LbPZ_postmeta AS mt6 ON ( 4x5LbPZ_posts.ID = mt6.post_id ) INNER JOIN 4x5LbPZ_postmeta AS mt7 ON ( 4x5LbPZ_posts.ID = mt7.post_id ) INNER JOIN 4x5LbPZ_postmeta AS mt8 ON ( 4x5LbPZ_posts.ID = mt8.post_id ) INNER JOIN 4x5LbPZ_postmeta AS mt9 ON ( 4x5LbPZ_posts.ID = mt9.post_id ) LEFT JOIN 4x5LbPZ_term_relationships AS trel ON (4x5LbPZ_posts.ID = trel.object_id) LEFT JOIN 4x5LbPZ_term_taxonomy AS ttax ON ( ( ttax.taxonomy = 'category' ) AND trel.term_taxonomy_id = ttax.term_taxonomy_id) LEFT JOIN 4x5LbPZ_terms AS tter ON (ttax.term_id = tter.term_id) LEFT JOIN 4x5LbPZ_postmeta AS m ON (4x5LbPZ_posts.ID = m.post_id) WHERE 1=1 AND ( ( (
4x5LbPZ_term_relationships.term_taxonomy_id IN (3)
) AND (((((4x5LbPZ_posts.post_title LIKE '%1%') OR (4x5LbPZ_posts.post_content LIKE '%1%'))) OR ((tter.slug LIKE '%1%')) OR ((ttax.description LIKE '%1%')) OR ((m.meta_value LIKE '%1%')) )) AND (
( 4x5LbPZ_postmeta.meta_key = 'listing_status' AND 4x5LbPZ_postmeta.meta_value NOT IN ('pending') )
AND
( mt1.meta_key = 'listing_status' AND mt1.meta_value IN ('for_sale') )
AND
( mt2.meta_key = 'listing_price' AND CAST(mt2.meta_value AS SIGNED) >= '0' )
AND
( mt3.meta_key = 'listing_price' AND CAST(mt3.meta_value AS SIGNED) <= '7500000' )
AND
( mt4.meta_key = 'listing_bedrooms' AND CAST(mt4.meta_value AS SIGNED) >= '0' )
AND
( mt5.meta_key = 'listing_bedrooms' AND CAST(mt5.meta_value AS SIGNED) <= '36' )
AND
( mt6.meta_key = 'listing_bathrooms' AND CAST(mt6.meta_value AS SIGNED) >= '0' )
AND
( mt7.meta_key = 'listing_bathrooms' AND CAST(mt7.meta_value AS SIGNED) <= '7' )
AND
( mt8.meta_key = 'listing_furniture' AND mt8.meta_value = 'true' )
AND
( mt9.meta_key = 'listing_location' AND mt9.meta_value = '80' )
) AND 4x5LbPZ_posts.post_type = 'listing' AND (4x5LbPZ_posts.post_status = 'publish' OR 4x5LbPZ_posts.post_status = 'acf-disabled')) AND post_type != 'revision') AND post_status != 'future' GROUP BY 4x5LbPZ_posts.ID ORDER BY 4x5LbPZ_posts.post_date DESC;
meta_query
配列には、実際にはTYPE
、KEY
、VALUE
、COMPARE
しか使用していないので、WordPressを使用するようにビルドすることができますが、それでも計算が遅くなります。これが発生すると、サイト全体が応答しなくなるまで要求が蓄積されます。
いくつかの選択肢があります。
\WP_Query
の代わりに生のクエリを使用します。お勧め: