Oracle体系结构(一):内存结构

实例的概念

下图是整个Oracle数据库的体系:

image

我们的Oracle数据库要跑起来,当然需要有Oracle软件+数据文件,一个需要内存空间,一个需要硬盘空间。对应着实例与数据库文件。

实例就是Oracle软件在内存中的主要工作区域。所有与客户端的沟通,所有的SQL语句(DML,DDL....)和RDBMS的命令(startup,shutdown......)都在这个区域中运行,所以数据库的性能如何,40%是由实例决定的(提升性能,当然要加内存和升级CPU)

实例(INSTANCE) = 内存结构 + 后台进程

一、内存组成

1 、内存基本结构

内存结构主要由SGA和PGA构成,最大的区别是,SGA是共享的,PGA是非共享的内存区域

它们空间的分配时机:

当实例启动时分配SGA

当server process启动时分配PGA

每个版本Oracle的体系都有些差异,下图仅作参考。下面的UGA是在大池(large pool)中的,因为是在共享服务器模式下

image

1、PGA[程序/进程全局区]

PGA作用与结构

PGA是server process的的专有内存区域,主要服务于会话的操作,其中有一个内存区域叫UGA,是用来保存会话(session)的一些信息(在共享服务器模式,UGA是在SGA中的)

在ORACLE数据库中PGA只有一个,但是没有会话会拿到PGA的一个完整的结构克隆体,去进行独立且私有的操作(独占模式下)

如果是共享模式,那么有些PGA的结构会建立在SGA中当然再调用相关结构的时候依旧是会话独占的

类似JAVA中的类与对象,Oracle中的PGA是一个完整的结构,而且它有一定的空间,但是每一个会话链接的时候,是不允许使用这个大的PGA的,为什么?

因为太危险了,实例PGA(大PGA)如果被这个会话被弄挂了,其他的会话怎么办?

PGA中的栈与堆

PGA中有堆区和栈区

栈区(STACK AREA)

ORACLE所有代码均由C/C++开发的。

C与C++的共性,所有的变量都在栈这个内存对象用进行赋值与销毁。

所以ORACLE栈区主要负责:

1)对SQL语言出现的变量进行快速赋值

2)对PLSQL中出现的变量进行快速赋值

3)对ORACLE数据库中相关的进程进行变量赋值和进程内存持久化操作

处理sql语句过程

1、user process 与server process 建立session

2、 用户发出一条select语句

3、 sql语句交由sp处理

---------- SQL语句解析 ----------
4、 UGA中的语法解析

5、私有sql区中的语义解析

6、SQL工作区真正运行

---------- 分支1 :Oracle标准读 ----------

7、server process读数据块到buffer cache中

8、server process从buffer cache读出来传到session中,返回结果集

9、server process把结果集放到share pool的结果集缓存中

---------- 分支2:Oracle直接路径读 ----------

7、server process直接读数据到PGA的特定区域内(临时结果集缓存,不在体系结构内,是独立的内存区域)

8、server processPGA中读数据到session,用户收到数据

9、不会产生结果集缓存

标准读在数据量较大的情况发生,直接路径读是在数据量较小的时候发生

是由Oracle优化器自主选择的

多数人选择关闭直接路径读

包含单个服务器进程所需的数据与控制信息。比如每个人session传入的sql绑定变量,如果session进行了排序或者hash链接操作,也会使用PGA中的内存。

1)UGA:语法解析

请看下面

2)私有SQL区:语义解析

不要混淆在UGA中的私有SQL区

21C的说法标准:

分为解析区与运行区

优化器(CBO)就在运行区里

SGA中有share pool分为库缓存、字典缓存、其他等。

persistent area持久区,但是新的叫法脚解析区

这个地方非常复杂,Oracle从业人员最不愿意碰的地方

主要对SQL的语义解析

功能:

# 1 判断对定义名里的对象是否有权限

首先要判断能不能连上来

为什么不发生在语法解析里?就是上一步的UGA里?而是跟到了语义解析里?

因此语句已经到解析区了,如果权限不够,就等待赋权。

赋权后,再执行一次这条语句,其实是重新激活在解析区的这条语句。

不激活的话,某个时间后(60秒)就不存在了

# 2 SQL的HASH转换

这一步将SQL语句转换成HASHCODE,进而发生软解析和硬解析判断。

在oracle和mysql都使用了软硬解析判断,来判断SQL语句是否发生过,

但是oracle软硬解析判断发生在语义解析过程,mysql的软硬判断在sql刚提交的时候。mysql是不需要进行hash转换的,而是直接判断ASCII码。而oracle是要发生语句转换的,转换成hashcode来加速软硬解析判断的速度。

hashcode的优点

hash时间复杂度O(1),key-->value

为什么mysql与oracle不一样?

mysql效率为王,mysql的体系结构不复杂

