为什么我的INNER JOIN这么慢?服务器超时

时间:2015-01-21 15:50:59

标签: mysql sql mysqli

我的相对简单的查询需要花费很长时间来执行服务器超时。顺便说一句,如果我自己运行子查询,它会很快执行。

基本上我正在尝试获取每个game_id的第一个日期,然后获得相应的分数和持续时间......

我的查询:

SELECT 
    sq.*, 
    up.score AS score, 
    up.duration AS duration 
FROM (
    SELECT 
        up.uid AS uid, 
        up.lesson_id AS lesson_id, 
        up.level AS level, 
        up.game_id AS game_id, 
        MIN(up.date) AS first_date
    FROM cdu_user_progress up
    WHERE (up.score >= '0') 
    GROUP BY up.uid, up.lesson_id, up.level, up.game_id
) sq
INNER JOIN cdu_user_progress up ON up.uid = sq.uid AND up.lesson_id = sq.lesson_id AND up.level = sq.level AND up.game_id = sq.game_id AND up.date = sq.first_date
GROUP BY sq.uid, sq.lesson_id, sq.level, sq.game_id

cdu_user_progress是:

------------------------------------------------------------------------------------
|id    |uid    |lesson_id    |game_id    |level    |score    |duration    |date    |
------------------------------------------------------------------------------------

说明:

Field      Type     Null    Key     Default     Extra
--------------------------------------------------------------
id         int(11)  NO      PRI     NULL        auto_increment
uid        int(11)  NO      NULL     
lesson_id  int(11)  NO      NULL     
game_id    int(11)  NO      NULL     
level      int(11)  NO      NULL     
score      int(11)  NO      NULL     
duration   int(11)  NO      NULL     
date       int(11)  NO      NULL     

1 个答案:

答案 0 :(得分:1)

首先,除非您按日期重复,否则我认为您不需要外部group by。如果是这样,也许您可​​以使用id代替date

SELECT sq.*, up.score AS score,  up.duration AS duration 
FROM (SELECT up.uid, up.lesson_id, up.level, up.game_id,
             MIN(up.date) AS first_date
      FROM cdu_user_progress up
      WHERE up.score >= 0 
      GROUP BY up.uid, up.lesson_id, up.level, up.game_id
      ) s INNER JOIN
      cdu_user_progress up
      ON up.uid = sq.uid AND up.lesson_id = sq.lesson_id AND
         up.level = sq.level AND up.game_id = sq.game_id AND
         up.date = sq.first_date;

此查询的最佳索引是cdu_user_progress(score)cdu_user_progress(uid, lesson_id, level, game_id, date)。如果第一个查询运行得很快,那么第二个索引应该是一个很大的帮助。