Mysql 为什么内部联接比单独查询慢

Mysql 为什么内部联接比单独查询慢,mysql,sql,join,Mysql,Sql,Join,我有以下几张表 用户表 列:id、电子邮件 索引:id 位置表 列->id、名称、用户id、上次扫描时间 索引:id,用户\u id 项目表 列->id、名称、位置\u id、上次\u扫描\u时间 索引:id,位置\u id 我必须运行此查询才能获取项目 select items.* from items inner join locations on (items.last_scan_time = locations.last_scan_time and items.locatio

我有以下几张表

用户表 列:id、电子邮件 索引:id 位置表 列->id、名称、用户id、上次扫描时间 索引:id,用户\u id 项目表 列->id、名称、位置\u id、上次\u扫描\u时间 索引:id,位置\u 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')
以上查询1056870行需要13秒

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

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
我必须对联接查询或索引进行哪些更改才能使联接查询的运行速度快于单个查询的总时间

请帮忙

谢谢,,
Sachin

您的查询采用重新格式化的形式:

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'
因此,查询中的谓词基本上是:

用户表的电子邮件列上的eq文本

位置表用户id列上的eq ref

项目表位置id和上次扫描时间的eq ref

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

... ON users (email,id)

... ON locations (id, last_scan_time)

... ON items (location_id, last_scan_time)
但是这个建议实际上取决于实际的表定义,表是MyISAM还是InnoDB,基数和数据分布,等等


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

一个更好的示例是,如果您希望运行一个查询,该查询涉及两组数据的交集,而这两组数据在某种程度上是独立的数据部分。。。例如,如果您有一个事件表,则事件具有EventTypes,而EventTypes仅具有Singles属性。然后有一个Users表,Users有MaritalStatus,MaritalStatus有一个Single标志。当然,您还有一个将事件映射到用户的参与表


如果您想知道是否有任何非单身人士注册参加了仅单身人士的活动,正确的答案不是编写单个查询,通过ID将这些表连接在一起,然后在where子句中对其进行排序。最好得到一个结果,即用户类型不是单一的用户,将该结果加入到只选择事件类型为单一的事件的选择中。以这种方式格式化意味着考勤表周围的联接不会联接和返回单身用户,也不会匹配不只是单身的事件。

explain[您的查询]将告诉您发生了什么。特别是,哪些索引不是?正在使用。如果希望我们帮助优化查询,则需要向我们显示实际的表和索引定义,以及每个表的行计数。也许您的表定义不好。可能索引没有正确创建。也许你在你认为你有的专栏上没有索引。如果看不到表和索引定义,我们无法判断。我们还需要行计数,因为这会极大地影响查询优化。如果你知道如何进行解释或获得执行计划,也可以将结果放在问题中。感谢Spencer7953,在电子邮件上添加索引效果很好,它将原始查询的时间从13秒缩短到了0.05秒。也非常感谢评论者指出解释和基数值。这对优化有很大帮助。