На мой взгляд, основная проблема с вашим запросом - это сочетание левого и правого внешних соединений. Честно говоря, вы можете это правильно прочитать?
Одно только первое соединение кажется странным. Вы присоединяете пост к его тегам поста. Но может ли тег сообщения существовать без сообщения? К чему бы это относилось? (Было бы более разумно и наоборот: также выбирать сообщения, у которых нет тегов.) Если я не ошибаюсь, ваше соединение преобразуется в простое внутреннее соединение. В предложении where вы дополнительно ограничиваете этот результат тегами публикации с именем 'gameday'.
Затем вы выполняете правое внешнее соединение с пользователями. Мы избегаем правых внешних объединений, поскольку они гораздо менее читабельны, чем левые внешние объединения, но что ж, вы выбираете всех пользователей, даже тех, у кого нет тегов сообщений 'gameday'.
Затем вы оставили внешнее объединение для всех тегов 'gameday' . Это выглядит совершенно не связанным с другими таблицами (т.е. вы либо находите теги «gameday», либо нет). Но в своем объяснении вы говорите: «Таблица Post_tags содержит внешний ключ из тегов», поэтому я предполагаю, что в вашей таблице тегов сообщений нет tag_id, но на самом деле имя - это идентификатор тега (и, следовательно, также внешний ключ в тегах сообщений стол). Это снова приводит к вопросу: зачем вообще существовать тег поста, если он не имеет связанного тега? Вероятно, это невозможно, и снова все сводится к простому внутреннему соединению. (Я бы порекомендовал здесь иметь tag_id
вместо имен в обеих таблицах, просто для удобства чтения. Имя столбца name
как бы скрывает отношения внешнего ключа.)
В вашем запросе вы не используете не показывает никакой информации из таблицы тегов сообщений, но я вижу, что вы выбрали pt.post_id as tag_post_id
, что, конечно же, снова просто p.id as tag_post_id
. Я полагаю, это опечатка, и вы хотите вместо этого показать pt.id as tag_post_id
?
Я понимаю, что вы хотите видеть всех пользователей, но вас интересуют только теги сообщений 'gameday'. Это немного усложняет написание запроса. Я бы, вероятно, просто выбрал пользователей и присоединился к полной информации тегов сообщения.
Ваш create_date
не соответствует таблице. Полагаю, это столбец в таблице сообщений?
Это вопрос, который я задаю:
select
gdp.*,
u.unique_id,
u.nick_name,
u.avatar_thumb
from tt_users u
left join
(
select
p.*,
t.desc as tag_desc,
pt.id as tag_post_id
from tt_tags t
join tt_post_tags pt on pt.name = t.name
join tt_posts p on p.id = pt.post_id
where t.name = 'gameday'
) gdp on gdp.user_id = u.user_id
order by p.create_date desc;
Я много гадал, поэтому этот запрос все еще может немного отличаться от того, что вам нужно. Я не знаю.
Теперь давайте посмотрим, к каким столбцам таблицы осуществляется доступ, чтобы обеспечить хорошие индексы для запроса. Давайте особенно посмотрим на подзапрос, в котором мы собираем все теги постов:
- Нам нужны только теги 'gameday'. Поскольку это, по-видимому, первичный ключ для tt_tags, уже должен быть уникальный индекс для
tt_tags(name)
. - Поскольку это внешний ключ, также должен быть индекс для
tt_post_tags(name)
. Это хорошо, но, поскольку мы хотим продолжить присоединение к post_id
, было бы полезно иметь и это в индексе: create unique index idx on tt_post_tags(name, post_id)
. Однако, поскольку это естественный ключ таблицы, этот индекс также должен существовать, чтобы гарантировать целостность данных. Если его еще нет, поспешите предоставить. - Наконец, мы присоединяем
tt_posts
по его первичному ключу (т.е. должен быть индекс по tt_posts(id)
). Еще раз: нам здесь нечего делать.
Вы выбираете всех пользователей и выбираете все теги 'gameday'. Затем вы должны присоединить все найденные теги к пользователям, что уже является некоторой работой. Вы можете представить это как упорядочение всех найденных тегов по user_id
, чтобы присоединиться. Затем вы хотите отсортировать результат по дате публикации. Это означает, что СУБД должна снова отсортировать все строки результатов. Сортировка требует времени; так оно и есть. Сколько строк в результате? Если мы говорим о миллионах строк для сортировки, то это, вероятно, останется медленным. И если многие пост-теги являются тегами «игрового дня», то даже индексы могут не сильно помочь при чтении таблиц, а вместо этого СУБД может go для полного последовательного чтения таблицы. Убедитесь, что статистика актуальна (https://dev.mysql.com/doc/refman/8.0/en/analyze-table.html).