我有两个mysql脚本:
select
p.*
from
`products` p
JOIN dispensaries d ON (p.dispensary_id = d.id)
JOIN dispensary_locations dl ON(dl.dispensary_id = d.id AND dl.is_primary = 1)
JOIN dispensary_location_zip_codes dlzc ON(dlzc.dispensary_location_id = dl.id AND dlzc.zip_code = '941033')
and p.`is_hidden` = 0
and p.`deleted_at` is null
GROUP BY p.id
order by p.`points` desc
limit 12
和
select
*
from
`products`
where
exists (
select
*
from
`dispensaries`
where
`products`.`dispensary_id` = `dispensaries`.`id`
and exists (
select
*
from
`dispensary_locations`
where
`dispensary_locations`.`dispensary_id` = `dispensaries`.`id`
and exists (
select *
from
`dispensary_location_zip_codes`
where
`dispensary_location_zip_codes`.`dispensary_location_id` = `dispensary_locations`.`id` and `zip_code` = '941033'
)
AND is_primary = 1
)
)
order by `points` desc
limit 10;
逻辑它们应该是相同的,但在我的数据库中,当zip_code存在时,第一个需要60毫秒,不存在时需要30毫秒。 当zip_code存在时,第二个需要5毫秒,当zip_code不存在时需要9500毫秒,有没有人知道这里发生了什么?
我在数据库中有大约1万种产品。时代是 第一个脚本为60毫秒和30毫秒,第二个脚本为5毫秒和9500毫秒(9.5秒)...
答案 0 :(得分:4)
为什么Mysql“where where”比“join”慢得多?
在所有情况下都不会慢。它取决于许多因素,如每个表的大小,连接列的索引,值的存在(特别是对于exists语句)等。
例如,让p
和q
为每个表中的条目数。
默认情况下Exists
执行嵌套循环,并在找到某个内容后立即停止执行。因此,最坏情况的复杂性(如果值不存在)是O(p*q)
。
DB Engine如何连接表的粗略草图
嵌套加入
O(p*q)
O(p*logq)
哈希加入
使用连接属性和行准备较小关系的哈希表。扫描更大的关系。
如果表格足够小以适合内存
复杂性,正如所料 - O(p+q)
合并加入
如果两个表的排序顺序相同。两者都按顺序运行并匹配它们对应的位置。
如果两个表都在连接列上有索引,则索引已按顺序维护它们。因此,复杂性 - O(p+q)
O(p+qlogq)
O(plogq+qlogq)
在上面的场景中,当zip_codes不存在时,数据库引擎必须对查询2(存在)中的所有条目(O(p*d*dl*dlz)
)执行嵌套循环,其中在查询1数据库引擎中应用优化连接得到结果。
当zip_codes存在时,在查询2(存在)场景中,它找到匹配的条目而不对所有条目执行嵌套循环。