slow-log中记录:
SQL1:select t.CallerPhone,t.CompanyId as Id,c.Name from (select p.CallerPhone,p.CompanyId from PhoneBill
p group by p.CompanyId,p.CallerPhone order by p.StartTime desc limit 5) as t,companies c where t.CompanyId=c.Id;
每条查询耗时4.0s+;
SQL2:test> select sql_no_cache p.CallerPhone,p.CompanyId Id,c.Name from PhoneBill p left join companies c on p.CompanyId=c.Id group by p.CompanyId,p.CallerPhone order by p.StartTime desc limit 5;
test > desc select sql_no_cache t.CallerPhone,t.CompanyId as Id,c.Name from (select p.CallerPhone,p.CompanyId from PhoneBill p group by p.CompanyId,p.CallerPhone order by p.StartTime desc limit 5) as t,companies c where t.CompanyId=c.Id;
+----+-------------+------------+--------+---------------+---------+---------+-------------+--------+---------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+--------+---------------+---------+---------+-------------+--------+---------------------------------+
| 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 5 | | 
| 1 | PRIMARY | c | eq_ref | PRIMARY | PRIMARY | 4 | t.CompanyId | 1 | | 
| 2 | DERIVED | p | ALL | NULL | NULL | NULL | NULL | 220955 | Using temporary; Using filesort | 
+----+-------------+------------+--------+---------------+---------+---------+-------------+--------+---------------------------------+

test > desc select sql_no_cache p.CallerPhone,p.CompanyId Id,c.Name from PhoneBill p left join companies c on p.CompanyId=c.Id group by p.CompanyId,p.CallerPhone order by p.StartTime desc limit 5;
+----+-------------+-------+--------+---------------+---------+---------+-----------------+--------+---------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+---------------+---------+---------+-----------------+--------+---------------------------------+
| 1 | SIMPLE | p | ALL | NULL | NULL | NULL | NULL | 220955 | Using temporary; Using filesort | 
| 1 | SIMPLE | c | eq_ref | PRIMARY | PRIMARY | 4 | b2c.p.CompanyId | 1 | | 
+----+-------------+-------+--------+---------------+---------+---------+-----------------+--------+---------------------------------+

都出现耗得 temporary 和 filesort,
但按道理似乎应该 SQL2 比 SQL1 写的更好,通过profile SQL2 却在filesort 上也耗了相当长时间,导致实际查询中SQL2所耗时间差不多是SQL1两倍;而 SQL1 主要花销都在 temporary 这一步。
MySQLPerformance 关于 filesort 的解释是 “ Anytime a sort can’t be performed from an index, it’s a filesort. ”
(不能通过索引进行的排序--filesort)
再对表 PhoneBill 创建复合索引:
test > create index CompanyId_CallerPhone_StartTime on PhoneBill(CompanyId,CallerPhone,StartTime);
test > desc select sql_no_cache t.CallerPhone,t.CompanyId as Id,c.Name from (select p.CallerPhone,p.CompanyId from PhoneBill p group by p.CompanyId,p.CallerPhone order by p.StartTime desc limit 5) as t,companies c where t.CompanyId=c.Id;
+----+-------------+------------+--------+---------------+---------------------------------+---------+-------------+--------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+--------+---------------+---------------------------------+---------+-------------+--------+----------------------------------------------+
| 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 5 | | 
| 1 | PRIMARY | c | eq_ref | PRIMARY | PRIMARY | 4 | t.CompanyId | 1 | | 
| 2 | DERIVED | p | index | NULL | CompanyId_CallerPhone_StartTime | 95 | NULL | 232706 | Using index; Using temporary; Using filesort | 
+----+-------------+------------+--------+---------------+---------------------------------+---------+-------------+--------+----------------------------------------------+

test > desc select sql_no_cache p.CallerPhone,p.CompanyId Id,c.Name from PhoneBill p left join companies c on p.CompanyId=c.Id group by p.CompanyId,p.CallerPhone order by p.StartTime desc limit 5;
+----+-------------+-------+--------+---------------+-----------+---------+-----------------+------+-----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+---------------+-----------+---------+-----------------+------+-----------------+
| 1 | SIMPLE | p | index | NULL | StartTime | 8 | NULL | 5 | Using temporary | 
| 1 | SIMPLE | c | eq_ref | PRIMARY | PRIMARY | 4 | b2c.p.CompanyId | 1 | | 
+----+-------------+-------+--------+---------------+-----------+---------+-----------------+------+-----------------+

两条SQL耗时都0.4s左右,不可避免的join而Using temporary;
最后改动 对companies表增加冗余字段,避免了表联合,也不需要复合索引。