• in 型子查询引出的陷阱


    在开发商城的时候,核心有一个goods表和category表,category中有多级分类。假设有一个父分类为6,这个父分类中没有商品,商品都在子分类中,那么要查询分类为6的商品,如果我们使用in型子查询,会使用下面的sql。

    select * from  goods where cat_id in (select
    cat_id from category where parent_id=6);

    直观的感觉:先执行括号里面的,也就是select cat_id from category where parent_id = 6,然后在执行select * from goods where cat_id in (1,2,3,4),这里假设6号栏目下有子栏目1,2,3,4。

    事实上,并不是这样的,会全部扫描goods表,每扫到一行,就与category表对照,看parent_id=6是否成立,原因mysql的查询优化器,针对In型做优化,被改成了exists子查询的执行效果,当goods表越大时, 查询速度越慢。

    这里写图片描述

    我们来看一下查询计划,来佐证我的推论,首先在外层sql,在外层中type为all,表示进行全盘查goods表,虽然我已经在cat_id列上加了索引,但是不会使用到任何索引;然后看一下内层sql,在内容sql中使用到了category表的主键索引,为什么呢?因为在外层sql每查找一条记录,就会带上cat_id去cat表中执行这样的sql,select * from category where cat_id = x and parent_id = 6;,这个cat_id就是外层sql每查找到一件商品的分类编号,这条语句会使用到category表的主键索引。

    这里写图片描述

    那么该如何优化呢?

    我们可以改用连接查询,看看explain分析的结果,首先只是全表扫描category表,而category表的数据比较少,全表扫描对性能的影响也不会太大,不想上面的全表扫描goods,这个对性能的影响就太大了。然后就是连接查询了,还用到了goods表的cat_id的索引

    select * from goods inner join (select cat_id from category where parent_id = 6) as tmp on goods.cat_id = tmp.cat_id;

    这里写图片描述

    in型子查询和连接查询的对比:

    这里写图片描述

    query_id为1的是in型子查询,花费时间为0.00131675,而连接查询的花费时间为0.00068575,可以看到,在这个问题上,连接查询比in型子查询来的高效。但并不是说对于所有的查询in型子查询都比连接查询来的慢。

  • 相关阅读:
    Linux的五个查找命令
    Linux中ftp不能上传文件/目录的解决办法
    linux下的chmod,chown和chgrp
    Memcache基础教程
    Web服务器磁盘满故障
    linux定时任务生产java服务无法执行问题案例
    Linux 用户和用户组管理
    10-xargs 简明笔记
    51-du 显示关于目录层次结构或文件磁盘使用情况的信息
    46-df 显示磁盘空间的使用情况
  • 原文地址:https://www.cnblogs.com/cnsec/p/13407013.html
Copyright © 2020-2023  润新知