我正在试图弄清楚如何加速使用连接和分组的查询来从表中获取行作为另一个表中的列,并且还使用having子句。
我有以下两个表:
用户:
id name
1 bob
2 joe
3 paul
财产:
id user_id type_id type name
1 1 1 car honda
2 1 2 computer mac
3 2 1 car toyota
4 2 2 computer pc
5 2 3 phone htc
6 3 1 car toyota
7 3 2 computer pc
8 3 3 phone samsung
我正在使用以下查询:
select
p.user_id,
u.name,
max(case when p.type=1 then p.name end) as car,
max(case when p.type=2 then p.name end) as computer,
max(case when p.type=3 then p.name end) as phone
from
possesions p inner join users u
on p.user_id=u.id
group by
p.user_id,
u.name
having
car='toyota'
将此作为输出:
user_id name car computer phone
2 joe toyota pc htc
3 paul toyota pc samsung
有大量的数据 - 大约75,000个用户,20万个拥有者和25种不同的拥有类型。查询大约需要5秒钟。当我对查询做一个解释时,我得到了这个:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE users index (NULL) PRIMARY 4 (NULL) 77453 Using index
1 SIMPLE possesions ref FK_possessions_users FK_possessions_users 4 mydb.users.id 1
我在所有id列上都有索引。只是想知道我还能做些什么来加快速度。如果我删除HAVING子句,它当然会变得很快。非常感谢任何帮助,谢谢。
答案 0 :(得分:0)
这是您的查询:
select u.id, u.name,
max(case when p.type = 1 then p.name end) as car,
max(case when p.type = 2 then p.name end) as computer,
max(case when p.type = 3 then p.name end) as phone
from users u join
possesions p
on p.user_id = u.id
group by u.id, u.name
having car = 'toyota';
MySQL基本上没有提供优化聚合查询的机会。您可以将其更改为join
版本以查看是否有效。因此,假设每种类型最多出现一次:
select u.id, u.name, pc.name as car, pcomp.name as computer, pp.name as phone
from users u join
possesions pc
on pc.user_id = u.id and
pc.type = 1 and pc.name = 'toyota' left join
possessions pcomp
on pcomp.user_id = u.id and pcomp.type = 2 left join
possessions pp
on pp.user_id = u.id and pp.type = 3;
为此,您需要pc(user_id, type, name)
上的索引。
注意:查询的节省是避免使用group by
进行聚合。如果给定类型有多个名称,则无论如何都可能需要聚合。