1

我只是在学习 MYSQL 的过程中,并且有一些我一直想知道的事情。

让我们来看这个简单的场景:一个用于参加在线课程的假设网站,由 4 个表格组成:学生、教师、课程和注册(学生注册的每个课程一个条目)

您可以在 github 上找到 DB 生成代码。

虽然为了清晰起见,提供的数据库很小,但为了使其与我需要帮助的内容相关,让我们假设这是一个足够大的数据库,效率将是一个真正的问题——假设有数十万学生、教师等。



据我对 MYSQL 的了解,如果我们想要一张由“查尔斯·达尔文”教授的学生表,一个可能的查询是:

方法一

SELECT Students.name FROM Teachers
INNER JOIN Courses ON Teachers.id = Courses.teacher_id
INNER JOIN Registrations ON Courses.id = Registrations.course_id
INNER JOIN Students ON Registrations.student_id = Students.id
WHERE Teachers.name = "Charles Darwin"

这确实返回了我们想要的。

+----------------+
| name           |
+----------------+
| John Doe       |
| Jamie Heineman |
| Claire Doe     |
+----------------+


所以这是我的问题:

凭借我(非常)有限的 MYSQL 知识,在我看来,我们正在将JOIN元素添加到教师表中,这可能非常大,而我们最终只在一个教师之后,我们在最后过滤掉了他的查询。

我的“直觉”说,首先为我们需要的老师获得一行会更有效率,然后将剩余的东西加入其中:

方法二

SELECT Students.name FROM (SELECT Teachers.id FROM Teachers WHERE Teachers.name = 
"Charles Darwin") as Teacher
INNER JOIN Courses ON Teacher.id = Courses.teacher_id
INNER JOIN Registrations ON Courses.id = Registrations.course_id
INNER JOIN Students ON Registrations.student_id = Students.id

但真的是这样吗?假设有几千名师生,这比第一次查询效率高吗?可能是 MYSQL 足够聪明,能够以更高效的方式解析方法 1 查询。


另外,如果有人可以提出更有效的查询,我也会很感兴趣。

注意:我以前读过EXPLAIN用来确定查询的效率,但我对 MYSQL 的理解不够好,无法解读结果。这里的任何见解也将不胜感激。

4

1 回答 1

1

我的“直觉”说,首先为我们需要的老师获得一行会更有效率,然后将剩余的东西加入其中:

通过使用谓词,您在方法 1 中为教师获得了单行Teachers.name = "Charles Darwin"Teacher查询优化器应确定在加入其他表之前使用此谓词限制集合更有效。

如果您不信任优化器或想减少它所做的工作,您甚至可以强制表读取顺序使用SELECT STRAIGHT_JOIN ...orSTRAIGHT_JOIN而不是INNER_JOIN确保 MySQL 按照您在查询中指定的顺序读取表。

您的第二个查询会产生相同的答案,但可能效率较低,因为为您的教师子查询创建了一个临时表。

EXPLAIN文档是关于如何解释EXPLAIN输出的一个很好的来源。

于 2013-07-25T23:29:14.640 回答