MYSQL:从一个用户组中选择用户,并从另一个组中排除用户 - 优化

时间:2011-03-23 03:31:15

标签: mysql many-to-many query-optimization

我在这里有一个优化问题。

背景

我在用户表中有12000个用户,每个用户都有记录。每个用户可以是零个或多个组。我有一个包含45个组的组表和一个包含75000个记录的groups_link表(以促进多对多的关系)。

我正在创建一个查询屏幕,允许用户从用户列表中过滤用户。

目标

具体来说,我需要帮助:选择一个组中但不在另一个组中的所有用户。

数据库结构

enter image description here

查询

我当前的查询运行得太慢了......

 SELECT U.user_id,U.user_email
FROM (sc_module_users AS U)
JOIN sc_module_users_groups_links AS group_join ON group_join.user_id = U.user_id
LEFT JOIN sc_module_users_groups_links AS excluded_group_join ON group_join.user_id = U.user_id
WHERE group_join.group_id IN (27) AND excluded_group_join.group_id NOT IN (19) OR excluded_group_join.group_id IS NULL AND U.user_subscribed=1 AND U.user_active=1
GROUP BY U.user_id,U.user_id

此查询需要9分钟才能完成,它会返回11,000条记录(12,000条记录)。

解释

以下是该查询的解释: enter image description here Click here for a closer look

任何人都可以帮助我将其优化到1分钟以下......

经过3次修改后,我将其更改为

    SELECT U.user_id,U.user_email FROM (sc_module_users AS U) WHERE ( user_country LIKE '%australia%' ) AND 
EXISTS (SELECT group_id FROM sc_module_users_groups_links l WHERE group_id in (31) AND l.user_id=U.user_id) AND 
NOT EXISTS (SELECT group_id FROM sc_module_users_groups_links l WHERE group_id in (27) AND l.user_id=U.user_id) 
AND U.user_subscribed=1 AND U.user_active=1 GROUP BY U.user_id

” mucccch更快

2 个答案:

答案 0 :(得分:1)

编辑:删除了我的查询建议,但索引内容仍应适用:

sc_module_users_groups_links上的索引可以通过在user_idgroup_id上创建综合索引来改进。索引中列的顺序可能会产生影响 - 我认为user_id首先应该会有更好的效果。

您还可以尝试删除link_id并仅使用复合主键,因为link_id似乎没有任何其他用途。

答案 1 :(得分:0)

我认为您需要做的第一件事就是放置括号:

// should be  
.. AND ( excluded_group_join.group_id NOT IN (19) 
  OR excluded_group_join.group_id IS NULL)  AND ....