Выборка из нескольких таблиц

530
07 февраля 2017, 22:48

Доброго времени суток. Помогите решить задачу с MySQL (знаком довольно плохо):

Есть 5 таблиц:

games (id, name, info)
platforms (id, name, info)
categories (im, name, info)
games_platforms_assign (game_id, platform_id)
games_categories_assign (game_id, category_id)

Соответственно, таблица games имеет связи многие-ко-многим с таблицами platforms и categories. Необходимо выбирать все games, относящиеся к заданным platforms.name и categories.name. Делаю так:

SELECT games.*
FROM games
  JOIN games_platforms_assign On games.id = games_platforms_assign.game_id
  JOIN platforms ON platforms.name = 'pc' AND games_platforms_assign.platform_id = platforms.id
  JOIN games_categories_assign ON games.id = games_categories_assign.game_id
  JOIN categories ON categories.name = 'action' AND games_categories_assign.category_id = categories.id;
 

Результат выборки соответствует ожиданиям, но скорость выполнения ужасно медленна. Пробовал с помощью вложенных SELECTов - получалось в разы медленнее.

Как переделать запрос для существенного ускорения выполнения? Или, в крайнем случае, как лучше переделать структуру базы данных под подобные запросы?

Answer 1

Я бы перенёс изменяемые условия в WHERE. Это(в некоторых сценариях) позволит переиспользовать результат prepare.
Использование псевдонимов таблиц

SELECT g.id, g.name, g.info
FROM games g
  JOIN games_platforms_assign gp On g.id = gp.game_id
  JOIN platforms p ON gp.platform_id = p.id
  JOIN games_categories_assign gc ON g.id = gc.game_id
  JOIN categories c ON gc.category_id = c.id
WHERE p.name = ? AND c.name = ?

Абсолютно необходимо создать индексы(а лучше foreign keys) на поля-связки (game_id, platform_id, category_id) и индексы на поля поиска(name).

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

Answer 2
SELECT g.id g.name g.info
FROM games g
LTFT JOIN games_platforms_assign gpa ON (gpa.game_id = g.id)
LEFT JOIN games_categories_assign gca ON (gca.game_id = g.id)
LEFT JOIN platforms p ON (p.id = gpa.game_id)
LEFT JOIN categories c ON (c.id = gca.game_id)
WHERE p.name = .... AND c.name = ....
READ ALSO
Вывод контента в зависимости от страны

Вывод контента в зависимости от страны

Здравствуйте, стоит такая задачав контактах для посетителей страны России показывать один блок контактов, для посетителей с Украины другой,...

651
Не работает функция console.log

Не работает функция console.log

Нативная функция consolelog ничего не выводит в firebug окне

1736
Не поддаётся regexp

Не поддаётся regexp

Суть в чем, делаю расширение для хром, ему нужно обработать адрес открытой страницыСтруктура сайта такая: http://site

560
Проблема с закладками Яндекс

Проблема с закладками Яндекс

У меня возникла проблемаЯ поменял домен, но все ссылки нормально работают, кроме закладок яндекс

570