oracle 使用2个引擎来执行SQL和代码块:SQL 引擎和PL/SQL 引擎, Oracle 使用这2个引擎来执行PL/SQL blocks 和 subprograms。那么在执行的时候,PL/SQL 引擎把DML 语句发送给SQL 引擎,然后由SQL 引擎执行,执行完毕后,SQL 引擎把结果集在发送给PL/SQL 引擎。因此在不同引擎之间切换就需要进行context
switch,过多的context switch是会影响SQL性能的。而bulk (关于bulk,后续介绍)就是从减少引擎之间context switches的方式来提高sql的效率。 把对SQL 进行打包处理。
1、sql引擎介绍
一条sql语句在sql引擎中,大致会经过如下三个步骤:解析(parse)、执行(execute)、获取(fetch):这三个步骤分别由sql引擎的不同的组件完成。
1.1、sql编译器(sql compiler)
解析器(parser):
查询优化器(Query Optimizer):为语句生成一组可能被使用的执行计划,估算出每个执行计划的代价,调用计划生成器(Plan Generator)生成计划,比较计划的代价,最终选择一个代价最小的执行计划(注意代价估算器只能估算出代价,并不能选择出最优的,来让计划生成器生成那个最优的,而是让计划生成器生成所有的执行计划,再进行比较)。
通过上图也可以看到,查询优化器包含了:查询转换器(Query Transform)、代价估算器(Estimator)、计划生成器。
那么,我们继续看下查询优化器包含的这三个组件的用途:
查询转换器:决定是否重写用户的查询(包括视图合并,子查询反嵌套),以生成更好的查询计划。
代价估算器:代价估算器使用统计数据来估算操作的选择率(selectivity)、返回数据集的势(Cardinality)和代价。并最终估算出整个执行计划的代价。
计划生成器:计划生成器会考虑可能的访问路径(Access Path)、关联的方法和关联的顺序,生成不同的执行计划,让查询优化器从这些计划中选择代价最小的一个执行计划。
行源生成器(Row Source Generator):行源生成器从查询优化器接收到优化的执行计划,然后为该计划生成行源(Row Source)。行源是一个可被迭代控制的结构体,它能以迭代方式处理一组数据行、并生成一组数据行。
1.2、sql执行引擎(sql Execution Engine)
sql执行引擎依照语句的执行计划进行操作,产生查询结果。在每一个操作中,sql执行行引擎会以迭代的方式执行行源、生成数据行。
1.3、执行计划的生成
当前实例内存中的执行计划,可以通过视图:v$sql_plan读取。
启用了awr时,oracle会将内存的执行计划存到历史数据中,我们可以通过查询sql语句,或者oracle提供的系统包dbms_xplan从历史数据中读取。
除了通过执行sql让oracle在内存中生成执行计划外,我们还可以通过命令Explain Plan让优化器仅对sql语句进行解释,生成执行计划,由于语句并不会真正执行,因此它可以含有没有赋值的绑定变量。执行explain plan命令后,oracle会将解释生成的查询计划插入表SYS.PLAN_TABLE$中。然后我们就可以通过查询语句或者包:dbms_xplan从该表中读取查询计划咯。
注意:通过explain plan解释出来的查询计划不会被缓存到内存中,供语句执行时重用。
2、pl/sql引擎介绍