软硬解析判断过程

HASH算法来自于操作系统而不是数据库。

在PGA的私有SQL区中,把要执的SQL语句转换为HASHCODDE ,转换好后,server prcess将hashcode从PGA中与SGA 的share pool中的库缓存中进行hashcode对比,看看是否之前已经执行过。

执行过的话,将执行过语句的执行计划树直接拿到PGA中交由该语句直接到SQL运行区中直接执行即可(这是软解析) 。如果没有的话,那么server process会通知该语句接着向后执行(硬解析)

问题:HASHCODE放在什么地方?

放在SGA的share pool的库缓存里。

问题:HASHCODE保留多久?

按照库缓存大小和LRU算法进行判断

问题:一条SQL语句,如果where后的量变化的话。我们怎么保证软解析的发生?

使用绑定变量:

select * from where id = &id;

# 3 视图映射

将视图映射回基表上

# 4收集统计信息

最好收集统计信息

# 5 优化器介入

看使用了哪一种优化器RBO/CBO

RBO:基于规则的优化器

9i之前的优化器,Oracle官方模拟不同情况,写好的一种规则

金蝶,用友推荐使用RBO,在ERP系统中语句是比较固定的

CBO:基于开销的优化器

oracle,mysql都在使用

# 6 根据统计信息生成直方图

# 7 根据直方图指定可能的SQL执行方案,生成柱状图

生成柱状图

# 8 从柱状图中找到开销最小的那个执行计划

# 9 生产最终执行计划

并交到SQL运行区中,调用server process安装最终执行计划开始生产执行SQL。

其实也不是真正的执行计划,真正执行的时候会根据实际情况调整,真正的执行计划是发生在sql执行后的

-- 真正的执行计划
set autotrace on explain

PLSQL按F5生产的是解析计划,是发生在sql语句执行前的

3)SQL工作区 SQL Work Areas

SQL真正发生运行的地方,也分为了几个区

哈希区

hash区:如果sql语句产产生hash链接的话,这里将缓冲部分数据。如果该区域被用完了,那么就会使用临时表空间进行相关操作

sql语句一共有几种连接方式?

hash链接,笛卡尔积,排序合并,nest join

排序区:

如果sql语句产生排序,这里会缓冲部分数据。

位图区:

我们在创建索引和建表的时候需要调用系统表,那你使用系统表的时候,就会产生位图索引以及位图索引需要临时国建的数据。当然直接创建位图索引直接使用该区域。

如果该区域不够的话就会使用临时表空间。

谁是SQL工作区的补充?

临时表空间

2、SGA

1)数据库缓冲区缓冲 database buffer cache

DB buffer cache是SGA中最大的一部分,是用来存放从数据文件中读取到的数据块的副本,所有连接到同一数据库实例的用户,都可以访问得到。

这个缓冲区具有的一些结构:默认池(db_cache_size),保持池(buffer_pool_keep),回收池(db_pool_recycle)

缓存的作用

优化物理I/O

是Oracle执行SQL的区域。存数据块的拷贝信息

从数据文件没读一次到buffer cacha 就有一次IO

减少物理读(物理读:从数据文件里读),如果buffer cahe有的话就从内存里取,就不用IO了

数据库更新缓存中的数据块,并将有关更改的元数据存储在重做日志缓冲区。提交之后,数据库将重做缓冲区写入磁盘,但不一定会立即将数据块写入磁盘。相反,数据库写入器 (DBWn) 在后台执行惰性,写入操作

优化性能

显而易见的:将频繁访问的块保持在缓冲区高速缓存中,而将不常存取的块写到磁盘

数据块

数据文件中数据块是8k大小,读取到buffer中也是8k

在内存中的管理方式

数据一次读取到内存中,只要不被换出,就会一直在缓冲区中存在,等待下一次读取。

Oracle通过写入列表和LRU列表来管理这些缓存块。

写入列表:管理脏块,即已经发生修改,但未写入到数据文件中

LRU列表:包含FREE的buffer,命中的buffer已经未来得及写入的脏块。

注意数据的命中率(直接读db buffer cache的概率)

2)重做日志缓冲

是一个循环写的缓冲区

作用:存储改变信息

执行delete语句的时候,会先生成一条redo log,会先放在redo log buffer里

commit的时候,才会写到 redo log(文件)里

redo如何获得数据:

redo log buffer是SGA中一块循环使用的内存区域,保存数据库变更的信息。这些信息以重做条目(redo entries )形式存储。redo entries包含重构、重做数据库变更的重要信息,这些变更包括 INSERT UPDATE DELETE CREATE ALTER DROP 等

redo entries的内容被oracle数据库进程从用户的PGA中复制到SGA中redo log buffer中。

这解释了为什么redo buffer在SGA中,又是怎么获取用户的DML DCL语句的

redo entries 在内存中占用连续的顺序空间

