簡體   English   中英

對 meta_query 使用 NOT EXISTS 時 Wordpress 慢查詢

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

我在一個相對較小的數據庫(wp_posts 中的 10,000 行和 wp_postmets 中的 100,000 行)上運行查詢,但由於某種原因,查詢需要大約 5 到 7 秒才能執行。

我傳遞給 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
               )

       )

)

它運行的 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

我注意到,當我刪除這部分時,長查詢問題會自行解決;

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

SQL查詢中的哪個是;

OR mt1.post_id IS NULL

我要做的是查找標記為sponsored == 0或未標記為贊助或非贊助的文章(贊助的meta_key 不存在)。

有人可以向我指出/幫助我如何通過更有效的查詢/wp_query 獲得相同的結果嗎? 或者,如果您可以告訴我為什么OR mt1.post_id IS NULL會使查詢運行約 5 到 7 秒,而沒有它,查詢需要約 20 毫秒?

重新考慮如何指定“被贊助”。 你目前有

    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 
           )

這可能更容易擺脫這兩個 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' )

而且,一定要有WP Index Improvements 它將添加一個有助於該子查詢的索引。

我不能確定,但​​我認為這是不必要的(並導致額外的中間結果):

    GROUP BY  wp_posts.id

RANDSQL_CALC_FOUND_ROWS都需要查找具有術語分類 3 的所有行。請提供EXPLAIN SELECT ...以便我們可以討論是否不必要地查看所有帖子,而不僅僅是分類 3 帖子。 (這可能會導致優化。)

不幸的是,WP 不便於將贊助和分類標志放在 wp_posts 中。 然后,復合索引將導致更快的查詢。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM