Oracle 体系结构

Linux/Unix上,Oracle是多个进程实现的,每一个主要函数都是一个进程;在Windows上,则是一个单一进程,进程中包含多个线程。

Oracle把一系列物理文件,如数据文件(Data file)、控制文件(Control file)、联机日志(Redo log file)、参数文件(spfile or pfile)等物理结构及与之对应的逻辑结构,如表空间(Tablespace)、段(Segment)、块(Block)等组成的集合,称为数据库(Database)。 

Oracle内存结构和后台进程被做成数据库的实例(Instance),一个实例最多只能安装(Mount)或打开(Open)在一个数据库上,负责数据库的相应操作并与用户交互。一般情况下,一个数据库对应一个实例,但是在特点的情况下,如OPS/RAC的情况下,一个数据库可以对应到多个实例。

Oracle实例(Instance)

Oracle内存结构

Oracle内存结构主要可以分共享内存区与非共享内存区,共享内存区主要由SGA(System global area)组成,非共享内存区主要由PGA(Program global area)组成

 

SGA

这里的数据可以被Oracle的各个进程共用,如果有互斥的操作,如锁定一个内存对象,则需要通过LatchEnqueue来控制。

每个Oracle实例(Instance)只能启动一个SGA,除非通过RAC等一些特殊的全局管理方式,否则不同的实例只能访问自己的SGA区域。

以上是典型的OLTP(联机事务处理)环境中的SGA的分配情况。

 

Fixed Size

包括了一些数据库与实例的控制信息、状态信息、字典信息等,启动的时候就固定在SGA中,而且不会改变。

Variable Size

包含了shared poollarge pooljava poolstreams pool、游标区和其它结构等。

Database buffers(Data buffer)

它是数据库中数据块缓冲的地方,数据块在内存中就缓存在这里。所以,在OLTP环境中,Data buffer是SGA中最大的缓冲区,是数据库性能高低的关键所在。

Redo buffers

它是为了加快日志写进程的速度而设立的缓冲区,在一般OLTP环境中,因为提交很频繁,所以一般不会很大。

SGA的大小信息也可以从v$sga中获得,与show sga的结果一样。v$sgastat记录了SGA的一些统计信息,v$sga_dynamic_components则保存了SGA中可以动态调整的区域的一些动态或者手工调整记录。

 

共享池(Shared pool)

共享池是SGA中非常关键的内存片段,特别是在性能和可伸缩性上。由初始化参数shared_pool_size决定其大小,在10g后,Oracle可以自动管理大小。

在典型的OLTP高可用环境中,一个太小的共享池会扼杀性能,导致出现Ora-04031错误,使系统停止运行。但是太大的共享池也将消耗大量的CPU来管理。在数据仓库环境中,因为并发进程的需要,可能会分配比较大的共享池。

在实际的高可用环境中,有很大的一部分故障就是因为共享池的原因而导致系统停顿甚至宕机,如Latch争用Ora-04031错误Library cache争用与等待。

共享池又可以分为SQL语句缓冲区(Library Cache)数据字典缓冲区(Data Dictionary)及一些控制结构。而数据字典缓存区与控制结构是用户无法直接控制的,所以,真正与用户有关的其实就是SQL语句缓冲区。

当一个用户第一次提交一个SQL语句,Oracle会将这句SQL进行硬分析(Hard parse),这个过程类似于程序编译,会耗费相对较多的时间,因为它要分析语句的语法与语义,获得最佳的执行计划(Sql plan),并在内存中分配一定的空间来保存该语句对应的执行计划等信息。

因为Oracle总是保存语句的执行信息,当数据库第二次或者多次执行该SQL时,Oracle自动跳过这个硬分析过程,变为软分析(Soft parse)快速分析(Fast soft parse),从而减少了系统分析的时间,减少CPU与Latch的消耗。

Oracle中只有完全相同的语句,包括大小写、空格、换行都要求一样,才能重复使用以前的分析结果和执行计划。

如果大量的,频繁访问的SQL语句都不采用绑定(Bind)变量,Oracle为了做SQL的硬分析,shared pool latch将变得严重争用与等待,同样也会消耗大量的CPU,直到机器的资源耗尽。另外,因为Oracle会从共享池中分配空间来保存刚做完硬分析的SQL语句,也将耗费大量的内存空间,而且,这些被浪费的空间无法被重用。

共享池采用LRU算法来决定共享池中的对象是否继续保持,假设一个语句已经被执行过了,如果长时间没有被使用,重新执行的时候,也将面临重新分析。

对于间歇性访问的比较大的对象,如自定义的过程与包,如果不想在运行过程中被系统自动交换出去,可以调用DBMS_SHARED_POOL.KEEP存储过程将该过程或包pin在共享池中,以减少重新载入的巨大代价。

可以通过如下命令手工清除共享池的内容:

与共享池相关的视图:

v$sqlarea,每条记录都显示了一个SQL语句的详细统计信息,包括历史以来的执行次数、物理读、逻辑读、耗费时间等。

v$sqltext_with_newlines,因为v$sqlarea只是记录了一个语句或者是一个游标的前1000个字符,如果是比较大的SQL语句,则不能在v$sqlarea中完全显示。在这个视图中,一个SQL语句分为多行保存,通过hash_value来标示语句,通过piece排序。

