2011-09-26 107 views
0

我有以下查询:如何使这个SQL查询更快?

SELECT DISTINCT `movies_manager_movie`.`id`, 
       `movies_manager_movie`.`title`, 
       `movies_manager_movie`.`original_title`, 
       `movies_manager_movie`.`synopsis`, 
       `movies_manager_movie`.`keywords`, 
       `movies_manager_movie`.`release_date`, 
       `movies_manager_movie`.`rating`, 
       `movies_manager_movie`.`poster_web_url`, 
       `movies_manager_movie`.`has_poster`, 
       `movies_manager_movie`.`number`, 
       `movies_manager_movie`.`has_sources`, 
       `movies_manager_movie`.`season_id`, 
       `movies_manager_movie`.`created`, 
       `movies_manager_movie`.`updated`, 
       `movies_manager_moviecache`.`activity_name` 

FROM `movies_manager_movie` 

LEFT OUTER JOIN `movies_manager_moviecache` ON (`movies_manager_movie`.`id` = `movies_manager_moviecache`.`movie_id`) 

WHERE (`movies_manager_movie`.`has_sources` = 1 
     AND (`movies_manager_moviecache`.`team_member_id` IN (

      SELECT U0.`id` FROM `movies_manager_movieteammember` U0 
      INNER JOIN `movies_manager_movieteammemberactivity` U1 ON (U0.`id` = U1.`team_member_id`) 
      WHERE U1.`movie_id` = 3588) 
       AND `movies_manager_movie`.`number` IS NULL 
     ) 

    AND NOT (`movies_manager_movie`.`id` = 3588)) 
    ORDER BY `movies_manager_moviecache`.`activity_name` DESC LIMIT 3; 

该查询可能需要长达3秒钟,我是因为我得到的索引到处非常惊讶和我的每个MyISAM表的不超过35行,并使用最新的MySQL版本。

我缓存了一切,但我至少每天运行这个20000次,这大概是16小时的等待加载。我很确定我的用户(也不是谷歌机器人)都没有意识到每次页面加载都需要等待4次。

我该怎么做才能让它变得更快?

由于电影缓存的所有目的都是非规范化到复杂的连接,所以我想过从电影到电影缓存的重复字段。

我试图将子查询内联到一个ID列表,但令人惊讶地使查询时间加倍。

表:

+----------------+--------------+------+-----+---------+----------------+ 
| Field   | Type   | Null | Key | Default | Extra   | 
+----------------+--------------+------+-----+---------+----------------+ 
| id    | int(11)  | NO | PRI | NULL | auto_increment | 
| title   | varchar(120) | NO | UNI | NULL |    | 
| original_title | varchar(120) | YES |  | NULL |    | 
| synopsis  | longtext  | YES |  | NULL |    | 
| keywords  | varchar(120) | YES |  | NULL |    | 
| release_date | date   | YES |  | NULL |    | 
| rating   | int(11)  | NO |  | NULL |    | 
| poster_web_url | varchar(255) | YES |  | NULL |    | 
| has_poster  | tinyint(1) | NO |  | NULL |    | 
| number   | int(11)  | YES |  | NULL |    | 
| season_id  | int(11)  | YES | MUL | NULL |    | 
| created  | datetime  | NO |  | NULL |    | 
| updated  | datetime  | NO |  | NULL |    | 
| has_sources | tinyint(1) | NO |  | NULL |    | 
+----------------+--------------+------+-----+---------+----------------+ 
+---------------------+--------------+------+-----+---------+----------------+ 
| Field    | Type   | Null | Key | Default | Extra   | 
+---------------------+--------------+------+-----+---------+----------------+ 
| id     | int(11)  | NO | PRI | NULL | auto_increment | 
| name    | varchar(120) | NO | UNI | NULL |    | 
| biography   | longtext  | YES |  | NULL |    | 
| birth_date   | date   | YES |  | NULL |    | 
| picture_web_url  | varchar(255) | YES |  | NULL |    | 
| allocine_link  | varchar(255) | YES |  | NULL |    | 
| created    | datetime  | NO |  | NULL |    | 
| updated    | datetime  | NO |  | NULL |    | 
| has_picture   | tinyint(1) | NO |  | NULL |    | 
| biography_linkyfied | longtext  | YES |  | NULL |    | 
+---------------------+--------------+------+-----+---------+----------------+ 

+----------------+--------------+------+-----+---------+----------------+ 
| Field   | Type   | Null | Key | Default | Extra   | 
+----------------+--------------+------+-----+---------+----------------+ 
| id    | int(11)  | NO | PRI | NULL | auto_increment | 
| movie_id  | int(11)  | NO | MUL | NULL |    | 
| tag_slug  | varchar(100) | YES | MUL | NULL |    | 
| team_member_id | int(11)  | YES | MUL | NULL |    | 
| cast_rank  | int(11)  | YES |  | NULL |    | 
| activity_name | varchar(30) | YES | MUL | NULL |    | 
+----------------+--------------+------+-----+---------+----------------+ 

Mysql的告诉我这是一个缓慢的查询:

# Query_time: 3 Lock_time: 0 Rows_sent: 9 Rows_examined: 454128 
+4

替换与JOIN。搜索 - 在SO –

+1

有很多例子你是否真的需要独特的? – Ben

+0

我不知道我该如何做达哈泽的建议。 @Ben:我需要在页面上为每部电影只显示一个结果。如果我能以另一种方式做到这一点,我可以清除不同的问题。 –

回答

1

移动movies_manager_movieteammemberactivity和movies_manager_movieteammember到主连接语句(让你做movies_manager_movie之间的左外其他3个表格的内部连接产品)。这应该会大大加快您的查询速度。

+0

好的。但是,我如何在主连接中放置'IN'语句? –

1

试试这个:

SELECT `movies_manager_movie`.`id`, 
    `movies_manager_movie`.`title`, 
    `movies_manager_movie`.`original_title`, 
    `movies_manager_movie`.`synopsis`, 
    `movies_manager_movie`.`keywords`, 
    `movies_manager_movie`.`release_date`, 
    `movies_manager_movie`.`rating`, 
    `movies_manager_movie`.`poster_web_url`, 
    `movies_manager_movie`.`has_poster`, 
    `movies_manager_movie`.`number`, 
    `movies_manager_movie`.`has_sources`, 
    `movies_manager_movie`.`season_id`, 
    `movies_manager_movie`.`created`, 
    `movies_manager_movie`.`updated`, 
    (
     SELECT `movies_manager_moviecache`.`activity_name` 
     FROM `movies_manager_moviecache` 
     WHERE (`movies_manager_movie`.`id` = `movies_manager_moviecache`.`movie_id` 
      AND (`movies_manager_moviecache`.`team_member_id` IN (
       SELECT U0.`id` FROM `movies_manager_movieteammember` U0 
        INNER JOIN `movies_manager_movieteammemberactivity` U1 ON (U0.`id` = U1.`team_member_id`) 
       WHERE U1.`movie_id` = 3588) 
      AND `movies_manager_movie`.`number` IS NULL 
     )) LIMIT 1) AS `activity_name` 
FROM `movies_manager_movie`  
WHERE (`movies_manager_movie`.`has_sources` = 1 
    AND NOT (`movies_manager_movie`.`id` = 3588)) 
ORDER BY `activity_name` DESC 
LIMIT 3; 

让我知道如何执行