2016-05-10 17 views
0

システム内で非効率なクエリが見つかりました。 contentはスライドのバージョンを保持しています。これはidでスライドの最高バージョンを選択することになっています。デバッグ低速なmySQLクエリをExplainで実行します

SELECT `content`.* 
FROM (`content`) 
JOIN (
SELECT max(version) as `version` from `content` 
WHERE `slide_id` = '16901' 
group by `slide_id` 
) c ON `c`.`version` = `content`.`version`; 

一つの大きな問題は、外側のクエリは、スライドIDでフィルタリングしないように、システムのほぼすべてのスライドを返すことである。

+----+-------------+------------------+------------+--------+--------------------------------------------------------------------------------+------------------------------------+---------+-------+------+----------+--------------------------+ 
| id | select_type | table   | partitions | type | possible_keys                 | key        | key_len | ref | rows | filtered | Extra     | 
+----+-------------+------------------+------------+--------+--------------------------------------------------------------------------------+------------------------------------+---------+-------+------+----------+--------------------------+ 
| 1 | PRIMARY  | <derived2>  | NULL  | system | NULL                   | NULL        | NULL | NULL | 1 | 100.00 | NULL      | 
| 1 | PRIMARY  | content   | NULL  | ref | PRIMARY,version                | PRIMARY       | 8  | const | 9703 | 100.00 | NULL      | 
| 2 | DERIVED  | content   | NULL  | ref | PRIMARY,fk_content_slides_idx,thumbnail_asset_id,version,slide_id      | fk_content_slides_idx    | 8  | const | 1 | 100.00 | Using where; Using index | 
+----+-------------+------------------+------------+--------+--------------------------------------------------------------------------------+------------------------------------+---------+-------+------+----------+--------------------------+ 
をEXPLAIN私が取得することを追加した後...

SELECT `content`.* 
FROM (`content`) 
JOIN ( 
SELECT max(version) as `version` from `content` 
WHERE `slide_id` = '16901' group by `slide_id` 
) c ON `c`.`version` = `content`.`version` 
WHERE `slide_id` = '16901'; 

は正しく1までの行の量は減少しますが、doesntのは、本当に物事をスピードアップ

+----+-------------+------------------+------------+--------+--------------------------------------------------------------------------------+------------------------------------+---------+-------------+------+----------+--------------------------+ 
| id | select_type | table   | partitions | type | possible_keys                 | key        | key_len | ref   | rows | filtered | Extra     | 
+----+-------------+------------------+------------+--------+--------------------------------------------------------------------------------+------------------------------------+---------+-------------+------+----------+--------------------------+ 
| 1 | PRIMARY  | <derived2>  | NULL  | system | NULL                   | NULL        | NULL | NULL  | 1 | 100.00 | NULL      | 
| 1 | PRIMARY  | content   | NULL  | const | PRIMARY,fk_content_slides_idx,version,slide_id         | PRIMARY       | 16  | const,const | 1 | 100.00 | NULL      | 
| 2 | DERIVED  | content   | NULL  | ref | PRIMARY,fk_content_slides_idx,thumbnail_asset_id,version,slide_id    | fk_content_slides_idx    | 8  | const  | 1 | 100.00 | Using where; Using index | 
+----+-------------+------------------+------------+--------+--------------------------------------------------------------------------------+------------------------------------+---------+-------------+------+----------+--------------------------+ 

を説明します。

バージョン、slide_idにインデックスがあり、バージョンAND slide_idに一意のキーがあります。

これをスピードアップするために他に何かできますか?

MAXのTOP LIMIT 1の字句を使用しますか?

メートル

答えて

0

MySQLはインデックスを取るように見えるので、あなたがslide_idでグループを避けるべきだと思うだけの提案(バージョン、slide_id)テーブルを結合する。あなたが最初の列としてslide_idたインデックスが必要

SELECT `content`.* 
FROM `content` 
FORCE INDEX FOR JOIN (fk_content_slides_idx) 
join ( 
    SELECT `slide_id`, max(version) as `version` from `content` 
    WHERE `slide_id` = '16901' group by `slide_id` 
) c ON `c`.`slide_id` = `content`.`slide_id` and `c`.`version` = `content`.`version` 

とのより良い結果を取得する必要があり、私はそれがない場合は、別のものを取る、fk_content_slides_idxだ推測します。

部分FORCE INDEX FOR JOIN (fk_content_slides_idx)はそれを強制するだけです。mysqlが強制的にそれを取る場合は試してください(すべきです)。

インデックス(slide_id、バージョン)で少し良い結果が得られるかもしれませんが、差異が見られる場合はデータ量(たとえばidごとのバージョン数)によって異なります(ただし、あなたはすでにこのテーブルにたくさんいるが、あなたはそれを試してみてください)

+0

ありがとう@Solarfalreは、はるかに速く実行されているようです。 –

0

私はあなたがフィルタが1 slide_idであるのみ(16901)

SELECT `content`.* 
FROM (`content`) 
JOIN ( 
SELECT max(version) as `version` from `content` 
    WHERE `slide_id` = '16901' 
) c ON `c`.`version` = `content`.`version` 
WHERE `slide_id` = '16901'; 
関連する問題