2009-05-21 3 views
0

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

Здесь запрашивается каждый пользователь, у которого есть один вид спорта & один регион, по крайней мере, предназначенный для деятельности. Спорт может быть до 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% proc с mysql.

Любые подсказки, которые помогут вам?

[править: Структура таблицы]
Acces: идентификатор (первичный ключ), пользователь, персидско _ ID (ключ/внешний ключ Profil _ персидско [персидско _ ID]) [некоторые-другие-поля]
Profil _ персидско: персидско _ идентификатор (первичный ключ) courriel, область _ идентификатор, идентификатор (внешний ключ к Acces [ID]) [другие поля]
Acces _ Profil _ спорта: идентификатор/спорт _ идентификатор (двойной первичный ключ), niveau _ ID (двойной ключ со спортом _ ID)

+1

Не могли бы вы указать, с какими таблицами вы работаете, и каковы столбцы? –

+0

Правильно ли индексируются ваши таблицы? Хотя этот запрос невелик, кажется, что он не должен * * * длиться относительно относительно небольшом наборе данных, с которым вы работаете. –

+0

Вы не дали нам 2 таблицы в этом редактировании. Показывая мне, что «объяснение» в этом вопросе также даст много информации о том, где, вероятно, отсутствует индекс. –

ответ

4

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

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

Что касается правого соединения, вам нужен бит 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

Это будет обработано cron ночной ... вид почтового списка-ish – Erick

+0

Nice one! только 0,4 с! это то, что вам нужно. – Erick

+0

Neato, в значительной степени то, что я собираюсь предложить, хорошее решение! –

0

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

0
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

Зачем использовать подзапрос, в котором соединение разрешает его? Подзапросы, как правило, создают дополнительные накладные расходы, а в некоторых случаях значительно замедляются. –

+0

Как я уже упоминал в комментарии выше, я думаю, что может быть «отдельный», который необходимо использовать только для соединения. Использование «где существует» для объединения таблиц хорошо работает в большинстве БД, хотя я признаю, что я не очень много использую MySQL и не знал, что его можно избежать. – araqnid

Смежные вопросы