1

ユーザー (m_id) が表示したすべてのレッスン (o_id)、最後に評価した時間 (最初のサブクエリ)、最後に評価した時間 (2 番目のサブクエリ) を調べるクエリがあります。

本番環境ではクエリは高速ですが、つい最近、私の開発マシンでは停止してしまい、今日は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秒以上かかることを示しています...(つまり、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 に答える