2 Выберите или 1 Присоединитесь к запросу? - PullRequest
8 голосов
/ 13 июня 2010

У меня есть 2 таблицы:

книга (id, название, возраст) ----> 100 миллионов строк

автор (id, book_id, имя, рождение) ----> 10 миллионов строк

Теперь, предположим, у меня есть общий идентификатор книги. Мне нужно распечатать эту страницу:

Title: mybook

authors: Tom, Graham, Luis, Clarke, George

Итак ... каков наилучший способ сделать это?

1) Простое соединение, как это:

Select book.title, author.name 
From book, author 
WHERE ( author.book_id = book.id ) AND ( book.id = 342 )

2) Чтобы избежать объединения, я мог бы сделать 2 простых запроса:

Select title FROM book WHERE id = 342

Select name FROM author WHERE book_id = 342 

Какой самый эффективный способ?

Ответы [ 5 ]

8 голосов
/ 13 июня 2010

Первый. Это всего одна поездка туда и обратно. Требуется небольшая обработка, чтобы свести строки авторов в список через запятую, как вы хотите, но это в основном стандартный код.

Отдельные связанные запросы - вредная привычка, которая убивает вашу производительность быстрее, чем большинство вещей.

2 голосов
/ 13 июня 2010

Лучший вариант - запустить тесты скорости на вашем собственном сервере. В зависимости от того, как часто к различным таблицам обращаются вместе и независимо друг от друга, любая из них может быть быстрее.

На этот вопрос подробно отвечали ранее: ВЛЕВО СОЕДИНЕНИЯ против нескольких операторов SELECT

1 голос
/ 13 июня 2010

Минимизация в оба конца и продвижение вменяемых планов выполнения - самые заметные пункты в моем списке производительности.

Если у вас возникла ситуация со статическими зависимостями между полями в запросе, не позволяющая оптимизатору использовать индекс, а затем ломатьих использование в отдельных запросах может обеспечить огромный прирост производительности, поскольку используются индексы и увеличивается число строк набора данных.Для большинства транспортных протоколов базы данных дополнительные наборы результатов равны дополнительным циклам.Это может потенциально повлиять на производительность, если к данным регулярно обращаться через глобальную сеть.К счастью, есть способы получить свой торт и съесть его тоже:

Select title,NULL AS name FROM book WHERE id = 342 
UNION ALL
Select NULL,name FROM author WHERE book_id = 342 

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

1 голос
/ 13 июня 2010

Первый, особенно если у вас есть индекс на author.book_id. Закрытый индекс был бы лучше, если бы у вас было много книг для авторов, и это возможно, в противном случае незакрытый индекс также очень вам помог бы.

0 голосов
/ 13 июня 2010

Я знаю, что это не должно учитываться, но первый запрос вернет вам результирующий набор, подобный этому:

title     name
-----------------
mybook    Tom
mybook    Graham
mybook    Luis
mybook    Clarke
mybook    George

тогда как вторая пара вернет вам пару наборов результатов, как это:

title
-------
mybook

и

name
--------
Tom
Graham
Luis
Clarke
George

поэтому каждый подход возвращает данные по-своему. В этом простом примере повторение названия книги не будет значительным, но если бы вместо заголовка вы возвращали первую главу (скажем), это было бы менее эффективно, поскольку было бы много повторных данных. Таким образом, хотя второе может занять больше времени в базе данных, оно может быть быстрее и эффективнее при отправке этих данных по сети.

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

...