なぜ私のクエリが極端に遅いのか分かりません。 48ギガバイトDDR3デュアルXeonプロセッサL5630の60秒PHP7.0-FPMとMariaDB 10.0.27でのUbuntu 16.04を実行している特定のテーブルでLEFT JOINが非常に遅い
SELECT v.video_id, v.user_id, v.title, v.slug, v.rating, v.rated_by,
v.duration, v.thumb, v.total_views, v.total_comments, v.add_time,
v.view_time, v.status, v.source_id, v.orientation, v.thumbs,
v.featured, v.flagged,
u.username,
s.name,
f.reason,
GROUP_CONCAT(c.name) AS categories
FROM video AS v
LEFT JOIN video_flags AS f ON (f.video_id = v.video_id)
LEFT JOIN video_sources AS s ON (s.source_id = v.source_id)
LEFT JOIN user AS u ON (u.user_id = v.user_id)
LEFT JOIN video_category AS vc ON (vc.video_id = v.video_id)
LEFT JOIN video_categories AS c ON (c.category_id = vc.category_id) GROUP BY v.video_id ORDER BY v.video_id DESC LIMIT 10
私がコメントするときので、私は、video_flags表にあるように、問題を突き止めましたf.reasonフィールドとvideo_flagsの左側の結合では、クエリは152msしかかかりません。私は戻って、次の取得]を選択説明実行するとINT(11)
をvideo_flagsテーブルがVIDEO_IDにインデックスを持ち、フィールドタイプは、両方のテーブルに同じである:
+------+-------------+-------+--------+---------------+----------+---------+----------------------------+---------+-------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-------+--------+---------------+----------+---------+----------------------------+---------+-------------------------------------------------+
| 1 | SIMPLE | v | ALL | NULL | NULL | NULL | NULL | 1219933 | Using temporary; Using filesort |
| 1 | SIMPLE | f | ALL | video_id | NULL | NULL | NULL | 1 | Using where; Using join buffer (flat, BNL join) |
| 1 | SIMPLE | s | eq_ref | PRIMARY | PRIMARY | 4 | adb_network.v.source_id | 1 | |
| 1 | SIMPLE | u | eq_ref | PRIMARY | PRIMARY | 4 | adb_network.v.user_id | 1 | |
| 1 | SIMPLE | vc | ref | video_id | video_id | 4 | adb_network.v.video_id | 2 | Using index |
| 1 | SIMPLE | c | eq_ref | PRIMARY | PRIMARY | 4 | adb_network.vc.category_id | 1 | Using where |
+------+-------------+-------+--------+---------------+----------+---------+----------------------------+---------+-------------------------------------------------+
私は何を知りません私はここで紛失しています。まず、video_flagsテーブルが空であると思っていました。次にレコードを追加して、クエリを素早く(200ms)実行しましたが、問題は戻っています。
ご迷惑をおかけして申し訳ありません。
更新:
+------+-------------+-------+--------+---------------+----------+---------+----------------------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-------+--------+---------------+----------+---------+----------------------------+------+-------------+
| 1 | SIMPLE | v | index | NULL | PRIMARY | 4 | NULL | 5 | |
| 1 | SIMPLE | f | ref | video_id | video_id | 4 | adb_network.v.video_id | 1 | Using index |
| 1 | SIMPLE | s | eq_ref | PRIMARY | PRIMARY | 4 | adb_network.v.source_id | 1 | |
| 1 | SIMPLE | u | eq_ref | PRIMARY | PRIMARY | 4 | adb_network.v.user_id | 1 | |
| 1 | SIMPLE | vc | ref | video_id | video_id | 4 | adb_network.v.video_id | 2 | Using index |
| 1 | SIMPLE | c | eq_ref | PRIMARY | PRIMARY | 4 | adb_network.vc.category_id | 1 | Using where |
+------+-------------+-------+--------+---------------+----------+---------+----------------------------+------+-------------+
ソリューション:@somniumによって示唆されるように、私はFORCE INDEX
上を追加しようとしたは@somniumためf.reason列のない選択を説明追加video_id
の列とそれによってクエリ時間が60秒から272msに短縮されました。なぜなら、結合中にインデックスが失われても問題が解決される理由はまだ分かりません。ありがとう
SELECT v.video_id, v.user_id, v.title, v.slug, v.rating, v.rated_by,
v.duration, v.thumb, v.total_views, v.total_comments, v.add_time,
v.view_time, v.status, v.source_id, v.orientation, v.thumbs,
v.featured, v.flagged,
u.username,
s.name,
f.reason,
GROUP_CONCAT(c.name) AS categories
FROM video v
LEFT JOIN video_flags f FORCE INDEX FOR JOIN (video_id) ON (f.video_id = v.video_id)
LEFT JOIN video_sources s ON (s.source_id = v.source_id)
LEFT JOIN user u ON (u.user_id = v.user_id)
LEFT JOIN video_category vc ON (vc.video_id = v.video_id)
LEFT JOIN video_categories c ON (c.category_id = vc.category_id) GROUP BY v.video_id ORDER BY v.video_id DESC LIMIT 10
ビデオテーブルに1219933があり、他のいくつかのテーブルに参加しています。このテーブルにはフィルタがありません。したがって、これらのすべての行が複数の結合で使用されます。 60秒は本当に良いと思う。しかし、あなたがまだ持っていない場合は、video_idにインデックスを追加してみることができます – e4c5
ご意見ありがとうございます。不思議なのは私のクエリが複数の結合を行うことです。問題はf.reason列が含まれている場合にのみ発生します。私がそれをコメントアウトすると、他のすべての結合がそのまま残っているだけです。 video_flags.video_idにインデックスがあるので、どちらでも問題ありません。 – Hugo
あなたはグループ化していないSELECTのすべての列を集計すべきですか? MySQLはそうすることができますが、それは悪い習慣です。 –