今天我收到了来自我的托管帐户的电子邮件,说我需要调整我的查询:
SELECT
`id`, `nick`, `msg`, `uid`, `show_pic`,
`time`,`ip`,`time_updated`,
(SELECT COUNT(c.msg_id)
FROM `the_ans` c
where c.msg_id = d.id) AS counter,
(SELECT c.msg
FROM `the_ans` c
WHERE c.msg_id=d.id
ORDER BY `time` DESC LIMIT 1) as lastmsg
FROM
`the_data` d
ORDER BY `time_updated` DESC LIMIT 26340 ,15
说明:
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY d ALL 34309 Using filesort
3 DEPENDENT SUBQUERY c ALL 43659 Using where; Using filesort
2 DEPENDENT SUBQUERY c ALL 43659 Using where
此查询检查65,396,669,012,829行,这在共享主机中是不可接受的。
tbh,我不明白他们的解释.. 查询实际上做的是按时间顺序更新15个帖子, 对于每个帖子,我抓住最新的评论, 计算每篇文章的所有评论。
posts table - 'the_data'
comments table = 'the_ans'
我不是一个mysql大师,我不知道如何改进这个查询 任何帮助将不胜感激
THX
查询
SELECT
`id` , `nick` , `msg` , `uid` , `show_pic` , `time` , `ip` , `time_updated` , (
SELECT COUNT( c.msg_id )
FROM `the_ans` c
WHERE c.msg_id = d.id
) AS counter, (
SELECT c.msg
FROM `the_ans` c
WHERE c.msg_id = d.id
ORDER BY `time` DESC
LIMIT 1
) AS lastmsg
FROM `the_data` d
ORDER BY `time_updated` DESC
LIMIT 26340 , 15
这是结果结构
id| nick | msg | uid | show_pick | time | ip |time_updated|counter|lastmsg
| | | | | | | | |
7 | jqman | hello| 10074 | 0 |2013-21-01 | 12 |2013-21-01 | 55 |blah bl
答案 0 :(得分:3)
快速浏览解释计划表明,MySQL没有合适的索引可供使用,因此它采用全表扫描。
EXPLAIN:
id select_type table type possible_keys key key_len ref rows Extra
-- ------------------ ----- ---- ------------- --- ------- --- ----- ----------------------------
1 PRIMARY d ALL 34309 Using filesort
3 DEPENDENT SUBQUERY c ALL 43659 Using where; Using filesort
2 DEPENDENT SUBQUERY c ALL 43659 Using where
要优化现有查询的执行,需要添加适当的索引。可能的候选人:
ON `the_data`(`time_updated`)
ON `the_ans`(`msg_id`,`time`)
这些索引将显着提高外部查询(可能消除排序操作)的性能,以及相关子查询的大量执行。
除此之外,您还需要更改查询以提高性能。在准备整个结果集之后,将应用最外层查询的LIMIT
子句,这意味着将为表the_data
中的每一行执行这两个相关子查询。这将是你的午餐,表现明智。
要使这些相关子查询仅针对返回的(最多)15行运行,您需要在这些子查询运行之前应用LIMIT子句。
此查询应返回等效的结果集,并且将避免每个相关子查询的34,000多次执行,这应该会显着提高性能:
SELECT d.*
, ( SELECT COUNT( c.msg_id )
FROM `the_ans` c
WHERE c.msg_id = d.id
) AS counter
, ( SELECT c.msg
FROM `the_ans` c
WHERE c.msg_id = d.id
ORDER BY `time` DESC
LIMIT 1
) AS lastmsg
FROM ( SELECT e.`id`
, e.`nick`
, e.`msg`
, e.`uid`
, e.`show_pic`
, e.`time`
, e.`ip`
, e.`time_updated`
FROM `the_data` e
ORDER
BY e.`time_updated` DESC
LIMIT 26340 , 15
) d
ORDER BY d.`time_updated` DESC
(您当前的查询执行每个相关子查询“SELECT COUNT(1) FROM the_data
”次。通过上面的重写查询,每个子查询只执行15次。)
答案 1 :(得分:2)
在从主查询中选择限时行后执行相关子查询:
SELECT d.*,
(SELECT COUNT(c.msg_id)
FROM `the_ans` c
where c.msg_id = d.id) AS counter,
(SELECT c.msg
FROM `the_ans` c
WHERE c.msg_id=d.id
ORDER BY `time` DESC LIMIT 1) as lastmsg
FROM (SELECT
`id`, `nick`, `msg`, `uid`, `show_pic`,
`time`,`ip`,`time_updated`
FROM
`the_data`
ORDER BY `time_updated` DESC LIMIT 26340 ,15) d
另外,请确保您在time_updated
和msg_id
上有索引。
答案 2 :(得分:0)
这样的事情会让你的结果更快一些。
请注意,这是使用INNER JOIN,因为当* the_data *上的每条记录在* the_ans *
上至少有一条匹配记录时,它可以正常工作SELECT `id` , `nick` , `msg` , `uid` , `show_pic` , `time` , `ip` , `time_updated` , Sub1.counter, c.msg AS lastmsg
FROM `the_data` d
INNER JOIN (SELECT msg_id, COUNT( * ) AS counter, MAX( `time` ) AS MaxTime FROM `the_ans` GROUP BY msg_id) Sub1 ON d.id = Sub1.msg_id
INNER JOIN the_ans c ON d.id = c.msg_id AND sub1.MaxTime = c.`time`
ORDER BY `time_updated` DESC
LIMIT 26340 , 15