美文网首页
sql优化2

sql优化2

作者: chrisghb | 来源:发表于2022-03-28 17:19 被阅读0次

    一条查询sql语句的执行流程:
    1.FROM <表名>
     选取表,将<left_table>及<right_table>表数据通过笛卡尔积生成虚表VT1(此时VT1包括表中所有的字段?),

    1. ON <筛选条件>
       对笛卡尔积的虚表VT1根据条件进行筛选VT2
    2. JOIN <join, left join, right join...> <join表>
       指定join,保留表中未匹配的行就会作为外部行添加到虚拟表VT2中,产生虚表VT3,例如left join会将左表的剩余数据添加到虚表VT2中,生成虚表VT3
      (FROM子句包含两个以上表,则对前面两个表生成的结果表VT3和下一个表重复依次执行3个步骤,直到处理完所有的表为止,这个是为什么?本质上,是因为笛卡尔是两个集合之间的操作)
    3. WHERE <where条件>
       对上述虚表VT3进行筛选, 将符合<where-condition>的记录才会被插入到虚表VT4(此时还没有进行group by,因此WHERE中出现对统计的过滤是不对的(不可以使得聚合函数),若需要则在having中实现。请思考一下,对于同样的筛选条件:在on和where 处进行筛选有结果会有不同?)
    4. GROUP BY <分组条件>
       分组, 根据分组条件,对VT4进行分组操作,生成虚表VT5(若是有group by,那么后面的所有步骤都只能得到的VT4的列及聚合函数(count、sum、avg等),即VT5虚表只会生成这些)
    5. HAVING <分组筛选>
       对分组后的结果进行筛选,即对虚表VT5进行筛选生成VT6
    6. SELECT<返回数据列表>
       选择指定的列,生成虚拟表VT7(再次提醒:若有group by子句中,则此处除了group by子句中的列+聚合函数除外,不能再出现其它的列。请思考下,为什么不建议Select *from?)
    7. DISTINCT
       数据除重,生成VT8
    8. ORDER BY<排序条件>
       将虚表VT8按照<order_by_list>进行排序操作,产生虚拟表VT9,请注意:这是唯一的一个可以使用select列表中别名的步骤?
    9. LIMIT <行数限制>
       取出指定行的记录,产生虚拟表VT10, 并将结果返回
      最后:
      实际上上述过程并不是绝对的,mysql优化器对部分过程进行优化以达到最佳的效果。
      比如在select筛选出找到的数据集?

    扩展:带有子查询的执行顺序
    1. 不相关子查询:子查询的查询条件不依赖于父查询(由里向外 逐层处理。即每个子查询在上一级查询处理之前求解,子查询的结果用于建立其父查询的查找条件)
    select * from emp where sal = (select max(sal) from emp);
    先执行内层查询,作为where 条件再执行外层查询
    2. 相关子查询:子查询的查询条件依赖于父查询(先取外层查询中表的第一个元组,根据它与内层查询相关的属性值处理内层查询,若WHERE子句返回值为真,则取此元组放入结果表,然后再取外层表的下一个元组,重复这一过程,直至外层表全部检查完为止)
    select * from dept d where exists(select * from emp e where e.deptno = d.deptno);
    先执行外层查询,再执行内层查询

    对于笛卡尔积,有一个显而易见的SQL优化的方案是,当两张表的数据量比较大,又需要连接查询时,
    应该使用 FROM table1 JOIN table2 ON xxx的语法,避免使用 FROM table1,table2 WHERE xxx 的语法。
    因为后者会在内存中先生成一张数据量比较大的笛卡尔积表,增加了内存的开销。

    相关文章

      网友评论

          本文标题:sql优化2

          本文链接:https://www.haomeiwen.com/subject/taipjrtx.html