【问题标题】:How to make this SQL query faster?如何使这个 SQL 查询更快?
【发布时间】:2011-09-26 19:26:43
【问题描述】:

我有以下疑问:

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 秒,我很惊讶,因为我使用最新的 MySQL 版本在每个 MyIsam 表中都有索引并且不超过 35 行。

我尽可能缓存了所有内容,但我每天至少要运行 20000 次,这大约是等待加载的 16 小时。而且我很确定我的用户(和 Google Bot)都不喜欢每个页面加载 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

【问题讨论】:

  • 将 IN 替换为 JOIN。搜索 - SO 上有很多示例
  • 你真的也需要独特的吗?
  • 我不确定我该如何做 Darhazer 的建议。 @Ben:我只需要为页面上的每部电影显示一个结果。如果我能以另一种方式做到这一点,我可以删除 distinct。

标签: mysql performance


【解决方案1】:

将movies_manager_movieteammemberactivity 和movies_manager_movieteammember 移动到您的主连接语句中(这样您就可以在movies_manager_movie 和其他3 个表的内连接产品之间进行左外连接)。这应该会大大加快您的查询速度。

【讨论】:

  • 好的。但是如何将“IN”语句放在主连接中?
【解决方案2】:

试试这个:

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;

让我知道它的表现如何

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-13
    • 2014-11-29
    • 1970-01-01
    相关资源
    最近更新 更多