为什么内连接比单独的查询慢

时间:2014-02-14 04:51:31

标签: mysql sql join

我有以下表格

用户表

  • columns:id,email
  • index on:id

位置表

  • 列 - > id,name,user_id,last_scan_time
  • index on:id,user_id

项目表

  • 列 - > id,name,location_id,last_scan_time
  • index on:id,location_id

我必须运行此查询才能获取项目

select items.* from items 
inner join locations on (items.last_scan_time = locations.last_scan_time and      items.location_id = locations.id)
inner join users on (locations.user_id = users.id and users.email = 'abc@abc.com')

以上查询需要13秒才能获得1056870行

现在,如果我单独拆分每个查询而不是连接,则需要更少的时间

select id from users where email = 'abc@abc.com'
0.0 sec

select id,last_scan_time from locations where user_id = #user-id-returned-from-above-query#
0.0 sec

select * from items where last_scan_time = #last_scan_time-from-above-query# and  location_id = #location-id-from-above-query#
0.01 sec

为了使连接查询运行得比单个查询的总时间更快,我必须对连接查询进行哪些更改?

请帮忙。

谢谢你,
萨钦

2 个答案:

答案 0 :(得分:0)

您的查询格式为(重新格式化):

SELECT i.* 
  FROM items i
  JOIN locations l 
    ON l.last_scan_time = i.last_scan_time
   AND l.id = i.location_id
  JOIN users u
    ON u.id = l.user_id 
   AND u.email = 'abc@abc.com'

所以基本上,查询中的谓词是:

  • email表格的users列上的eq文字

  • user_id表的locations列的eq参考

  • eq ref location_id last_scan_time items

这表明对于此特定查询,最佳索引可能类似于:

... ON users (email,id)

... ON locations (id, last_scan_time)

... ON items (location_id, last_scan_time)

但是这个建议实际上取决于实际的表定义,表是MyISAM还是InnoDB,基数和数据分布等等。

我建议您使用EXPLAIN <query>来获取查询执行计划。

答案 1 :(得分:0)

一个更好的例子是,如果你想运行一个涉及两组数据交集的查询,这些数据在某种程度上是独立的数据部分...例如,如果你有一个事件表,那么事件就有EventTypes和EventTypes有一个属性“仅限单打”。然后你有一个Users表,用户有MaritalStatus,MaritalStatus有一个标志“Single”。您当然也有一个Attending表将事件映射到用户。

如果你想知道是否有任何非单身人士报名参加你的单打活动,那么正确的答案不是写一个通过ID将这些表连接在一起的查询,然后在where子句中对其进行排序。最好得到一个结果是UserTypes不是单一的用户,JOIN结果是Attending JOINED到一个Select只选择EventTypes只有Singles的事件。以这种方式格式化意味着考勤表周围的JOIN不会加入和返回单个用户,并且不匹配仅非单身人士的事件。