mysql 两表join与in子查询的比较

有两个表

promotion_full_reduction

这里写图片描述

base_user_favorite_item

这里写图片描述

现在要查询用户收藏的商品中参加促销了的商品个数,有两种写法,一种是使用in子查询:

SELECT
    COUNT(1)
FROM
    promotion_full_reduction fr
WHERE
    fr.item_id IN (
        SELECT
            ufi.item_id
        FROM
            base_user_favorite_item ufi
        WHERE
            ufi.platform_id = 222
        AND ufi.user_id = 111
    )

使用 explain 查看mysql执行计划:

这里写图片描述

此sql以promotion_full_reduction 为驱动表,虽然执行计划显示走了索引,但是由于外层查询没有where条件(因为子查询还未执行),结果就是将promotion_full_reduction 全表数据都扫描了出来load到了内存,然后进行nested loop,循环执行子查询,根据子查询结果对外层查询结果进行过滤,总共要循环99次(子查询到底是读99次磁盘还是只读一次这个我不确定,希望了解的人解释一下)。

再看使用两表关联进行查询:

SELECT
    count(1)
FROM
    promotion_full_reduction pr
JOIN base_user_favorite_item bi ON pr.item_id = bi.item_id
WHERE
    bi.user_id = 111
AND bi.platform_id = 2222

使用 explain 查看mysql执行计划:

这里写图片描述

执行计划显示mysql选择了 base_user_favorite_item 作为驱动表,由于带有where条件,驱动表查询出来的结果只有两条,显然磁盘io次数少了,nested loop循环次数也降了下来。

结论:不要轻易使用in子查询,由于in子查询总是以外层查询的table作为驱动表,所以如果想用in子查询的话,一定要将外层查询的结果集降下来,降低io次数,降低nested loop循环次数,即:永远用小结果集驱动大的结果集。

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值