MySQL JOIN与SUBQUERY非常慢

时间:2014-07-03 18:10:58

标签: mysql sql

我有一个论坛,我希望看到最新的主题与作者的姓名和最后回答的用户

表主题(论坛)

| idTopic | IdParent | User | Title | Text             |
--------------------------------------------------------
| 1       | 0        | Max  | Help! | i need somebody  | 
--------------------------------------------------------
| 2       | 1        | Leo  |       | What?!           |  

查询:

SELECT 
    Question.*,
    Response.User AS LastResponseUser 
FROM Topic AS Question
LEFT JOIN (
   SELECT User, IdParent  
   FROM Topic 
   ORDER BY idTopic DESC
) AS Response 
    ON ( Response.IdParent = Question.idTopic )
WHERE Question.IdParent = 0
GROUP BY Question.idTopic
ORDER BY Question.idTopic DESC

输出:

| idTopic | IdParent | User | Title | Text             | LastResponseUser |
---------------------------------------------------------------------------
| 1       | 0        | Max  | Help! | i need somebody  | Leo              |
---------------------------------------------------------------------------

实施例: http://sqlfiddle.com/#!2/22f72/4

查询有效,但速度很慢(超过25'000记录的时间大约为0.90秒)。

如何让它更快?

更新

建议的解决方案之间的比较

http://sqlfiddle.com/#!2/94068/22

2 个答案:

答案 0 :(得分:2)

假设最高IDTopic是最后一个响应用户... 并假设您想要在没有回复的情况下返回主题......

Select A.IDTopic, A.IDParent, A.User, A.Title, A.Text, 
case when b.User is null then 'No Response' else B.User end as LastReponseUser
FROM topic A
LEFT JOIN Topic B
 on A.IdTopic = B.IDParent
 and B.IDTopic = (Select max(IDTopic) from Topic 
                  where IDParent=B.IDParent group by IDParent)
WHERE  A.IDParent =0

答案 1 :(得分:2)

如果使用当前架构,我建议添加索引(特别是聚簇索引(主键))并简化SQL以让mySQL完成优化语句的工作,而不是强制它运行子查询,排序结果,然后运行主查询。

CREATE TABLE Topic (
  idTopic  INT
  ,IdParent INT
  ,User     VARCHAR(100)
  ,Title    VARCHAR(255)
  ,Text     VARCHAR(255)       
  ,CONSTRAINT Topic_PK PRIMARY KEY (idTopic) 
  ,CONSTRAINT Topic_idTopic_UK UNIQUE (idTopic) 
  ,INDEX Topic_idParentIdTopic_IX (idParent, idTopic)
);


INSERT INTO Topic (idTopic, IdParent, User, Title, Text) VALUES 
(1, 0, 'Max', 'Help!', 'i need somebody'),
(2, 1, 'Leo', '', 'What!?');


SELECT Question.*
, Response.User AS LastResponseUser 
FROM Topic AS Question
LEFT JOIN Topic AS Response 
  ON Response.IdParent = Question.idTopic
WHERE Question.IdParent = 0
order by Question.idTopic
;

http://sqlfiddle.com/#!2/7f1bc/1

<强>更新

在您提到的评论中,您只想要最近的回复。为此,试试这个:

SELECT Question.*
, Response.User AS LastResponseUser 
FROM Topic AS Question
LEFT JOIN (
  select a.user, a.idParent 
  from Topic as a
  left join Topic as b
  on b.idParent = a.idParent
  and b.idTopic > a.idTopic
  where b.idTopic is null 
) AS Response 
  ON Response.IdParent = Question.idTopic
WHERE Question.IdParent = 0
order by Question.idTopic
;

http://sqlfiddle.com/#!2/7f1bc/3