Oracle物理体系之旅

Oracle物理体系的体系结构图的学习:

Oracle物理体系之旅

1.Oracle由实例和数据库组成,在图中用虚框标记,上半部的直角方框为实例instance,下半部的圆角方框为数据库Database。

2.共享内存区SGA(System Global Area)和一系列后台进程组成的。

3. 其中SGA最主要被划分为 共享池(shared pool)、数据缓冲区(db cache)和日志缓冲区(log buffer)三类。后台进程包括图中的PMON、SMON、LCKn、RECO、CKPT、DBWR、LGWR、ARCH等系列进程。

4.数据库是由数据文件、参数文件、日志文件、控制文件、归档日志文件等系列组成的,其中归档日志最终可能会被转移到新的存储介质中,用于备份恢复使用。

PGA(Program Global Area)区,这也是一块开辟出来的内存区,和SGA最明显的差别在于,PGA不是共享内存,是私有不共享的,用户对数据库发起的无论查询还是更新的任何操作,都是在PGA先预处理,然后接下来才进入实例区域。由SGA和系列后台进程共同完成用户发起的请求。

PGA起到的具体作用,也就是前面说的预处理,是什么呢?主要有三点:第一,保存用户的连接信息,如会话属性、绑定变量等:第二,保存用户权限等重要信息,当用户进程与数据库建立会话时,系统会将这个用户的相关权限查询处理,然后保存在这个会话区内;第三,当发起的指令需要排序的时候,PGA正是这个排序区,如果在内存中放下排序的尺寸,就在内存PGA区内完成,如果放不下,超出的部分就在临时表空间(也就是磁盘)完成排序。

 

5.用户发起的请求经历的顺序一般如下: 1 区 => 2 区 => 3 区   或者 1 区 => 2 区

 

那么一条普通的查询SQL在其中经历了什么呢?

大家请看,发出一条简单的查询语句 select name from user where user_id = 11;之后,该SQL语句从1区先做准备工作,在PGA中的session会话 完成了用户连接信息和权限的保存,这样只要这个session不断开连接,下次系统就不用再去硬盘中读取数据,而直接从PGA内存区中获取。而这种数据避免重复获取的方法就是 将用户发出的这条查询SQL立即匹配成一条唯一的 HASH 值,接下来该SQL指令进入2区进行处理,也就是SGA内存区,第一步便是SGA区的共享池的大门,准备进入。

       该条SQL先在SGA区的共享池中查询是否有什么地方有存储过这个SQL指令的身份证(就是那个唯一的 HASH值),如果没有,那么首先查询自己的语句语法是否正确,是否有权限,在这些都没问题的情况下生成这条语句的身份证,唯一的 HASH 值被存储下来了。接下来开始进行解析,解析什么呢? 比如该条  select name from user where user_id = 11 的语句,在user_id列有索引的情况下,是用索引读高效,还是全表扫描更高效呢?Oracle要自己解析做出选择。

     当Oracle通过计算发现索引代价更低,那么它就选用索引读的执行计划进入 ‘数据缓存区’中,数据缓存区开始根据ID列上的索引在user表中进行查找,但是如果没有找不到怎么办呢?那就只好去Database数据文件区中查找所需要的资源,方式必须是执行计划中设定的索引读,如果找到了,就带回到数据缓冲区中,如果没找到,也就只能空手回去了。

这就是一条最普通的SQL指令的执行经历了。

 

那么如果我第二次执行这条查询语句呢?它的执行过程是一样的吗? 执行过程是有差异的。

1. 用户首次执行该条SQL指令时,该指令从磁盘中获取用户连接信息和相关权限信息权限,并保持在PGA内存里。当用户再次执行该指令时,由于SESSION之前未被断开重连,连接信息和相关权限信息就可以在PGA内存中直接获取,避免了物理读。

2. 首次执行该SQL指令结束后,SGA内存区的共享池里已经保存了该SQL唯一指令HASH值,并保留了语法语意检查及执行计划等相关解析动作的劳动成果,当再次执行该SQL时,由于该SQL指令的HASH值和共享池里保存的相匹配了,所以之前的硬解析动作就无须再做,不仅跳过了相关语法语意检查,对于该选取哪种执行计划也无须考虑,直接拿来用就好了。

3. 首次执行该SQL指令时,数据一般不在SGA的数据缓存区里(除非被别的SQL读入内存了),只能从磁盘中获取,不可避免地产生了物理读,但是由于获取后保存在数据缓冲区里,再次执行就可以直接从数据缓冲区里获取了,完全避免了物理读,效率高了不少。

我们可以在查询语句前加一句 set timing on表示跟踪该语句的执行完成时间然后进行两次执行,会发现第一次执行时可能花费物理读为3,第二次执行物理读便为0了。