简体   繁体   English

对 meta_query 使用 NOT EXISTS 时 Wordpress 慢查询

[英]Wordpress slow query when using NOT EXISTS for meta_query

I am running a query on a relatively small database (10,000 rows in wp_posts and 100,000 rows in wp_postmets) but for some reason the query takes around ~5 to 7 seconds to execute.我在一个相对较小的数据库(wp_posts 中的 10,000 行和 wp_postmets 中的 100,000 行)上运行查询,但由于某种原因,查询需要大约 5 到 7 秒才能执行。

The args I'm passing into wp_query are;我传递给 wp_query 的参数是;

Array(
   [post_type] => post
   [post_status] => publish
   [ignore_sticky_posts] => 0
   [posts_per_page] => 1
   [orderby] => rand
   [meta_key] => 
   [meta_value] => 
   [order] => DESC
   [offset] => 0
   [post__not_in] => Array
       (
       )

   [author__in] => Array
       (
       )

   [tax_query] => Array
       (
           [relation] => AND
           [0] => Array
               (
                   [taxonomy] => category
                   [field] => slug
                   [terms] => Array
                       (
                           [0] => beauty
                       )

                   [operator] => IN
                   [include_children] => 0
               )

       )

   [meta_query] => Array
       (
           [relation] => OR
           [0] => Array
               (
                   [key] => sponsored
                   [value] => 1
                   [compare] => !=
                   [type] => CHAR
               )

           [1] => Array
               (
                   [key] => sponsored
                   [value] => 
                   [compare] => NOT EXISTS
                   [type] => CHAR
               )

       )

)

And the SQL query it runs is;它运行的 SQL 查询是;

SELECT SQL_CALC_FOUND_ROWS wp_posts.id
FROM   wp_posts
       LEFT JOIN wp_term_relationships
              ON ( wp_posts.id = wp_term_relationships.object_id )
       LEFT JOIN wp_postmeta
              ON ( wp_posts.id = wp_postmeta.post_id )
       LEFT JOIN wp_postmeta AS mt1
              ON ( wp_posts.id = mt1.post_id
                   AND mt1.meta_key = 'sponsored' )
WHERE  1 = 1
       AND ( wp_term_relationships.term_taxonomy_id IN ( 3 ) )
       AND ( ( wp_postmeta.meta_key = 'sponsored'
               AND wp_postmeta.meta_value != '1' )
              OR mt1.post_id IS NULL )
       AND wp_posts.post_type = 'post'
       AND (( wp_posts.post_status = 'publish' ))
GROUP  BY wp_posts.id
ORDER  BY Rand()
LIMIT  0, 1

I have noticed that the long-query issue resolves itself when I remove this part;我注意到,当我删除这部分时,长查询问题会自行解决;

Array(
   [key] => sponsored
   [value] => 
   [compare] => NOT EXISTS
   [type] => CHAR
)

Which in the SQL query is; SQL查询中的哪个是;

OR mt1.post_id IS NULL

What I am trying to do is look for articles that are marked as sponsored == 0 or where they're not marked as both sponsored or not-sponsored (sponsored meta_key doesn't exist).我要做的是查找标记为sponsored == 0或未标记为赞助或非赞助的文章(赞助的meta_key 不存在)。

Can someone please point out to me/help me with how I can achieve the same results with a more efficient query/wp_query?有人可以向我指出/帮助我如何通过更有效的查询/wp_query 获得相同的结果吗? Or if you can give me an idea around why OR mt1.post_id IS NULL makes the query run for ~5 to 7 seconds whereas without it the query takes ~20 milliseconds?或者,如果您可以告诉我为什么OR mt1.post_id IS NULL会使查询运行约 5 到 7 秒,而没有它,查询需要约 20 毫秒?

Rethink how you specify "is sponsored".重新考虑如何指定“被赞助”。 You currently have你目前有

    LEFT JOIN  wp_postmeta  ON ( wp_posts.id = wp_postmeta.post_id )
    LEFT JOIN  wp_postmeta AS mt1  ON ( wp_posts.id = mt1.post_id
              AND  mt1.meta_key = 'sponsored' 
                          )
    WHERE  ( ( wp_postmeta.meta_key = 'sponsored'
                      AND  wp_postmeta.meta_value != '1' )
              OR  mt1.post_id IS NULL 
           )

This might be simpler to get rid of those 2 JOINs and change that part of WHERE to这可能更容易摆脱这两个 JOIN 并将 WHERE 的那部分更改为

    WHERE NOT EXISTS( SELECT 1 FROM wp_postmeta AS m
                WHERE m.post_id = wp_posts.id
                  AND m.meta_key = 'sponsored'
                  AND m.meta_value = '1' )

And, be sure to have WP Index Improvements .而且,一定要有WP Index Improvements It will add an index that will help that subquery.它将添加一个有助于该子查询的索引。

I can't be sure, but I think that this is unnecessary (and leads to an extra sort of the intermediate results):我不能确定,但​​我认为这是不必要的(并导致额外的中间结果):

    GROUP BY  wp_posts.id

RAND and SQL_CALC_FOUND_ROWS both necessitate finding all the rows with term taxonomy 3. Please provide EXPLAIN SELECT ... so we can discuss whether it is unnecessarily looking at all posts, not just the taxonomy 3 posts. RANDSQL_CALC_FOUND_ROWS都需要查找具有术语分类 3 的所有行。请提供EXPLAIN SELECT ...以便我们可以讨论是否不必要地查看所有帖子,而不仅仅是分类 3 帖子。 (That may lead to an optimization.) (这可能会导致优化。)

It's unfortunate that WP does not facilitate putting the sponsored and taxonomy flags in wp_posts.不幸的是,WP 不便于将赞助和分类标志放在 wp_posts 中。 Then, a composite index would lead to a much faster query.然后,复合索引将导致更快的查询。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM