简体   繁体   English

MySQL的JOIN与SUBQUERY非常慢

[英]MySQL JOIN with SUBQUERY very slow

I have a forum and I would like to see the latest topics with the author's name and the last user who answered 我有一个论坛,我想查看作者姓名和最近一次回答的用户的最新话题

Table Topic (forum) 表格主题(论坛)

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

Query: 查询:

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

Output: 输出:

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

Example: http://sqlfiddle.com/#!2/22f72/4 示例: http//sqlfiddle.com/#!2 / 22f72 / 4

The query works, but is very slow (more or less 0.90 seconds over 25'000 record). 该查询有效,但是非常慢(在25,000条记录上大约0.90秒)。

How can I make it faster? 我怎样才能使其更快?

UPDATE 更新

comparison between the proposed solutions 拟议解决方案之间的比较

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

Assuming the highest IDTopic is the last responses user... and assuming you want to return topics without responses... 假设最高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

If using your current schema, I'd recommend adding indexes (particularly a clustered index (primary key)) and simplifying your SQL to let mySQL do the work of optimising the statement, rather than forcing it to run a subquery, sort the results, then run the main query. 如果使用当前架构,建议添加索引(尤其是聚集索引(主键))并简化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 http://sqlfiddle.com/#!2/7f1bc/1

Update 更新资料

In the comments you mentioned you only want the most recent response. 在您提到的评论中,您只需要最新的回复。 For that, try this: 为此,请尝试以下操作:

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 http://sqlfiddle.com/#!2/7f1bc/3

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM