使用多个JOIN优化SQL查询

时间:2014-08-16 07:34:25

标签: mysql sql

如何优化此查询并提高其性能,

SELECT user.id,user.name,profile.info,score.amount
FROM user
LEFT JOIN profile ON profile.user_id = user.id AND profile.type = 'language'
LEFT JOIN score ON score.user_id = user.id AND score.type = 'total'
WHERE email = 'example@mail.com'

返回结果:

[id]       =>    1060225
[name]     =>    john
[info]     =>    En
[ammount]  =>    533

返回结果2:

[id]       =>    1022805
[name]     =>    karin
[info]     =>    
[ammount]  =>    11

表:

用户表

id     name         email
1      john      example@mail.com
2      karin     tt@kkk.com
3      Tom       kk@yahoo.com
4      kit       mm@gmail.com

个人资料表

id     user_id       type          info
1        1          is_admin       true
2        1          language        En
3        1          active         true
4        2          is_admin       false
1        1          like           null
2        2          favorite       null
3        3          is_admin       false
4        2          experience       4

得分表

id     user_id     type     amount
1         1        daily      33
2         1        total      533
3         2        total      11
4         3        daily      44

感谢,

3 个答案:

答案 0 :(得分:2)

对于此查询:

SELECT u.id, u.name, p.info, s.amount
FROM user u LEFT JOIN
     profile p
     ON p.user_id = u.id AND p.type = 'language' LEFT JOIN
     score s
     ON s.user_id = u.id AND s.type = 'total'
WHERE u.email = 'example@mail.com';

(我刚刚添加了表别名,以使查询更具可读性,并澄清列的来源。)

请尝试以下索引:

create index idx_user_email_id_name on user(email, id, name);
create index idx_profile_userid_type on profile(user_id, type);
create index idx_score_userid_type on score(user_id, type);

答案 1 :(得分:1)

您应该在profile上提供score(type, user_id)表复合索引。我不确定在索引中首先使用typeuser_id是否更好,您应该尝试每一个并查看哪个更好;您可以使用EXPLAIN来比较执行计划。

答案 2 :(得分:1)

您可以尝试在连接列上创建索引(如果不存在),并使用子查询而不是连接:

SELECT 
  id,
  name,
  (select info from profile where user_id = user.id AND type = 'language') as "info", 
  (select amount from score where user_id = user.id and type = 'total') as "amount"
FROM user
WHERE email = 'example@mail.com'

其他提示:检查执行计划,添加索引以避免在适当的情况下进行全表扫描,通过在必要时使用视图复制某些数据或使用视图来对表进行非规范化。