1

我有一个查询,查看用户(m_id)查看过的所有课程(o_id)、他们给它的最后评分(第一个子查询)和最后一次评分(第二个子查询)

该查询在生产中很快,但最近在我的开发机器上它停止了,我今天发现它花了1800 秒

SELECT o_id i , UNIX_TIMESTAMP(mo_access_date) a, mo_complete c, mo_quizscore q,
  (
    SELECT mlr_rating 
    FROM member_lesson_rating 
    WHERE m_id=mo.m_id&&o_id=mo.o_id 
    ORDER BY mlr_id DESC 
    LIMIT 1
  ) r,
  (
    SELECT if(mlr_rating > 0, UNIX_TIMESTAMP(mlr_created),null) x 
    FROM member_lesson_rating  
    WHERE m_id=mo.m_id&&o_id=mo.o_id 
    ORDER BY mlr_id DESC 
    LIMIT 1
  ) u
FROM member_object_tbl mo
WHERE m_id=64206

和描述(

+----+--------------------+----------------------+-------+------------------+----------+---------+-------+------+-------------+
| id | select_type        | table                | type  | possible_keys    | key      | key_len | ref   | rows | Extra       |
+----+--------------------+----------------------+-------+------------------+----------+---------+-------+------+-------------+
|  1 | PRIMARY            | mo                   | ref   | opt_cols,m_id    | opt_cols | 4       | const |   99 |             |
|  3 | DEPENDENT SUBQUERY | member_lesson_rating | index | m_id,m_id_2,o_id | PRIMARY  | 4       | NULL  |    1 | Using where |
|  2 | DEPENDENT SUBQUERY | member_lesson_rating | index | m_id,m_id_2,o_id | PRIMARY  | 4       | NULL  |    1 | Using where |
+----+--------------------+----------------------+-------+------------------+----------+---------+-------+------+-------------+

分析查询表明每个子查询在我的测试中占用一秒钟......(即1 * 99)

和创建表

CREATE TABLE `member_lesson_rating` (
  `mlr_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `m_id` int(10) unsigned NOT NULL,
  `o_id` int(10) unsigned NOT NULL,
  `mlr_created` datetime NOT NULL,
  `mlr_rating` tinyint(4) NOT NULL,
  PRIMARY KEY (`mlr_id`),
  KEY `m_id` (`m_id`,`o_id`),
  KEY `m_id_2` (`m_id`),
  KEY `o_id` (`o_id`)
) ENGINE=MyISAM AUTO_INCREMENT=2882202 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

更新:不会导致任何问题的新查询

SELECT
  mo.o_id i , 
  UNIX_TIMESTAMP(mo_access_date) a, 
  mo_complete c, 
  mo_quizscore q,
  if(mlr_rating > 0, UNIX_TIMESTAMP(mlr_created),null) u,
  mlr_rating r
FROM 
  (SELECT * FROM member_object_tbl WHERE m_id=?) mo
LEFT JOIN
  (  
    SELECT * 
    FROM (
      SELECT * 
      FROM member_lesson_rating 
      WHERE m_id=?
      ORDER BY mlr_id DESC
    ) mlr2 
    GROUP BY o_id
  ) mlr
ON mo.o_id=mlr.o_id
4

1 回答 1

0

依赖子查询在扩展方面很糟糕;我认为您可以通过首先选择最大值mlr_id然后再次将其加入自身以获取mlr_rating相关字段来解决此问题。

SELECT tmp.*, r2.mlr_rating, IF(r2.mlr_rating > 0, UNIX_TIMESTAMP(r2.mlr_created), NULL) x FROM 
  (SELECT o_id i, UNIX_TIMESTAMP(mo_access_date) a, mo_complete c, mo_quizscore q,
      MAX(mlr_id) AS max_mlr_id
      FROM member_object_tbl mo
      INNER JOIN member_lesson_rating r ON r.m_id = mo.m_id AND r.o_id = mo.o_id
      WHERE m_id=64206
      GROUP BY m.o_id
  ) tmp
  INNER JOIN member_lesson_rating r2 ON r2.mlr_id = tmp.max_mlr_id
于 2012-06-08T03:43:17.860 回答