理解Oracle的优化第一回合:Sql语句的执行过程
1.SQL语句的执行过程
我们平常都用PLSQL等工具去执行sql,其实工具会自动帮我们做很多事,我们自然不会关注到其中的细节,但是懂得sql的执行步骤,可以帮助我们写出更好更有效的sql语句,在出现一些问题时,如select较慢,我们可以分析在哪个阶段除了问题,找到解决办法。
下面是sql的执行过程:
DML语句的处理:
每一种类型的语句都需要执行下面的步骤:
•第1步:CreateaCursor创建游标
•第2步: Parse the Statement分析语句
•第5步:BindAnyVariables绑定变量
•第7步: Run the Statement运行语句
•第9步:ClosetheCursor关闭游标
如果使用了并行功能,还会包含下面这个阶段:
•第6步: Parallelize the Statement并行执行语句
如果是查询语句,则需要以下几个额外的步骤,如图3所示:
•第3步: Describe Results of a Query描述查询的结果集
•第4步: Define Output of a Query定义查询的输出数据
•第8步:FetchRowsofaQuery取查询出来的行
下面具体来说下每一步都做了什么?
第一步 创建游标**
任何一个sql语句都会创建游标,特别是运行DML时,但大多数情况下,都是自动创建,无需开发人员干预。当然在预编译的proc中也有可能会显示的创建。
第二步 分析语句**
这里的分析,主要是语法的分析,sql语句和分析的信息都会被装入到 共享sql区 ,这个阶段可以解决许多类型的错误。
语法的分析主要有以下操作:
- 翻译sql语句,验证它是否合法
- 实现数据字典查找,判断表、列是否定义
- 获取语法分析锁,保障分析过程中不改变访问对象的定义
- 验证操作的权限
- 绝对此条语句的最佳执行计划
- 将此条语句装入共享sql区
- 对于分布式的语句,检查语句的路由是否包含所有的远程节点
以上的任何一步有错,都会中断sql的执行。只有共享池中不存在等价的语句时,才会执行语法分析 。这个功能主要依赖于绑定变量来实现的,也就是我们常说的共享sql。
所以这一步给出的sql优化技巧如下:
1.尽量编执行语法分析。
2.查询语句较其他类型语句不同,因为会返回一行或者多行数据。我们可以通过批量的fetch数据,降低网络开销。
第三步 描述查询的结果集
当查询由用户交互的输入查询的列名时,需要描述查询结果的特征。
第四步 定义查询的输出语句
此阶段可指定与查询的列值对应的接受变量的位置、大小。数据类型,这样我们就能通过接收变量就可以得到查询结果。
第五步 绑定变量
此时oracle已知道SQL语句的意思,但仍然没有足够的信息用于执行该语句。需要得到语句中列出的所有变量的值,得到这个变量值的过程就是绑定变量。
如 select * from scott.emp where empno= :var_empno;
中得到 empno这个限定值的过程。
第六步 并行执行语句
并行可以使多个服务器进程为同一个sql服务,但会耗费更多的资源,不到万不得已不要使用。
第七步 执行语句
此时,一切准备就绪,准备执行了。update、delete等语句需要锁定影响的行,保证数据的一致性。
这里的优化技巧:对于一些语句,可指定执行的次数,可以减少网络开销。
第八步 取出查询的行
第九步 关闭游标
这是sql处理的最后的一个阶段。
对于DDL语句,需要对数据字典进行修改,语句分析阶段至包含 分析、查找数据字典的信息和执行。
事务的四大特性分别是:原子性、一致性、隔离性、持久性
原子性: 是指事务包含的所有操作要么全部成功,要么全部失败回滚
一致性:一个事务执行之前和执行之后都必须处于一致性状态。比如,一个 事务给另一个事务转10块钱,那么他俩一共只有10块钱,总量是不可能改变的。
隔离性:多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰
持久性一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的