v$sql_plan,保存了被执行的SQL语句的执行计划。

v$shared_pool_advice,这个视图会对Oracle的共享池做一些预测,范围可能在当前值的50%~200%之间,其中的字段SHARED_POOL_SIZE_FACTOR说明了预测的共享池大小与现在大小的比例。

数据缓冲区(Data buffer)

它是影响OLTP系统性能的关键,因为它的Cache技术可以很大程度地避免磁盘寻道,直接从Data buffer中获得。所以,Oracle把从Data buffer获得的数据块叫Cache hit,把从磁盘获得数据块叫Cache miss,它们的比率就是我们常说的Data buffer命中率。OLTP的环境中,命中率一般要求在95%以上

大的Data buffer对提高系统的性能有巨大的好处,因为Data buffer比较大,缓冲的数据块也就比较多,命中率也就更高。

在典型的OLAP环境中,大的Data buffer则不一定是必要的,因为OLAP的查询基本是要求从磁盘返回,而且以直接读写居多,直接读写是不经过数据缓存区的,使得命中率失去意义。所以在OLAP环境中,需要考虑用更多的磁盘驱动器,OLAP的速度取决于硬盘的多少与系统的带宽。

数据缓存区中的块基本上在两个不同的列表中管理。一个是块的“脏”表(Dirty List),表示被用户修改过的数据块,采用检查点队列(Checkpoint queue)来管理这些脏的数据块,必要的时候通过数据库写进程(DBWR)来写入这些脏块;另外一个队列是不脏的块的列表(LRU List),比如通过Select从磁盘获得的数据块。

快缓冲区高速缓存又可以细分为以下三个部分Default poolKeep poolRecycle pool,在9i以前,它们对应的是db_block_buffersbuffer_pool_keepbuffer_pool_recycle三个参数,分别表示每个缓冲区块的个数。从9i开始,又重新引入了三个新的参数:db_cache_sizedb_keep_cache_sizedb_recycle_cache_size分别表示该缓冲区的字节大小

从9i开始,Oracle支持创建不同块尺寸的表空间,这个新的特性同时也解决了在不同块大小的数据库之间传输表空间的问题,并且可以为不同块尺寸的数据块指定不同大小的数据缓冲区。不同块尺寸的数据缓存区的大小就由相应的参数db_nk_cache_size来指定,其中n可以是2,4,8,12或32。如创建了一个大小为2k的非标准尺寸的表空间,就可以指定db_2k_cache_size为这个表空间指定缓存区的大小。

正确使用Default pool、Keep pool、Recycle pool也可以提高系统的性能,如把一个访问很频繁的表或索引放置在适当大小的Keep pool中,可以减少物理读,提升IO性能。是否决定使用这个功能,要看系统的具体情况,如参考Statspack中的Segment统计信息,关注其中的物理读部分,分析Top物理读的对象,如果有些对象的确不大,但是物理读有很大,就可以考虑缓冲分离。

视图v$db_cache_advice与共享池的v$shared_pool_advice一样,由Oracle自动根据一些数字模型算法,收集信息后产生的一系列建议值,可以作为调整Data buffer大小的参考。

v$bh与x$bh

v$bh记录了数据块在数据缓冲区内使用的情况,一条记录对应一个Block的详细信息。

v$bh的来源与x$bhx$le,但是,主要数据与字段都是来源于x$bh

不同的是,x$bh包含了更多的信息,如touch count得信息,在8i以上作为LRU算法的一个重要参考信息,表示了一个块的热点程度。

(1)对象有多少个数据块缓冲在Data buffer中

先创建测试表,插入数据

用show_space存储过程分析表的空间使用情况

这张TEST表一共使用了16个块,数据文件id为6,再分析一下数据所在的Rowid

(通过Rowid查询使用了哪些数据块,只适合没有发生行迁移与行链接的情况下,如新创建的表,插入的小记录是适合的。如果发生了行迁移与行链接,因为Rowid本身不发生变化,而数据块的使用却会发生变化)

数据块其实只占用了8个块,但是表合计占用了16个数据块,另外8个是段头、位图块等,是表中的额外开销。

现在查询一下x$bh与v$bh,看看它们中间保存了几条记录

这两个查询都返回了16条记录,中间包含了数据块所在的8个块。看x$bh返回了块的触摸(tocun count)

表示了一个块的热点程度,当前最热的是数据块146,它并不是数据块,而是段头,通过如下查询可以证明:

看v$bh返回了快的状态信息,这里是xcur,表示排斥状态,被当前instance独占,也就是该块正在被使用。常见的状态还有scur表示被instance共享;cr表示一致性读;free表示空闲的状态;read表示正在从磁盘上读取;write表示正在被写入。这个时候,手工清除一次Data buffer,情况如下:

可以看到,x$bh中的块的tch都恢复到0了,而v$bh中的状态也都变成free了,但是记录数并没有发生变化,也就是说,数据块虽然被刷新到磁盘上去了,数据块的记录指针只不过是简单地被清空而已。

如果统计一个对象的非free状态的v$bh的记录数,基本就反映了一个对象在Data buffer中的被Cache的块数

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值