mySQL-如何解释解释结果并优化此查询?

mySQL-如何解释解释结果并优化此查询?,mysql,optimization,query-optimization,explain,Mysql,Optimization,Query Optimization,Explain,希望了解我的EXPLAIN结果在这里的含义,并尽可能优化此查询和我的表 查询: SELECT i.pending, i.itemid, i.message, i.cid, i.dateadded, i.entrypoint, SUM(CASE WHEN v.direction = 1 THEN 1 WHEN v.direction = 2 THEN -1

希望了解我的
EXPLAIN
结果在这里的含义,并尽可能优化此查询和我的表

查询:

SELECT i.pending,
       i.itemid, 
       i.message,
       i.cid, 
       i.dateadded, 
       i.entrypoint,  
       SUM(CASE WHEN v.direction = 1 THEN 1
                     WHEN v.direction = 2 THEN -1
                     ELSE 0 END) AS votes,
       c.name AS cname,
       c.tag AS ctag,
       i.userid,
       (SELECT COUNT(commentid) FROM `comments` WHERE comments.itemid = i.itemid) AS commentcount,
       CASE WHEN NOT EXISTS (SELECT voteid FROM `votes` WHERE votes.itemid = i.itemid AND votes.userid = @userid) THEN '0' ELSE '1' END AS hasVoted,
       CASE WHEN NOT EXISTS (SELECT voteid FROM `user_favorites` WHERE user_favorites.itemid = i.itemid AND user_favorites.userid = @userid) THEN '0' ELSE '1' END AS isFavorite
    FROM `contentitems` i
      LEFT JOIN votes v ON i.itemid = v.itemid
      LEFT JOIN `user_favorites` uv ON i.itemid = uv.itemid AND (uv.userid = @userid)
      INNER JOIN  `categories` c ON i.cid = c.cid
    GROUP BY i.itemid
    HAVING SUM(CASE WHEN v.direction = 1 THEN 1
                    WHEN v.direction = 2 THEN -1
                    ELSE 0 END) > -3 AND i.pending = 0
    ORDER BY i.dateadded DESC
(编辑格式)

结果如下:

+----+--------------------+----------------+--------+-------------------------+-------------------------+---------+------------------------+------+-------------------------------------------------------
| id |    select_type     |     table      |  type  |      possible_keys                  key                               | key_len | ref                     | rows |              Extra              |
+----+--------------------+----------------+--------+-------------------------+-------------------------+---------+------------------------+------+------------------------------------------------------+
|  1 | PRIMARY            | i              | ALL    | NULL                              | NULL                              | NULL    | NULL                    |  121 | Using temporary; Using filesort |
|  1 | PRIMARY            | v              | ref    | fk_contentitemsitemid_votesitemid | fk_contentitemsitemid_votesitemid | 4       | db33481_mydb.i.itemid   |    2 |                                 |
|  1 | PRIMARY            | uv             | ALL    | NULL                              | NULL                              | NULL    | NULL                    |    7 |                                 |
|  1 | PRIMARY            | c              | eq_ref | PRIMARY                           | PRIMARY                           | 4       | db33481_mydb.i.cid      |    1 |                                 |
|  4 | DEPENDENT SUBQUERY | user_favorites | ALL    | NULL                              | NULL                              | NULL    | NULL                    |    7 | Using where                     |
|  3 | DEPENDENT SUBQUERY | votes          | ref    | fk_contentitemsitemid_votesitemid | fk_contentitemsitemid_votesitemid | 4       | func                    |    2 | Using where                     |
|  2 | DEPENDENT SUBQUERY | comments       | ALL    | NULL                              | NULL                              | NULL    | NULL                    |   26 | Using where                     |
+----+--------------------+----------------+--------+-------------------------+-------------------------+---------+------------------------+------+------------------------------------------------------+

我发现没有用于访问
评论
投票
用户收藏夹
的键。除非表非常小,否则您应该尝试在这些表中的
userid
itemid
上添加索引。

尝试查看此以了解解释计划。试着往下看,它清楚地解释了你需要寻找什么


你的解释计划越详细,信息就越少。请尝试使用oracle提供的。它是开源的,并为您提供了解释计划的适当细节

我将添加以下索引:

ALTER TABLE comments ADD INDEX(commentid)

altertableuser\u收藏夹添加索引(itemid,voteid)


此外,如果可能的_keys列表示NULL,则表示该表没有可用的键。即使它们没有用于优化,如果它们存在于查询中的某个列中,也会显示在那里。最可能的情况是,您在查询中未访问的列上的这些表上有一个主键。

首先,您有一个select not exists投票ID,然后在from中进行左联接,最后在having中进行求和。这三次击中了你的投票表。如果每个投票可能与一个“ItemID”关联,那么最好将其自身作为自己的“总和”进行一次预聚合

此外,由于您的最后一个“HAVING”子句是投票的直接基础,所以在投票上使用左连接将成为一个死点,并最终以正常连接结束

尽管如此,我还是会先预先查询投票结果,然后加入到内容项和其他加入中。。。对用户\u收藏夹的查询是一个计数,将为0(未找到)或1(已找到)。不需要一个案例/当

我的第一个查询别名“PQ”表示“预查询”

其他人也表示需要索引,表示同意。我将确保每个表在用户ID或项目ID(或在适当的情况下两者)上都有各自的索引


其他几点。。。您最初开始查询所有ContentItems,但保留了与投票的连接。。。但随后应用了用户ID的元素。这无疑是对特定用户的查询。这就是说,我还将使用用户ID所做的任何事情的唯一项ID来预先启动整个查询。。。然后继续查询。

我对您提到的三个表有一个主键,如何告诉查询使用它们?或者我应该在每个表上创建一个复合键,并相应地包含primary和userid/itemid?尝试创建一个复合键。在“')、1、0)附近出现语法错误,您可以更新您的答案吗?
SELECT
      PQ.ItemID,
      PQ.VSum as Votes,
      PQ.HasVoted,
      i.pending,
      i.itemid, 
      i.message,
      i.cid, 
      i.dateadded, 
      i.entrypoint,  
      i.userid,
      c.name AS cname,
      c.tag AS ctag,
      ( SELECT COUNT(commentid) 
           FROM `comments` 
           WHERE comments.itemid = PQ.itemid) AS commentcount,
      ( SELECT COUNT(*) FROM user_favorites uf
              WHERE uf.itemid = PQ.itemid 
                AND uf.userid = @userid ) AS isFavorite
   from 
      ( SELECT
              v.itemid,
              SUM( case when v.Direction = 1 then 1
                        when v.Direction = 2 then -1
                        ELSE 0 end ) as VSum,
              MAX( if( votes.userid = @userid, 1, 0 ) AS HasVoted 
           from 
              votes v
           group by 
              v.itemid
           having
              VSum > -3 ) PQ

         JOIN ContentItems i
            ON PQ.ItemID = i.ItemID
            and i.Pending = 0

         JOIN Categories c
            ON i.cid = c.cid

   ORDER BY 
      i.dateadded DESC