zoukankan      html  css  js  c++  java
  • ORACLE数据库SQL语句的执行过程

    SQL语句在数据库中处理过程是怎样的呢?执行顺序呢?在回答这个问题前,我们先来回顾一下:在ORACLE数据库系统架构下,SQL语句由用户进程产生,然后传到相对应的服务端进程,之后由服务器进程执行该SQL语句,如果是SELECT语句,服务器进程还需要将执行结果回传给用户进程。

    SQL语句的执行过程一般如下:

    解析(PARSE)—— 绑定(BIND)——执行(EXECUTE)——提取(FETCH 只有SELECT才需要这步)

    clip_image001

    解析

    服务器进程接收到一个SQL语句时,首先要将其转换成执行这个SQL语句的最有效步骤,这些步骤被称为执行计划。

    Step 1:检查共享池中是否有之前解析相同的SQL语句后所存储的SQL文本、解析树和执行计划。如果能从共享池的缓存库中找到之前解析过生成的执行计划,则SQL语句则不需要再次解析,便可以直接由库缓存得到之前所产生的执行计划,从而直接跳到绑定或执行阶段,这种解析称作软解析。

    但是如果在共享池的库缓存中找不到对应的执行计划,则必须继续解析SQL、生成执行计划,这种解析称作硬解析

    在缓存池解析过的SQL,会有一个对应的哈希值与之对应,你可以通过V$SQL视图来查询,请看下面一个例子:

    复制代码
    SQL>SELECT * FROM SCOTT.DEPT WHERE DEPTNO =10;
    
    SQL>SELECT * FROM SCOTT.DEPT WHERE DEPTNO =20;
    
    SQL> SELECT HASH_VALUE , ADDRESS, EXECUTIONS ,SQL_TEXT
    
    2 FROM V$SQL
    
    3 WHERE SQL_TEXT LIKE 'SELECT * FROM SCOTT.DEPT WHERE DEPTNO%'
    
    4 ;
    
    HASH_VALUE ADDRESS EXECUTIONS SQL_TEXT
    
    ---------- -------- ---------- --------------------------------------------------------------------------------
    
    442836625 27EE4B7C 1 SELECT * FROM SCOTT.DEPT WHERE DEPTNO =20
    
    4215405494 27EEA3BC 1 SELECT * FROM SCOTT.DEPT WHERE DEPTNO =10
    复制代码

     下面我们先清空共享池缓存的执行计划,然后使用绑定变量,查看执行计划的变换

    复制代码
    SQL> ALTER SYSTEM FLUSH SHARED_POOL;
    
    System altered
    
    SQL> VARIABLE deptno NUMBER;
    
    SQL> EXECUTE :deptno := 10;
    
    PL/SQL procedure successfully completed
    
    deptno
    
    ---------
    
    10
    
    SQL> SELECT * FROM SCOTT.DEPT WHERE DEPTNO=:deptno;
    
    DEPTNO DNAME LOC
    
    ------ -------------- -------------
    
    10 ACCOUNTING NEW YORK
    
    SQL> EXECUTE :deptno :=20;
    
    PL/SQL procedure successfully completed
    
    deptno
    
    ---------
    
    20
    
    SQL> SELECT * FROM SCOTT.DEPT WHERE DEPTNO=:deptno;
    
    DEPTNO DNAME LOC
    
    ------ -------------- -------------
    
    20 RESEARCH DALLAS
    
    SQL> SELECT HASH_VALUE , ADDRESS, EXECUTIONS ,SQL_TEXT
    
    2 FROM V$SQL
    
    3 WHERE SQL_TEXT LIKE ' SELECT * FROM SCOTT.DEPT WHERE DEPTNO%';
    
    HASH_VALUE ADDRESS EXECUTIONS SQL_TEXT
    
    ---------- -------- ---------- --------------------------------------------------------------------------------
    
    3669302979 27D2BA1C 2 SELECT * FROM SCOTT.DEPT WHERE DEPTNO=:deptno
    复制代码

    Step 2:语法分析,分析SQL语句的语法是否符合规范,衡量语句中各表达式的意义

    Step 3:检查是否存在语义错误和权限。语义分析,检查语句中设计的所有数据库对象是否存在,且用户有相应的权限。

    Step 4:视图转换和表达式转换 将涉及视图的查询语句转换为相应的对基表查询语句。将复杂表达式转化较为简单的等效连接表达式。

    Step 5:决定最佳执行计划。优化器会生成多个执行计划,在按统计信息带入,找出执行成本最小的执行计划,作为执行此SQL语句的执行计划

    Step 6:将SQL文本、解析树、执行计划缓存到库缓存,存放地址以及SQL语句的哈希值。

    绑定

    如果SQL语句中使用了绑定变量,扫描绑定变量的声明,给绑定变量赋值。则此时将变量值带入执行计划。

    执行

    此阶段按照执行计划执行SQL,产生执行结果。不同类型的SQL语句,执行过程也不同。

    SELECT查询

    检查所需的数据块是否已经在缓冲区缓存中,如果已经在缓冲区缓存中,直接读取器内容即可。这种读取方式称为逻辑读取。如果所需数据不在缓冲区缓存中,则服务器进程需要先扫描数据块,读取相应数据块到缓冲区缓存,这种读取方式称为物理读。和逻辑读相比较,它更加耗费CPU和IO资源。

    修改操作(INSERT、UPDATE、DELETE)

    Step 1:检查所需的数据库是否已经被读取到缓冲区缓存中。如果已经存在缓冲区缓存,则执行Step 3

    Step 2:若所需的数据库并不在缓冲区缓存中,则服务器将数据块从数据文件读取到缓冲区缓存中

    Step 3:对想要修改的表取得的数据行锁定(Row Exclusive Lock),之后对所需要修改的数据行取得独占锁

    Step 4:将撤销数据的Redo记录复制到日志缓冲区,产生数据行的撤销数据,将数据行修改的Redo记录复制到日志缓冲区,修改数据行。

    Step 5: 产生数据修改的撤销数据

    Step 6:复制数据修改的Redo记录到日志缓冲区

    Step 7:修改数据行的内容,如果之前的缓冲为干净缓冲,则此时将变为脏缓冲。

    提取

    提取只有SELECT查询语句才有的步骤。获取查询的记录行,必要的时候对查询结果排序。

  • 相关阅读:
    javaweb学习总结(四十五)——监听器(Listener)学习二
    javaweb学习总结(四十四)——监听器(Listener)学习
    javaweb学习总结(四十三)——Filter高级开发
    javaweb学习总结(四十二)——Filter(过滤器)学习
    javaweb学习总结(四十一)——Apache的DBUtils框架学习
    javaweb学习总结(四十)——编写自己的JDBC框架
    javaweb学习总结(三十九)——数据库连接池
    javaweb学习总结(三十八)——事务
    javaweb学习总结(三十七)——获得MySQL数据库自动生成的主键
    javaweb学习总结(三十六)——使用JDBC进行批处理
  • 原文地址:https://www.cnblogs.com/likeju/p/5039208.html
Copyright © 2011-2022 走看看