redo log 是循环使用的,通过LGWR进程不断把redo log buffer的内容写到redo log file 中,redo log file 同样是循环使用的

image

为什么不直接写到文件中?

写入到磁盘之前要先在buffer中临时缓存这些数据。因为内存到内存的速度比内存到磁盘的速度快多了,因此使用buffer 可以加快数据操作

实际上数据在buffer中不会停留太长,LGWR会自动刷新(flush)

3)共享池 share pool

关键词:执行计划、硬解析、软解析

image

主要组成部分:

1)库缓存

库缓存是存放可执行SQL和PLSQL代码的内存结构。

包含共享SQL和PLSQL区。

在共享服务体系结构中,还包含私有SQL区

可以手动删除共享池中的所有信息:

 ALTER SYSTEM FLUSH SHARED_POOL

2)数据字典缓存区:

数据字典是数据库表和视图的集合,其中包含有关数据库及其结构、用户等参考信息。

部分v$视图,dba_*视图 all、user视图就存放在这里。

Oracle 数据库在解析 SQL 语句期间,会频繁访问数据字典Oracle 数据库如此频繁地访问数据字典,所以指定了以下这些特别的内存位置来保存字典数据:

数据字典缓存:此缓存保存有关数据库对象的信息。此缓存也称为 行缓存,因为它按行、而不是按缓冲区保存数据

库缓存:存放用过的sql和plsql

3)结果集缓存

与缓冲池保存数据块不同, 服务器结果缓存保存的是结果集。服务器结果缓存包含 SQL 查询结果缓存和 PL/SQL 函数结果缓存,它们共享相同的基础结构。

SQL结果集

数据库能在 SQL 查询结果高速缓存中存储查询和查询片段的结果,将此缓
存结果用于将来的查询和查询片段。大多数应用程序受益于这种性能改善。

例如,假设应用程序将重复执行相同的 SELECT 语句。如果结果会被缓存,
则数据库会将其立即返回。通过这种方式,数据库避免了重读块和重计算结
果等昂贵操作。每当事务修改了数据或用于构造该缓存结果的数据库对象元
数据时,数据库自动使其高速缓存结果无效

用户可以为查询或查询片断添加 RESULT_CACHE 提示,以指示数据库应将
其结果存储在 SQL 查询结果缓存中。由 RESULT_CACHE_MODE 初始化参
数确定 SQL 查询结果缓存将用于所有查询(如果可能) 还是仅用于添加了
注释的查询。

补充:硬解析与软解析

​ 在执行 SQL 语句时,数据库将尝试重用以前执行过的代码。如果在库缓存中存在该 SQL 语句的已解析表示形式,并且是可以共享的,则数据库会重用该代码,这称为 软解析或 库缓存命中。否则,数据库必须为应用程序代码建立一个新的可执行版本,这称为 硬解析或 库缓存未命中

作用

语法分析,编译,生产执行计划,运行执行计划。

共享,就是保存共享的执行计划

3、UGA[会话全局区]

会话全局区,也叫会话游标全局区,主要存放session的信息,还有打开的游标,执行语句中的私有变量等。UGA也分为两大部分,一个叫会话区;一个叫持久区,也叫游标持久区。

会话区

会话区的作用

保留会话产生的所有信息:客户端的ID,客户端进程状态,sever process的ID,sever process的状态,session ID,会话状态等。

如果你想知道那台机器连上了数据库,可以在会话区里找到。

会话区还做了其他事,也会校验相关的权限(用户的权限,能不能连),相当于MYSQL的链接池

持久区,游标持久区

游标的概念,在ORACLE数据库中有两种游标

1、程序游标,就是PLSQL中的cursor,只是一个程序体,负责采集结果集,并将结果集数据一一读出。

2、可执行游标,在ORACLE数据中所有可执行的SQL与PLSQL程序都被称为游标,在持久区中的游标就是一种可执行游标。

我们持久区中的游标是指:可执行游标

可执行游标分类:

父游标:游标(SQL/PLSQL)的明文语句。

子游标:父游标执行过程中产生的细节描述和最终由优化器产生的执行计划

持久区的主要功能:

检验SQL语法是否正确,以及你访问的相关对象是否存在 。

持久区不是不会区访问表和视图是不是真的存在,而是让持久区守护进程去让sever process访问系统表,去验证表或视图是否存在。

持久区还有一个隐藏功能:

判断事务与非事务的语句,事先判断是否发生事务

SQL语法过程

ORACLE数据库的SQL解析,真正意义上的第一个步,发生在UGA持久区中的语法解析:

1 判断SQL语法是否正确

判断关键字与关键字组合是否正确,不会判断定义名

2 判断定义名是否存在

3 预先判断是否发生事务

posted on 2023-02-28 16:44  兔哥DB  阅读(479)  评论(0编辑  收藏  举报

导航