Oracle中SQL解析整体过程

Oracle中SQL解析整体过程

  • Oracle数据库体系结构
    • 数据库服务器构成
      • 内存
      • 进程
      • 存储
    • 表空间,数据块,数据库
      • 表空间
      • 段,区,块
      • 灰数据
  • Sql执行过程
    • 客户端将sql语句发到服务器进行解析
    • 检查SQL语句的合法性
    • 检查SQL语言含义
    • 获得对象解析锁
    • 数据访问权限的核对
    • 对sql语句进行解析(软解析和硬解析)
    • 确定最佳执行计划
    • SQL语句执行(exec)
    • 提取数据(fetch)
  • 总结

Oracle数据库体系结构

数据库服务器构成

1)由Oracle实例和Oracle数据库组成
2)Oracle实例:包含SGA和后台进程
3)Oracle数据库结构:内存,进程,存储

内存

目前共有6大内存
1)共享池:缓存最近执行过的sql语句,以及执行计划,避免硬解析
2)数据库缓冲区高速缓存:缓存oracle访问的数据块,避免磁盘i/o
3)重做日志缓存区:用于处理日志的
4)大型池:oracle需要比较大的内存时会用到,备份恢复或者并行处理等
5)Streams池:用于streams复制
6)Java池:java类编译时会用到

进程

1)用户进程:数据库用户请求连接oracle时启动(配合监听进程去访问远端的数据库)
2)服务器进程:连接oracle时使用,用户建立会话时启动
3)后台进程:启动oracle实例时启动。
	后台进程主要包括四种:
	a.系统监视器SMON:
	b.进程监视器PMON:
	c.数据库写进程DBWn:将信息从SGA的数据库缓冲存储区中写入到数据库数据文件中
	d.日志写进程LGWR:会重做日志文件,并执行归档进程ARCn,完成归档日志文件

存储

1)控制文件:记录数据库的物理结构信息、当前运行的状态信息等
2)数据文件:Oracle表信息
3)联机重做日志文件:记录数据文件块所有的操作变化过程。
4)参数文件
5)备份文件
6)口令文件
7)归档日志文件
8)预警和跟踪日志文件

附图:附加一张Oracle Concepts Guide中给出的图
Oracle中SQL解析整体过程_第1张图片

表空间,数据块,数据库

表空间

1)SYSTEM和SYSAUX表空间是必须存在的表空间
2)以上俩个表空间在创建数据库时创建的,且必须联机
3)SYSTEM表空间用于核心功能(数据字典),SYSAUX表空间用于附加的数据库组件
4)一个表空间包含多个数据文件
5)一个数据文件仅归属一个表空间

段,区,块

1)段存在于表空间
2)段由区的集合构成
3)区是数据块的集合
4)数据块映射到磁盘块

灰数据

在数据库缓冲区中对数据块增删改查,当DBWn写入到数据块时,出现问题,
导致SGA中数据库缓冲区中的数据块记录和数据快文件不一致导致灰文件。

Oracle中SQL解析整体过程_第2张图片

Sql执行过程

客户端将sql语句发到服务器进行解析

客户端的用户使用进程将sql传递到服务器,服务器进程PGA将sql传递到后台进程,使之进行操作。

检查SQL语句的合法性

对SQL语句进行语法检查,看其是否符合语法规则。
如果服务器进程认为这条SQL语句不符合语法规则时,会把这个错误信息,反馈到客户端,展现给用户。
在整个过程中不会对SQL中的表名和列名进行检查。

检查SQL语言含义

若SQL语句符合语法规则,则服务器进程接下来会对语句中的字段、表等内容进行检查。
看字段、表是否在数据库中。
如果表名与列名不准确的话,会把这个错误信息,反馈到客户端,展现给用户。

获得对象解析锁

当语法、语义都正确后,系统会对需要查询的对象进行加锁。
主要是为了保证数据的一致性,防止我们在操作的过程中,其他用户对这个对象的结构发生改变。

数据访问权限的核对

当前面几步完成之后,服务器进程还会检查,所连接的用户是否有这个数据访问的权限。

对sql语句进行解析(软解析和硬解析)

软解析:将用户输入的SQL进行HASH运算和共享池中的HASH值对比,相同即直接运行。
硬解析:将用户输入的SQL进行HASH运算和共享池中的HASH值对比,不相同则执行7,8,9步。
1)验证SQL语句是否完全一致:
	Oracle会对传递进来的SQL语句使用HASH函数运算得出HASH值,并于共享池中的HASH值进行对比。
