zoukankan      html  css  js  c++  java
  • 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型子查询都比连接查询来的慢。

  • 相关阅读:
    js 获取和设置css3 属性值的实现方法
    API的自动化测试
    删除html标签或标签属性以及样式
    JS+CSS实现数字滚动
    video元素和audio元素相关事件
    SDT v0.0.1 上线
    safari浏览器fixed后,被软键盘遮盖的问题—【未解决】
    js中DOM事件探究
    使用Web存储API存取本地数据
    剑指offer(Java版)第七题:用两个栈实现一个队列。队列的声明如下,请实现它的两个函数appendTail和deleteHead, 分别完成在队列尾部插入结点和在队列头部删除结点的功能。
  • 原文地址:https://www.cnblogs.com/cnsec/p/13407013.html
Copyright © 2011-2022 走看看