J'ai récemment développé un site Web pour un client qui est un agent immobilier. Le projet comprend un type de message appelé listing
. Ce type de publication est utilisé pour toutes leurs listes et des informations supplémentaires sont stockées dans la table postmeta
via l'utilisation de Advanced Custom Fields Pro
.
Sur le front-end du site, j'ai développé une barre de filtrage dans laquelle les utilisateurs peuvent sélectionner plusieurs filtres et soumettre le formulaire, qui génère à son tour un WP_Query complexe pour renvoyer les listes correspondantes. Assez simple! Bien que la plupart des recherches fonctionnent parfaitement, certaines plus complexes génèrent une requête SQL qui cache le fil. Lorsque la base de données doit tout effacer, le serveur se bloque jusqu'à ce que quelqu'un tue le processus. Cela se produit sur tous les environnements, pas seulement en production.
Par exemple, voici une requête qui vérifie l'intervalle de prix, les chambres, les salles de bain, que la liste comprend les meubles et l'emplacement (post_id) et le titre du message "1". Ne ressemble pas à une recherche super avancée, n'est-ce pas? (c'est le SQL généré)
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;
En réalité, je n'utilise que TYPE
, KEY
, VALUE
et COMPARE
dans le tableau meta_query
, de sorte qu'il est construit comme il se doit, à l'aide de WordPress, mais il devient pourtant incroyablement lent. Lorsque cela se produit, les demandes s'accumulent jusqu'à ce que l'ensemble du site ne réponde plus.
Il y a plusieurs options:
\WP_Query
.Recommandations: