Имеются следующие таблицы:
matches: id, start_time, tournament_id
teams: id, name, logo
matches_teams: id, match_id, team_id
tournaments: id, name
Сейчас полную инфу о матчах получаю следующим образом:
1. Одним запросом получаю matches.id, matches.start_time, tournaments.name
2. Далее циклом для каждого матча из п1 делаю еще два запроса - для первой команды и для второй.
В итоге получаю примерно такой массив:
match_id
match_start_time
tournament_name
team_A_name
team_A_logo
team_B_name
team_B_logo
И получается, что для получения 20 матчей делается 60 запросов (для получения инфы для одной лишь страницы).
Исходя из этого есть несколько вопросов
1. как можно оптимизировать запросы?
2. что лучше, несколько простых запросов или один сложный?
3. можно ли средствами mysql получать вложенные массивы? чтобы не было $result['team_A_name'], $result['team_A_logo'], а было $result['team_A']['name'], $result['team_A']['logo'] (php). Сейчас делаю это с помощью php, "конфигурируя" новый массив с вложенной структурой
во первых - это не показатель, во вторых - банально внесение данных из внешних источников в бд, как пример.
UPD: иногда есть задача выбирать запрос по результату предыдущего рекурсивно, там тоже проще циклом, чем городить 20 запросов вложенными подзапросами...
Не силён в этом, но скажу то, что знаю, ответив на список вопросов, могу и ошибаться:
1) количество запросов можно сократить, использовав JOIN (LEFT JOIN). Но тут важно не перестараться: много JOINов в одном запросе - это не хорошо. И ещё, нужно знать, что объединение создаёт временную таблицу и если туда попадёт поле типа blob или таблица будет превышать лимит размера временных таблиц, то, скорее всего (а может и не скорее всего, а однозначно) таблица будет писаться на диск, что очень сильно будет тормозить ответ.
2) лучше среднее между одним сложным и несколькими простыми.
3) средствами СБД многомерный массив не получить, на сколько я знаю.
ThunderCat, ну на счёт инсертов - да. На счёт батчинга и прочих штук говорить не буду, т.к. это демагогия будет уже. Но мы же в данном случае говорим о селектах и тут ситуация чуть иная.
И да, рекурсивные делаются одним запросом через переменные или union с подзапросом как бы =)))
рекурсивные делаются одним запросом через переменные
это в том случае если они имеют прямую связь через релации. Есть случаи когда релации/условия получают из внешнего источника, например из внешнего апи. Секурити, блокчейн и вот это все...
В целом запросы в цикле - однозначное зло, но говорить что этого всегда можно избежать - слишком категорично.
Игорь, это в каких таких случаях нельзя избежать запросов в циклах? За всю мою практику не сталкивался с такими.
Я часто использую ORM в своих проектах, моя цель абстрагироваться от SQL это имеет косвенное отношение к вопросу.
Если речь идёт о нормализованной базе данных со сложной структурой, это я имел в виду.
Обратите внимание на пример.
Сколько нужно выполнить запросов в базу данных что бы построить такое дерево?
Каждый объект представляет собой отдельную таблицу.
1) как уже указал вам Кирилл Несмеянов - читайте про джоин, ин и вложенные запросы, задача как раз классическая на джоин и ин.
2) Абсолютно верно замечено John Didact - из бд вы ВСЕГДА получаете "плоские" данные, однако вы можете для себя их разделить префиксами в алиасах и обработать на стороне кода как удобно.
3) Большой запрос с множеством джоинов почти всегда лучше нескольких маленьких. Исключение - большие массивы текстовых/блоб полей, но и это обычно не критично, если выставить адекватные лимиты. Как минимум, преимущество в возможности удобного кеширования. Плюс время на открытие/закрытие соединения, плюс не надо гонять туда-сюда полученные данные несколько раз.