WordPress主题中MySQL Select语句的改进



我正在使用Industrialthemes的WordPress主题引擎,并看到首页的呈现使用了大量查询,在我的MySQL数据库中运行大约需要0.4秒。像这个:

SELECT SQL_NO_CACHE SQL_CALC_FOUND_ROWS wp_posts.ID
FROM wp_posts
INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id)
WHERE 1 =1
  AND (wp_term_relationships.term_taxonomy_id IN (1))
  AND wp_posts.post_type = 'post'
  AND (wp_posts.post_status = 'publish'
       OR wp_posts.post_status = 'closed')
GROUP BY wp_posts.ID
ORDER BY wp_posts.post_date DESC 
LIMIT 0,  5;

有什么方法可以改进这个查询吗?据我所见,WordPress安装为所有涉及的字段都设置了默认索引。我在调优SQL Select语句方面的知识并不好,所以我希望一些专家能在这方面帮助我。谢谢

(来自评论(

CREATE TABLE wp_term_relationships (
    object_id bigint(20) unsigned NOT NULL DEFAULT '0', 
    term_taxonomy_id bigint(20) unsigned NOT NULL DEFAULT '0', 
    term_order int(11) NOT NULL DEFAULT '0', 
    PRIMARY KEY (object_id,term_taxonomy_id), 
    KEY term_taxonomy_id (term_taxonomy_id), 
    KEY idx1 (object_id)
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

(稍后…(

CREATE TABLE wp_term_relationships (
    object_id bigint(20) unsigned NOT NULL DEFAULT '0', 
    term_taxonomy_id bigint(20) unsigned NOT NULL DEFAULT '0', 
    term_order int(11) NOT NULL DEFAULT '0', 
    PRIMARY KEY (object_id,term_taxonomy_id), 
    KEY term_taxonomy_id (term_taxonomy_id), 
    KEY idx1 (term_taxonomy_id,object_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
wp_term_relationships needs INDEX(term_taxonomy_id, object_id) -- in this order
wp_posts might benefit from INDEX(post_type, ID, post_status, post_date) -- in this order

两者都是"覆盖"指数
前者使JOIN有效地工作为优化器提供了从wp_term_relationships开始的选项。它应该取代KEY term_taxonomy_id (term_taxonomy_id)
无论先选择哪一张表,后者都应该能很好地工作。

(更多(

SELECT  SQL_NO_CACHE SQL_CALC_FOUND_ROWS p.ID
    FROM  wp_posts AS p
     WHERE p.post_type = 'post'
      AND  p.post_status IN ( 'publish', 'closed' )
      AND EXISTS ( SELECT 1 FROM wp_term_relationships AS tr
                     WHERE p.ID = tr.object_id
                       AND tr.term_taxonomy_id IN (1) )
    ORDER BY  p.post_date DESC
    LIMIT  0, 5;

使用这种配方,

如果EXPLAIN以p:开头

p:  (post_date, post_type, post_status, ID)
p:  (post_type, post_status, ID, post_date)
tr:  (object_id, term_taxonomy_id)  -- which you have

如果EXPLAIN以tr:开头

p:  (ID)  -- which you probably have
tr:  (term_taxonomy_id, object_id)

主要问题:

  • GROUP BY正在加大力度。(我通过将JOIN更改为EXISTS来消除它。(
  • IN ( 'publish', 'closed' )——抑制指标的有效使用
  • SQL_CALC_FOUND_ROWS——意味着当它得到5行时不能停止
  • IN (1)变成= 1,这是好的;但CCD_ 11更混乱

或者,更直白地说,WP还没有被设计成规模。

请添加索引并获得EXPLAIN SELECT

来自pastebin:

SELECT  SQL_NO_CACHE p.ID
    FROM  wp_posts AS p
    WHERE  p.post_type = 'post'
      AND  p.post_status = 'publish'
      AND  EXISTS 
    (
        SELECT  1
            FROM  wp_term_relationships AS tr
            WHERE  p.ID = tr.object_id
              AND  EXISTS 
            (
                SELECT  1
                    from  wp_term_taxonomy AS tt
                    WHERE  tr.term_taxonomy_id = tt.term_taxonomy_id
                      AND  tt.taxonomy = 'post_tag'
                      AND  tt.term_id IN (548, 669) ) 
    );

这是一个不同的查询。它还需要这个:

tt:  INDEX(term_taxonomy_id, taxonomy,  -- in either order
           term_id)   -- last

而且。。。

SELECT  SQL_NO_CACHE wp_posts.ID
    FROM  wp_posts
    INNER JOIN  wp_term_relationships tr 
           ON (wp_posts.ID = tr.object_id)
    INNER JOIN  wp_term_taxonomy tt
           ON (tr.term_taxonomy_id = tt.term_taxonomy_id)
    WHERE  ( post_type = 'post'
              AND  post_status = 'publish'
              AND  tt.taxonomy = 'post_tag'
              AND  tt.term_id IN (548, 669)  
           )
    GROUP BY  wp_posts.ID;

需要

tt:  INDEX(taxonomy, term_id, term_taxonomy_id)  -- in this order

我将把这两个索引都添加到tt中,看看EXPLAINs和性能会发生什么变化。

重写查询查看这是否给出了"正确"答案:

SELECT  p.ID, p.post_name, p.post_title,
        p.post_type, p.post_status,
        tt.term_id as termid, tt.taxonomy
    FROM  wp_posts AS p
    INNER JOIN  wp_term_relationships tr  ON (p.ID = tr.object_id)
    INNER JOIN  wp_term_taxonomy tt  ON (tr.term_taxonomy_id = tt.term_taxonomy_id)
    WHERE  p.post_type = 'post'
      AND  p.post_status = 'publish'
      AND  tt.taxonomy = 'post_tag'
      AND  tt.term_id IN (548, 669)
    ORDER BY  p.ID;

注:

  • GROUP BY已删除
  • AND/OR可能没有按预期工作:a AND b OR c相当于(a AND b) OR c,但我认为您想要a AND (b OR c)
  • 你添加了推荐的索引了吗

相关内容

  • 没有找到相关文章

最新更新