[英]Why does my query take over 30 mins on MySQL 5.7 but a couple seconds on MySQL 8?
I have the following query.我有以下查询。 On MySQL 5.7 it takes over 30 mins minutes to run but on MySQL 8 it takes less than 10 seconds.在 MySQL 5.7 上运行需要 30 多分钟,但在 MySQL 8 上运行时间不到 10 秒。 There are around 20k records in students_t, 500 in classes_t and 1100 in groups_t. student_t 中有大约 20k 条记录,classes_t 中有 500 条记录,groups_t 中有 1100 条记录。 student_enrolled_classes_t contains 100288 records and 160156 records.There are no foreign keys in place. student_enrolled_classes_t 包含 100288 条记录和 160156 条记录。没有外键。
SELECT DISTINCT
s.forename
, s.surname
, count(c.id) as 'classes'
, group_concat(DISTINCT g.name) 'groups'
FROM students_t s
, student_enrolled_classes_t c
, student_enrolled_groups_t eg
, groups_t g
WHERE s.id = c.student_id
AND s.id = eg.student_id
AND eg.group_id = g.id
GROUP BY s.id, c.id
ORDER BY s.forename ASC;
The table structures are (generated with Hibernate):表结构(使用 Hibernate 生成):
CREATE TABLE classes_t
(id BIGINT auto_increment PRIMARY KEY);
CREATE TABLE groups_t
(id BIGINT auto_increment PRIMARY KEY
,name VARCHAR(255) NULL);
CREATE TABLE student_enrolled_classes_t
(id BIGINT auto_increment PRIMARY KEY
,class_id BIGINT NULL
,student_id BIGINT NULL);
CREATE TABLE student_enrolled_groups_t
(id BIGINT NOT NULL PRIMARY KEY
,group_id BIGINT NULL
,student_id BIGINT NULL);
CREATE TABLE students_t
(id BIGINT auto_increment PRIMARY KEY
,forename VARCHAR(255) NULL
,surname VARCHAR(255) NULL);
The question is: Why does it take 30 mins on MySQL 5.7 but only 10 seconds on MySQL 8?问题是:为什么在 MySQL 5.7 上需要 30 分钟,而在 MySQL 8 上只需要 10 秒?
Thank you谢谢
You could write the query as follows.您可以按如下方式编写查询。 It uses newer join syntax and takes into a account situations where student is not part of a class/group.它使用较新的连接语法,并考虑到学生不属于班级/组的情况。
SELECT
s.forename
, s.surname
, count(distinct c.id) as 'classes'
, group_concat(distinct g.name) 'groups'
FROM students_t s
LEFT JOIN student_enrolled_classes_t c ON c.student_id=s.id
LEFT JOIN student_enrolled_groups_t eg ON eg.student_id=s.id
LEFT JOIN groups_t g ON eg.group_id = g.id
GROUP BY s.id
ORDER BY s.forename ASC;
We need to see EXPLAIN SELECT...
to analyze why one runs so slowly.我们需要看看EXPLAIN SELECT...
来分析为什么一个人跑得这么慢。 While you are at it, also get EXPLAIN FORMAT=JSON SELECT...
.当你在它的时候,也得到EXPLAIN FORMAT=JSON SELECT...
。
This reformulation and indexes may speed up the query on both servers, possibly making them both fast.这种重新制定和索引可以加快两台服务器上的查询,可能使它们都快。 Note that it gets rid of the GROUP BY
and DISTINCT
, both of which slow down the query.请注意,它摆脱了GROUP BY
和DISTINCT
,这两者都会减慢查询速度。
SELECT s.forename, s.surname,
( SELECT COUNT(*)
FROM student_enrolled_classes_t
WHERE student_id = s.id
) AS 'classes',
( SELECT GROUP_CONCAT(g.name)
FROM student_enrolled_groups_t AS eg
JOIN groups_t AS g ON eg.group_id = g.id
WHERE eg.student_id = s.id
) AS 'groups'
FROM student_t AS s
ORDER BY s.forename ASC;
It seems that student_enrolled_groups_t
is a many-to-many mapping table.似乎student_enrolled_groups_t
是一个多对多映射表。 In that case, get rid of id
and have these two indexes:在这种情况下,摆脱id
并拥有这两个索引:
PRIMARY KEY(student_id, group_id)
INDEX(group_id, student_id)
When writing JOINs
, please use the newer syntax involving ON
-- for saying how the tables are 'related'.在编写JOINs
时,请使用涉及ON
的较新语法——用于说明表是如何“相关”的。 Filtering is done in WHERE
.过滤在WHERE
中完成。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.