高级WP查询占用了SQL服务器

时间:2018-08-28 作者:Jonathan

我最近为一位房地产经纪人的客户开发了一个网站。项目中包含一个名为listing. 此帖子类型用于他们的所有列表,其他信息存储在postmeta 表通过使用Advanced Custom Fields Pro.

在网站的前端,我开发了一个过滤栏,用户可以通过几个过滤器进行选择并提交表单,然后生成一个复杂的WP\\u查询以返回匹配的列表。很简单!虽然大多数搜索都工作得很好,但一些更复杂的搜索将生成占用线程的SQL查询。当数据库需要刷新堆积的所有内容时,服务器基本上会冻结,直到有人终止进程。这在所有环境中都会发生,而不仅仅是在生产环境中。

例如,这里有一个查询,用于检查价格区间、卧室、浴室、列表是否包括家具、位置(post\\u 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;
我真的只使用TYPE, KEY, VALUECOMPAREmeta_query 数组,所以它的构建应该使用WordPress,但它变得极其缓慢。当这种情况发生时,请求将不断增加,直到整个站点没有响应为止。

1 个回复
最合适的回答,由SO网友:kaiser 整理而成

有几种选择:

使用一些基于Lucene的搜索索引并将查询缓存在那里。使用大量RAM为其供电,这样在第一次查询后,就不会有任何东西击中您的DB。使用类似于Elasticsearch的工具,不要试图运行Lucene plain…你会发现自己身处地狱。没有人这样做是有充分理由的

    • 重写查询并使用原始查询,而不是\\WP_Query.
    • 使用Memcached(meh)…或Redis(更好,因为您可以对其进行群集,并且它可以通过负载平衡安装进行更好的配置。)

      • 记录慢速查询

  • 结束

    相关推荐

    如何从SQL文件中获取WordPress密码?

    如何从SQL文件中获取wordpress密码?我遇到了一些问题,因为一个用户没有留下他们的密码,而且它位于一个没有PHPmyadmin或其他服务的虚拟服务器上,因为它不是我的,我无法安装其他任何东西,所以我只保留了一个SQL文件。我已经尝试使用忘记的密码,但不是我的服务器不会发送电子邮件。我知道我的密码有MD5加密,它使用唯一的哈希来生成密码,所以我想知道是否可以生成新密码或恢复以前的密码,或者至少直接在SQL文件中插入新用户。数据如下:INSERT INTO `dexim_users` VALUES&#