2013-07-25 3 views
1

Я только что изучаю MYSQL и имею то, о чем мне было интересно.Более эффективно использовать подзапрос перед внутренними соединениями?

Давай этот простой сценарий: гипотетический сайт с онлайн-курсами, состоящий из 4-х таблиц: студентов, преподавателей, курсы и регистраций (один входа на курс, который студент зарегистрирован)

Вы можете найти Код генерации DB on github.

Хотя предоставленная БД для ясности является крошечной, чтобы учесть ее в том, что мне нужно, давайте предположим, что это с достаточно большой базой данных, где эффективность будет реальной проблемой, скажем, сотнями тысяч студентов, учителей и т.д.



насколько я понимаю, с MYSQL, если мы хотим, чтобы таблица студентов преподается «Чарльз Дарвин», один возможный запрос будет таким:

Метод 1

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 -ing элементы на стол учителя, который может быть довольно большим, в то время как мы, в конечном счете, только после одного учителя, которого мы отфильтровываем в самом конце запроса.

Мой «Интуиции» говорит, что было бы гораздо эффективнее сначала получить одну строку для учителя нам нужно, а затем присоединиться оставшиеся вещи на том, что вместо:

Метод 2

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

Я могу дать частичный ответ: если два запроса действительно эквивалентны, вся суть использования РСУБД заключается в том, что вам не нужно беспокоиться об этой оптимизации. Оптимизатор запросов должен отобразить этот материал для вас. Тем не менее, многие оптимизаторы нуждаются в большом руководстве, что приводит к переписываниям, которые очень похожи на тот, который вы предоставили. Это зависит от конкретной базы данных (и запроса). – mzedeler

ответ

1

Мой «Интуиция» говорит, что было бы гораздо эффективнее сначала получить одну строку для учителя нам нужно, а затем присоединиться к оставшейся вещи на том, что вместо:

Вы получение одной строки для учителя в методе 1 с использованием предиката Teachers.name = "Charles Darwin". Оптимизатор запросов должен определить, что более эффективно ограничивать набор Teacher с использованием этого предиката перед присоединением к другим таблицам.

Если вы не доверяете оптимизатору или хотите, чтобы уменьшить работу он делает вы можете даже заставить таблицу чтения порядка с помощью SELECT STRAIGHT_JOIN ... или STRAIGHT_JOIN вместо INNER_JOIN, чтобы убедиться, что MySQL читает таблицы в том порядке, указанные вами в запросе.

Ваш второй запрос приводит к тому же ответу, но может быть менее эффективным, поскольку временная таблица создается для подзапроса учителя.

EXPLAIN documentation - хороший источник информации о том, как интерпретировать вывод EXPLAIN.

 Смежные вопросы

  • Нет связанных вопросов^_^