如果SQL语句的HASH值和共享池中的某个HASH值一致,那么ORACLE事实上还需要对SQL语句的语义进行再次检测,以决定是否一致,此时为了防止不同用户所导致sql语句不相同。
现有数据库中SQL语句的HASH值,可以通过访问v$sql、v$sqlarea、v$sqltext等数据字典中的HASH_VALUE列查询得出。
	注意:查询v$sql_shared_cursor可以得知SQL为何不能共享的原因,语句如下:
		语句:select address,auth_check_mismatch,translation_mismatch,optimizer_mismatch from v$sql_shared_cursor where address in ( select address from v$sql where upper(sql_text) like 'SELECT * FROM EMP%' )  
		参数1:AUTH_CHECK_MISMATCH 表示对同样一条SQL语句转换是不匹配的。
		参数2:TRANSLATION_MISMATCH 表示SQL游标涉及到的数据对象是不同的。
		参数3:OPTIMIZER_MISMATCH 表示会话的优化器环境是不同的。

2)验证SQL语句执行环境是否相同:
	验证SQL语句执行环境是否一样。
	通过上面的检查以后,如果SQL语句是一致的,那么就会重用原有SQL语句的执行计划和优化方案,也就是软解析。
	如果SQL语句没有找到同样的SQL副本,那么就需要进行硬解析了,也就是需要进行下面的操作。

3)解决硬解析的最好办法就是绑定变量
	(1)使用了Bind Var能提高性能主要是因为这样做可以尽量避免不必要的硬分析(Hard Parse)而节约了时间,同时节约了大量的CPU资源。
	(2)当一个Client提交一条Sql给Oracle后,Oracle 首先会对其进行解析(Parse),
		然后将解析结果提交给优化器(Optimiser)来进行优化而取得Oracle认为的最优的Query Plan,
		然后再按照这个最优的Plan来执行这个Sql语句(当然在这之中如果只需要软解析的话会少部分步骤)。
	(3)但是,当Oracle接到 Client提交的Sql后会首先在共享池(Shared Pool)里面去查找是否有之前已经解析好的与刚接到的这一个Sql完全相同的Sql,
		当发现有相同的以后解析器就不再对新的Sql在此解析而直接用之前解析好的结果了。
		这里就节约了解析时间以及解析时候消耗的CPU资源。尤其是在OLTP中运行着的大量的短小Sql,效果就会比较明显了。

确定最佳执行计划

当上面的步骤都完成以后,并且没有在共享池找到对应的SQL副本,那么就会进入硬解析,也就是此步骤,
首先会对SQL语句进行优化,但是这个优化是有限度的,远没有工程师对SQL优化的程度大,所以每当开发完成,数据库的优化就显得极为重要。
当服务器进程的优化器确定这条查询语句的最佳执行计划后,会将这条SQL语句与执行计划保存到共享池的库缓存(library cache)中。
后面还有这个查询时,就会省略上面的语法、语义与权限检查的步骤,而直接执行SQL语句,提高SQL语句处理效率。

SQL语句执行(exec)

SQL语句解析是为了确保服务器可以知道这条语句在表达什么意思。
等SQL语句解析完成以后,数据库服务器进程会真正执行这条SQL语句。
一般执行分为俩种情况:
	第一种:若需要使用的数据块已经被读取到数据缓冲区的话(也就是上文提到的数据库缓冲区高速缓存),则服务器进程会直接把这个数据传递给客户端,而不是从数据库文件中去查询数据。
	第二种:若数据不在缓冲区中,服务器进程将从数据库文件中查询相关数据,并且把这些查到的数据放入到数据缓冲区中。
Oracle数据库中,定义了很多种类的高速缓存。例如上面提到的SQL语句缓存(共享池)与现在说的数据缓存(数据库缓冲区高速缓存)。

提取数据(fetch)

当语句执行完成之后,查询到的数据还是在服务器进程中,
所以在服务器端的进程中,有一个专门负责数据提取的一段代码,把查询到的数据结果返回给用户端进程,从而完成整个查询动作。

总结

执行计划这块我会专门总结一篇文章,因为这部分知识带你比较多而且灰常重要。
总结的可能有不到位的地方或者错别字各位大佬多多见谅,至于排版我会尽快改善。
^_^

你可能感兴趣的:(数据库基础,数据库,sql)