Взгляд на оптимизацию запросов - PullRequest
0 голосов
/ 21 мая 2009

Я пытаюсь найти пользователей, которые имеют виды спорта и регионы, на которые ориентирован вид деятельности. В таблице acces [users] есть около 17K пользователей. У каждого может быть определенное количество спортивных интересов и один регион.

Здесь запрос ищет всех пользователей, которые имеют хотя бы один вид спорта и один регион, на которые ориентированы действия. Спорт может быть до 75, когда мы выбираем каждый из них [не совсем хорошо с запросом IN].

SELECT a.user, pp.courriel
FROM acces a
LEFT JOIN acces_profil_sport ap ON ap.id = a.id
LEFT JOIN profil_perso pp ON pp.id = a.id
WHERE ap.sport_id IN
  (
    SELECT ac.sport_id
    FROM activite_sport ac
    RIGHT JOIN activite a ON a.activite_id = ac.activite_id AND a.is_cron = 1 AND a.cron_processed = 0
   )
  AND pp.region_id IN
  (
    SELECT ar.region_id
    FROM activite_region ar
    RIGHT JOIN activite a ON a.activite_id = ar.activite_id AND a.is_cron = 1 AND a.cron_processed = 0
  )
GROUP BY a.id

Если я удалю спортивный поиск, выполнение запроса займет около 30 секунд. В противном случае это займет довольно много времени и использует около 99% процесса с mysql.

Какие-нибудь подсказки, чтобы помочь этому?

[редактировать: структура таблицы]
Доступ: id (первичный ключ), пользователь, perso _ id (ключ / внешний ключ к профилю _ perso [perso _ id]) [some-other-fields]
профиль _ чел.: чел. _ id (первичный ключ), курриель, регион _ id, id (внешний ключ для доступа [id]) [некоторые другие поля]
доступ _ профиль _ спорт: идентификатор / спорт _ идентификатор (двойной первичный ключ), niveau _ идентификатор (двойной ключ со спортом _ идентификатор)

Ответы [ 3 ]

4 голосов
/ 21 мая 2009

Я подозреваю, что ваши индексы неверны. Если вы распечатаете объяснение выбора ... , я могу лучше прокомментировать это. Кроме того, мне любопытно, почему вы делаете левые / правые объединения и подвыборы.

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

Что касается правильных объединений, вам нужен бит ar, который не является частью правой стороны. Я бы либо удалил их, либо сделал бы их прямыми соединениями. Я полагаю, поскольку вы проверяете, как выглядит необработанная работа cron, вы хотите оставить их.

SELECT a.user, pp.courriel
FROM acces 
JOIN acces_profil_sport ap ON ap.id = a.id
JOIN profil_perso pp ON pp.id = a.id
JOIN activite_sport ac ON ac.sport_id = ap.sport_id
JOIN activite a1 ON a.activite_id = ac.activite_id AND a.is_cron = 1 AND a.cron_processed = 0
JOIN activite_region ar ON ar.region_id = pp.region_id
JOIN activite a2 ON a.activite_id = ar.activite_id AND a.is_cron = 1 AND a.cron_processed = 0
0 голосов
/ 21 мая 2009
SELECT acces.user, courriel
FROM acces
JOIN profil_perso ON acces.id = profil_perso.id
WHERE EXISTS (SELECT 1 FROM acces_profil_sport JOIN activite_sport on acces_profil_sport.sport_id = activite_sport.sport_id JOIN activite ON activite.activite_id = activite_sport.activite_id WHERE is_cron = 1 AND cron_processed = 0 AND acces_profil_sport.id = profil_perso.id)
AND EXISTS (SELECT 1 FROM activite_region JOIN activite ON activite_region.activite_id = activite.activite_id WHERE is_cron = 1 AND cron_processed = 0 AND activite_region.region_id = profil_perso.region_id);
0 голосов
/ 21 мая 2009

Есть ли у вас индексы is_cron и cron_processed? Это может помочь ускорить процесс.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...