gpt4 book ai didi

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

转载 作者:可可西里 更新时间:2023-11-01 07:41:49 25 4
gpt4 key购买 nike

希望了解我的 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 |
+----+--------------------+----------------+--------+-------------------------+-------------------------+---------+------------------------+------+------------------------------------------------------+

最佳答案

首先,您有一个选择不存在的投票 ID,然后在 from 中进行左连接,最后在 having 中进行求和。这是 3 次点击您的投票表。如果每个投票都可能与单个“ItemID”相关联,那么最好将其作为自己的“总和”预先聚合一次。

此外,由于您最后的“HAVING”子句是投票的直接基础,因此投票上的左连接成为死点并最终以正常的 JOIN 结束。

综上所述,我会首先预先查询符合条件的 HAVING 条件的选票,然后加入内容项和其他加入...针对 User_Favorites 的查询是一个计数,或者是0(未找到)或 1(找到)。应该不需要 case/when

我的第一个查询别名“PQ”代表“PreQuery”

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

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

其他几点...您最初开始查询所有 ContentItems,但左连接投票...然后应用用户 ID 的元素。这绝对有特定用户查询的味道。话虽这么说,我会另外预先启动整个查询,仅选择用户 ID 已对其执行任何操作的 ItemIDs...然后继续查询。

关于mySQL - 如何解释我的 EXPLAIN 结果并优化此查询?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7742667/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com