MySQL查询优化器源码分析--整体流程

函数间关系的主要逻辑如下:

handle_select(){――第(1)层

  mysql_union(); //处理union操作

  mysql_select(){――第(2)层

JOIN::optimize() {――第(3)层

  simplify_joins(); //把外连接简化为内连接 

optimize_cond(…, conds, …); //优化whrer子句

optimize_cond(…, having, …); //优化having子句

opt_sum_query(); //优化count(*), min() and max(),只适用于没有group子句的情况

make_join_statistics();//确定多表的连接路径;单表是多表的特例

{――第(4)层

  update_ref_and_keys();//获取索引信息,为快速定位数据、条件比较做准备

    get_quick_record_count();
choose_plan()
    {――第(5)层
      
      optimize_straight_join(); 
      find_best ();
      greedy_search(); 
      {――第(6)层
        best_extension_by_limited_search()
        {――第(7)层
          best_access_path()//估算局部查询树的最佳访问路径
        }
      }//――第(6)层结束

}//――第(5)层结束

  }//――第(4)层结束

……

make_outerjoin_info();//填充外连接的信息

……

substitute_for_best_equal_field(); //循环遍历所有表达式,化简表达式(重复的等式能去掉则直接去掉,如:WHERE a=5 AND ((a=b AND b=c) OR  c>4) 的条件将变为:“=(a) and (=(5abc) or c>4)”)[1]

……

make_join_select(); //用于执行各种不同情况的join查询。该函数通过join时,连接表的不同搜索方式(唯一索引查找、ref查找、快速范围查找、合并索引查找、全表扫描等不同方式),进行join操作的处理

 

//优化distinct谓词相关的情况,如下多行代码,处理不同的distinct情况

……

 

//创建临时表

//处理简单的IN子查询

}――第(3)层结束,optimize()

}――第(2)层结束,mysql_select()

}――第(1)层结束,handle_select()

以上是查询优化的整体流程,在进入第4层之前是的逻辑查询计划生成,如外连接转换为內连接、表达式化简、子查询的消除等逻辑优化策略都是在这个阶段之前完成的。

 

4层之后是物理查询计划生成,利用贪婪(greddy)算法,实现多个关系的访问方式确定(顺序访问、索引访问)、连接方式确定(嵌套循环连接算法)、连接顺序选取。



[1] 如执行如下sql,并查看其查询计划,可以看到查询计划的条件发生了变化:

create table t(a int, b int, c int, d int);

insert into t values(1,2,3,4);

insert into t values(5,5,5,5);

insert into t values(10,20,30,40);

explain EXTENDED select * from t WHERE a=5 AND ((a=b AND b=c) OR  c>4);

SHOW WARNINGS;

查询计划的结果为:

select `test`.`t`.`a` AS `a`,`test`.`t`.`b` AS `b`,`test`.`t`.`c` AS `c`,`test`.`t`.`d` AS `d` from `test`.`t` where ((`test`.`t`.`a` = 5) and (((`test`.`t`.`b` = 5) and (`test`.`t`.`c` = 5)) or (`test`.`t`.`c` > 4)))

你可能感兴趣的:(数据库)