Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > PHP: Базы Данных > оптимальная комбинация запросов на форум


Автор: bars80080 10.3.2010, 17:22
вот, смотрим на этот форум и видим список тем. в конце есть дата обновления и имя последнего отвечавшего.

вопрос: как бы это сделать оптимальней?

раньше бы (при малых объёмах постов и тем) я бы не стал заморачиваться, и даже не создал бы поля под это дело в таблице topics.
но допустим, количество посетителей будет такое же, как здесь. наверняка, лучше вставить дополнительные поля в таблицу topics: dateupdate и id_updater. и обновлять эти поля при каждом добавлении/редактировании поста в топик.
таким образом, мы устраняем по одному лишнему запросу на тему при выводе списка тем

теперь ещё одна заморочка. не будем же мы показывать id пользователей, надо отобразить имя. как это сделать?
единственное, что приходит в голову, так это при выборке топиков складировать все id_updater (а также id_creator) в массив, и затем провести дополнительный запрос на в таблицу users по набранным id.

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


или может я ошибаюсь в некой глобальной точке?

Автор: Ипатьев 10.3.2010, 17:51
А джойны совсем не рассматриваются?
Если первая задача денормализацией решается часто (но при этом усложняет обслуживание форума), то вторая-то как была джойном - так и остается.

Автор: bars80080 10.3.2010, 18:05
Цитата(Ипатьев @  10.3.2010,  16:51 Найти цитируемый пост)
А джойны совсем не рассматриваются?

очень даже рассматриваются.

сейчас попробую изобразить:

Код

SELECT * FROM `topics` LEFT JOIN `users` ORDERS ON (topics.id_creator=users.id OR topics.id_updater=users.id) 
    WHERE `directory`=4 ORDER BY `dateupdate` DESC LIMIT 1, 50


однако, 
Цитата(bars80080 @  10.3.2010,  16:22 Найти цитируемый пост)
что-то мне не кажется, что составной запрос, где имя пользователя получается сразу, будет быстрее

считаете, что не прав. создавать и мерять что ли?

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

Автор: skyboy 10.3.2010, 18:10
зачем left join?
даже если юзеры "удаляются", ничего не мешает оставлять их в базе и помечать "удаленными". при этом, использовать inner join во всех соответствующих запросах.
тебе ж имя пользователя понадобится при выводе сообщений темы - не будешь же ты при удалении пользователя удалять и все его сообщения, правда?

Добавлено через 35 секунд
Цитата(bars80080 @  10.3.2010,  17:05 Найти цитируемый пост)
считаете, что не прав. создавать и мерять что ли?

inner join по числовому полю, ещё и первичному ключу - разницы практически не будет.

Автор: bars80080 10.3.2010, 18:16
Цитата(skyboy @  10.3.2010,  17:10 Найти цитируемый пост)
зачем left join?

понятия не имею. физически не могу представить эту операцию (сколько не читал). поэтому просто передрал


Цитата(skyboy @  10.3.2010,  17:10 Найти цитируемый пост)
inner join по числовому полю, ещё и первичному ключу

то есть так:
Код

SELECT * FROM `topics` INNER JOIN `users` ORDERS ON (topics.id_creator=users.id OR topics.id_updater=users.id) 
    WHERE `directory`=4 ORDER BY `dateupdate` DESC LIMIT 1, 50

?

первичный ключ, в смысле, id в users отмечено primary key и этого хватит?

Автор: nerezus 13.3.2010, 00:58
Цитата

физически не могу представить эту операцию (сколько не читал). поэтому просто передрал
 Сделай себе 2 таблички (id: 1,2,3  name: a,b,c)  и (id: 2,3,4  name: d,e,f) и попробуй над ними все типы джойнов. Поймешь по результату.

Автор: Wolf1994 13.3.2010, 08:40
Цитата(bars80080 @  10.3.2010,  17:22 Найти цитируемый пост)
но допустим, количество посетителей будет такое же, как здесь. наверняка, лучше вставить дополнительные поля в таблицу topics: dateupdate и id_updater. и обновлять эти поля при каждом добавлении/редактировании поста в топик.

