本文的主要围绕着下面这些问题展开的,在阅读之前可以先思考一下问题的答案是什么
- Oracle中的SQL的执行过程什么样的?
- 什么是硬解析?什么是软解析?
- 如何避免硬解析?
Oracle中的SQL的执行过程
从图中我们可以看出SQL语句在Oracle中经历了以下的几个步骤:
- 语法检查:检查SQL拼写是否正确,如果不正确,Oracle会报语法错误。
- 语义检查:检查SQL中的访问对象是否存在。比如我们在写SELECT语句的时候,列名写错了,系统就会提示错误。语法检查和语义检查的作用是保证SQL语句没有错误。
- 权限检查:看用户是否具备访问该数据的权限。
- 共享池检查:共享池(Shared Pool)是一块内存池,最主要的作用是缓存SQL语句和该语句的执行计划。Oracle通过检查共享池是否存在SQL语句的执行计划,来判断进行软解析,还是硬解析。
- 优化器:优化器中进行硬解析,也就是决定怎么做,比如创建解析树,生成执行计划。
- 执行器:当有了解析树和执行计划之后,就知道了SQL该怎么被执行,这样就可以在执行器中执行语句了。
共享池是Oracle中的术语,包括了库缓存,数据字典缓冲区等。**库缓存区,主要缓存SQL语句和执行计划。**数据字典缓冲区存储的是Oracle中的对象定义,比如表、视图、索引等对象。当对SQL语句进行解析的时候,如果需要相关的数据,会从数据字典缓冲区中提取。
硬解析和软解析
软解析:在共享池中,Oracle首先对SQL语句进行Hash运算,然后根据Hash值在库缓存(Library Cache)中查找,如果存在SQL语句的执行计划,就直接拿来执行,直接进入“执行器”的环节
硬解析:如果没有找到SQL语句和执行计划,就会进入“优化器”这个步骤,Oracle就需要创建解析树进行解析,生成执行计划
如何避免硬解析
在Oracle中,绑定变量是它的一大特色。绑定变量就是在SQL语句中使用变量,通过不同的变量取值来改变SQL的执行结果。
这样做的好处是能提升软解析的可能性,不足之处在于可能会导致生成的执行计划不能优化,因此是否需要绑定变量还需要视情况而定。
举个例子,我们可以使用下面的查询语句:
SQL> select * from student where student_id = 100;
你也可以使用绑定变量,如:
SQL> select * from student where student_id = :student_id;
这两个查询语句的效率在Oracle中是完全不同的。
如果在查询过student_id = 100
以后,我们还需要继续查询101、102
等学生的信息,那么我们每次使用第一种查询方式的时候,都会创建一个新鞋的查询解析。
使用第二种方式的时候,第一次查询之后,会在共享池中存在这类查询的执行计划,也就是上面提到的软解析。
绑定变量的方式可以减少硬解析,减少Oracle的解析工作量。但是因为参数不同,可能会导致SQL的执行效率不同,同时SQL优化也会比较困难。