提高MySQL查询性能

提高MySQL查询性能,mysql,Mysql,我有下面的查询,它连接了5个与InnoDB相关的表,以获得所需的10行结果集。我尽力通过添加索引和以多种不同方式重新编写查询来解决这个问题,但结果不是意外的,就是查询速度非常慢 这是一个问题 SELECT a.*, c.id as category_id, c.title as catname, CONCAT(u.fname, ' ', u.lname) as username, DATE_FORMAT(a.created, '%W %M %d, %Y

我有下面的查询,它连接了5个与InnoDB相关的表,以获得所需的10行结果集。我尽力通过添加索引和以多种不同方式重新编写查询来解决这个问题,但结果不是意外的,就是查询速度非常慢

这是一个问题

SELECT 
    a.*,
    c.id as category_id,
    c.title as catname,
    CONCAT(u.fname, ' ', u.lname) as username,
    DATE_FORMAT(a.created, '%W %M %d, %Y - %T') as long_date,
    DATE_FORMAT(a.created, '%d/%m/%Y - %T') as short_date,
    (SELECT 
            COUNT(article_id)
        FROM
            comment
        WHERE 
            article_id = a.id) as totalcomments,
    YEAR(a.created) as year,
    MONTH(a.created) as month,
    DAY(a.created) as day
FROM
    article as a
        INNER JOIN
    article_related_categories rc ON a.id = rc.article_id
        LEFT JOIN
    category as c ON c.id = rc.category_id
        LEFT JOIN
    user as u ON u.id = a.user_id
WHERE
    rc.category_id = 1
        AND a.created <= NOW()
        AND (a.expire = '0000-00-00 00:00:00'
        OR a.expire >= NOW())
        AND a.published IS NOT NULL

ORDER BY a.created DESC
LIMIT 0 , 10
目前,文章表中有13000多行,预计将快速增长

问题是,执行此查询可能需要大量时间,大约需要3-4秒。我怀疑大部分问题都是由内部JION引起的,但我想在这里问一下,是否有人对改进此查询的性能有任何想法。

嵌套选择可能会减慢速度。加入注释表并按a.id分组:


好吧,一个快速解决办法就是摆脱这个

    AND a.created <= NOW()

我会在你的桌子上放一个索引

article table index -- ( published, expire, id )
article table index -- ( id ) just the primary key ID for secondary join criteria
article_related_categories table index( article_id, category_id )
comment table (article_id)
然后,让一个预查询什么都不做,只获取ID和文章以及相关数据的计数 10篇文章的兴趣类别、顺序和限制。。。然后加入类别和用户 用于最终输出的表

SELECT
      a2.*,
      c.id as category_id,
      c.title as catname,
      CONCAT(u.fname, ' ', u.lname) as username,
      DATE_FORMAT(a2.created, '%W %M %d, %Y - %T') as long_date,
      DATE_FORMAT(a2.created, '%d/%m/%Y - %T') as short_date,
      PreQual.TotalComments,
      YEAR(a2.created) as year,
      MONTH(a2.created) as month,
      DAY(a2.created) as day
   from 
      ( select 
              a.id,
              rc.category_id,
              COUNT(c.article_id) as TotalComments
           from 
              article a
                 join article_related_categories rc 
                    ON a.id = rc.article_id
                    AND rc.category_id = 1
                 left join comment c
                    ON a.id = c.article_id
           where
                  a.published IS NOT NULL
              AND (    a.expire >= now()
                    OR a.expire = '0000-00-00 00:00:00' )
           group by
              a.id,
              rc.category_id
           order by
              a.created DESC
           limit
              0, 10 ) PreQual
        JOIN article a2
           ON PreQual.ID = a2.id
           LEFT JOIN user u
              ON a2.user_id = u.id
        LEFT JOIN category as c 
           ON PreQual.Category_ID = c.id
现在,即使使用上面的查询,执行它所显示的基于web的活动,以及在相关条件下对整个子集进行计数,也会对性能造成巨大的影响。您最好从一个方面对数据进行反规范化。在文章表中,为CommentCount添加一列。然后,当添加任何新注释时,在插入到注释后有一个触发器,该触发器基本上执行

update Articles
   set CommentCount = CommentCount +1
   where id = the article ID of the new comment ID just inserted.

然后,你再也不用每次都回去数数了。那将是你最好的行动。在创建触发器之前,必须默认所有计数,但这将是计数的一次性相关更新。您只需返回到相关文章类别表,以符合您感兴趣的类别标准。

其中rc.category_id=1您可以从相关类别文件开始,因为您已经将其缩小为一个。希望这是有意义的。从rc.id=x.id上的相关类别rc join x中选择blah,其中rc.category\u id=1
SELECT
      a2.*,
      c.id as category_id,
      c.title as catname,
      CONCAT(u.fname, ' ', u.lname) as username,
      DATE_FORMAT(a2.created, '%W %M %d, %Y - %T') as long_date,
      DATE_FORMAT(a2.created, '%d/%m/%Y - %T') as short_date,
      PreQual.TotalComments,
      YEAR(a2.created) as year,
      MONTH(a2.created) as month,
      DAY(a2.created) as day
   from 
      ( select 
              a.id,
              rc.category_id,
              COUNT(c.article_id) as TotalComments
           from 
              article a
                 join article_related_categories rc 
                    ON a.id = rc.article_id
                    AND rc.category_id = 1
                 left join comment c
                    ON a.id = c.article_id
           where
                  a.published IS NOT NULL
              AND (    a.expire >= now()
                    OR a.expire = '0000-00-00 00:00:00' )
           group by
              a.id,
              rc.category_id
           order by
              a.created DESC
           limit
              0, 10 ) PreQual
        JOIN article a2
           ON PreQual.ID = a2.id
           LEFT JOIN user u
              ON a2.user_id = u.id
        LEFT JOIN category as c 
           ON PreQual.Category_ID = c.id
update Articles
   set CommentCount = CommentCount +1
   where id = the article ID of the new comment ID just inserted.