IMHO, так можно поступить и с именами пользователей: минус один запрос при выводе списка тем с создавшим, последним отписавшимся в тему, плюс дополнительные возможности по поиску тем по автору - задаётся маска имени и одним запросом находятся сообщения всех участников с похожими именами, возможно, есть ещё какие-то плюсы... Для вывода сообщений в полном формате - либо JOIN, либо два SQL: один на выбор топиков, второй - информации об авторах по массиву идентификаторов полученному в первом запросе.

Автор: Ипатьев 13.3.2010, 09:19
Wolf1994, ну если у вас нет опыта веб-разработки, то читайте хотя бы тему перед тем, как в нее писать. Никакого дополнительного запроса для имени автора и так не делается. Имя автора вообще не проблема для запросов, каких угодно - что для вывода тем, что для поиска авторов. Все делается джойном.

Автор: Wolf1994 13.3.2010, 15:16
Я прочитал тему.

Прошу прощения, если что-то неправильно понял, но, кажется, речь всё же шла о выборе между вариантом с двумя простыми запросами:
Цитата(bars80080 @  10.3.2010,  17:22 Найти цитируемый пост)
единственное, что приходит в голову, так это при выборке топиков складировать все id_updater (а также id_creator) в массив, и затем провести дополнительный запрос на в таблицу users по набранным id.

и составным запросом:
Цитата(bars80080 @  10.3.2010,  17:22 Найти цитируемый пост)
что-то мне не кажется, что составной запрос, где имя пользователя получается сразу, будет быстрее. али я не прав?

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

Суть моего комментария сводится к тому, что, в некоторых случаях, можно обойтись без этих двух вариантов, занеся информацию о name_creator, name_updater в таблицу топиков, в дополнение к id_creator, id_updater.

И раз уж коснулся упоминания двух вышеназванных методов выборки, то выскажу мнение человека далёкого от веб-разработки и по этому вопросу: два простых SQL предпочтительнее работы с JOIN.

Автор: Ипатьев 13.3.2010, 15:28
Цитата(Wolf1994 @  13.3.2010,  15:16 Найти цитируемый пост)
так как он осложняет и замедляет выборку

ответ был дан выше:
Цитата(skyboy @  10.3.2010,  18:10 Найти цитируемый пост)
разницы практически не будет. 


что же касается
Цитата(Wolf1994 @  13.3.2010,  15:16 Найти цитируемый пост)
два простых SQL предпочтительнее работы с JOIN. 

то это просто заблуждение.

Автор: Wolf1994 13.3.2010, 16:34
Это моё мнение. Ваше право считать его заблуждением.

Автор: Ипатьев 13.3.2010, 16:56
Беда в том, что такое "мнение", иррелевантное как задангному вопросу, так объективной реальности, у вас при каждой попытке что-то написать в этот раздел форума.

Автор: Wolf1994 13.3.2010, 17:11
Тем не менее, я оставляю за собой право его высказывать, без претензии на абсолютную истину.

Автор: skyboy 13.3.2010, 21:15
Цитата(Wolf1994 @  13.3.2010,  14:16 Найти цитируемый пост)
два простых SQL предпочтительнее работы с JOIN.

- накладные расходы на передачу запроса и обработку ответа от СУБД удваиваются
- оптимизатор работает с двумя отдельными запросами и результат оптимизации может быть хуже, чем если бы он получал сразу один запрос
- с точки зрения читаемости, код проигрывает, потому что логика выборки данных оказывается разделена между разными запросами и "разбавлена" дополнительными конструкциями(присваивания, условия или что там ещё)
если бы был подзапрос, приводящий к using temporary, то можно было бы ещё о чем-то спорить и делать замеры. а так как мы говорим про join, то я даже не берусь придумать причину, по которой два запроса были бы предпочтительнее одного.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)