洞察查询优化

时间:2009-05-21 17:25:37

标签: php sql mysql optimization

我在这里尝试基本上找到有体育用户的用户活动所针对的地区。在acces [users]表中,大约有17K用户。每个人都可以拥有一定数量的体育兴趣和一个地区。

这里有查询查找每个拥有一项运动&至少通过活动定位的一个区域。当我们选择每个em时,体育可以达到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秒才能运行。否则它需要非常永久,并使用mysql大约99%的proc。

有任何提示可以帮助吗?

[编辑:表格结构]
Acces:id(主键),用户,perso _ id(对于profil _ perso [perso _ id]的键/外键)[some-other-fields]
profil _ perso:perso _ id(主键)courriel,区域_ id,id(访问[id]的外键)[其他一些字段]
访问_ profil _ sport:id / sport _ id(双主键),niveau _ id(带有运动_ ID的双键)

3 个答案:

答案 0 :(得分:4)

我怀疑你的索引是错误的。如果您打印出 explain select ... ,我可以更好地评论。此外,我很好奇你为什么要做左/右连接和子选择。

在我看来,这些都应该是正常连接,因为两个左连接只有在它们存在时才会起作用。如果它们为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

答案 1 :(得分:0)

您有is_croncron_processed的索引吗?它可以帮助加快速度。

答案 2 :(得分: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);