我正在学习MYSQL,并且有一些我一直在想的事情。
让我们采用这个简单的场景:一个假设的网站,用于参加在线课程,包括4个表:学生,教师,课程和注册(学生注册的每门课程一个条目)
您可以找到数据库生成代码on github。
虽然提供的数据库很小,但为了保持与我需要的帮助相关,我们假设这是一个足够大的数据库,效率将是一个真正的问题 - 让我们来看看说成千上万的学生,老师等。
就我对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以便能够破译结果。这里的任何见解也将非常受欢迎。
答案 0 :(得分:1)
我的'直觉'说首先得到的效率要高得多 我们需要的老师一行,然后加入其余的 相反的东西:
通过使用谓词Teachers.name = "Charles Darwin"
,您可以在方法1中为教师获取单行。查询优化器应确定在加入其他表之前使用此谓词限制Teacher
集更有效。
如果您不信任优化器或想要减少它所做的工作,您甚至可以使用SELECT STRAIGHT_JOIN ...
或STRAIGHT_JOIN
代替INNER_JOIN
强制执行表读取顺序以确保MySQL按照您在查询中指定的顺序读取表。
您的第二个查询会得到相同的答案,但可能效率较低,因为会为您的教师子查询创建一个临时表。
EXPLAIN
documentation是解释EXPLAIN
输出的良好来源。