Oracle-数据库的内存结构
⼀、内存结构的概述
Oracle数据库为 程序代码、⽤户共享的数据 以及 每个连接⽤户的私有数据区域,创建和使⽤了多个内存区域。这些相关的基本内存结构包括System Global Area(SGA)、Program Global Area(PGA)、User Global Area(UGA)、Software Code Areas等。
在数据库实例启动时,⾸先在服务器内存中分配⼀个包含了实例数据和控制信息的共享内存区域(SGA),然后启动⼀组常驻内存的后台进程(执⾏维护任务,例如执⾏实例恢复、清理进程、编写重做缓冲区到磁盘等)。当客户端/应⽤程序连实例操作接数据库时,实例通过创建服务器进程(基于客户端请求执⾏⼯作,例如解析SQL查询并将放在共享池、创建和执⾏查询计划、从缓冲区缓存或磁盘中读取数据块),分配该进程专⽤的包含进程数据和控制信息的内存区域(PGA),来处理连接到该实例的客户端进程的请求。
⼆、SGA
即系统全局区域,是⼀组共享的内存结构,包含⼀个数据库实例的相关数据和控制信息,在实例启动时⾃动分配,在实例关闭时回收,包含⼀个数据库实例的相关数据和控制信息。所有的⽤户和服务器进程都共享。
SGA与后台进程⼀起构成⼀个数据库实例。服务器和后台进程是不驻留在SGA中的,⽽是存在于单独的内存空间。 SGA由多个内存组件组成,这些内存组件是⽤于满⾜特定类别的内存分配请求的内存池,其中包括Database Buffer Cache、Redo Log Buffer、In-Memory Column Store、Shared Pool、Large Pool、Java Pool、Streams Pool、Fixed SGA等。
SGA 中的数据字典缓存和其他信息会被实例的后台进程所访问,它们在实例启动后就固定在SGA中了,⽽且不会改变,所以这部分⼜称为固定SGA(Fixed SGA);Shared Pool、Java Pool、Large Pool和Streams Pool这⼏块内存区的⼤⼩是随系统参数设置⽽改变的,所以⼜通称为可变SGA(Variable SGA )。
SQL> show sga
Total System Global Area 4259229696 bytes  --总系统全局区域⼤⼩
Fixed Size                  2220072 bytes  --固定SGA⼤⼩
Variable Size            1660948440 bytes  --可变SGA⼤⼩
Database Buffers        2583691264 bytes  --数据缓冲区缓存⼤⼩
Redo Buffers              12369920 bytes  --重做⽇志缓冲区缓存⼤⼩
1、Database Buffer Cache
也叫Buffer Cache,即数据库缓冲区缓存或者缓冲区缓存,是存储从数据⽂件中读取的数据块的副本的内存区域。Oracle进程如果发现需要访问的数据块已经在Buffer Cache中,就可以直接读写在内存中的相应区域即相应的缓冲块,⽽⽆需读取数据⽂件以提⾼性能。
⼀个缓冲块(Buffer)的状态包括:Unused,不⽤的(从未被使⽤过或当前未被使⽤的块,是可供使⽤的块);Clean,⼲净的(较早被使⽤⽽现在包含了在⼀个时间点上是读⼀致版本的块,数据库可以定位并重⽤的块);Dirty,脏的(缓冲块中包含尚未写⼊磁盘的已修改数据。数据库必须在重新使⽤之前检查的块)
为了使缓冲区访问有效,必须确定要在内存中缓存哪些缓冲区以及从磁盘访问哪些缓冲区,数据库默
认使⽤了基于LRU的替换算法,是通过两个重要的链表实现的:写链表和最近最少使⽤链表(the Least Recently Used,LRU)。写链表所指向的是所有脏数据块缓存(即被进程修改过,但还没有被回写到数据⽂件中去的数据块,此时缓冲中的数据和数据⽂件中的数据不⼀致)。⽽LRU链表指向的是所有空闲的缓存、正在被访问的缓存以及还没有来的及移⼊写链表的脏缓存。LRU列表有⼀个热端和冷端。冷端的缓冲区是最近没有使⽤的缓冲区,热端的缓冲区是经常被访问并且最近被使⽤的缓冲区。当脏缓冲区到达LRU的冷端时,数据库将它们从LRU移到写链表,然后数据库编写器(DBW)会进程周期性地将写链表中的缓冲区写⼊磁盘。
当客户进程请求⼀个缓冲区时,服务器进程会先搜索缓冲区缓存中的缓冲区,如果数据库在内存中到缓冲区,则会发⽣缓存命中(cache hit),它就直接执⾏⼀个逻辑读取从内存中取该缓冲区。如果在buffer cache中没有到该数据块,即未命中(cache miss),它就需要先执⾏物理读取从数据⽂件中取出该数据块到缓冲区缓存中,然后再执⾏逻辑读取才能访问该数据块。
在将数据块读取到缓存中时,服务器进程需要从空闲列表种到⼀个适合⼤⼩的空闲缓存,如果空闲列表中没有适合⼤⼩的空闲缓冲块,就会从冷端开始查LRU链表,在查过程中,如果进程到⼀个脏缓存块,它将这个缓存块移到写链表中去,然后继续查;当它到⼀个空闲块后,就从磁盘中将数据块读取到内存的缓存块中,并将这个缓存块移到LRU链表的中间;当进程查到块数最⼤限制后还没有到可供使⽤的缓存块,就停⽌查LRU链表,并且通过信号通知DBW将脏缓存写⼊磁盘以
提供可⽤的缓冲块;⽽当内存不⾜迫使数据库将数据写⼊临时表并在稍后读取数据时,就会出现⼀个临时⽂件。
数据库使⽤触摸计数来度量LRU列表上的缓冲区访问频率,该机制能够在缓冲块被命中时增加计数器,计数规则为三秒内的⼀和多次命中都计数为⼀次,触摸计数⾼的缓冲块就会移动到热端,移动时仅更改LRU列表的指针
数据库对表扫描时,默认情况下磁盘读取缓冲区插⼊到LRU列表的中间,⽽对于全表扫描,默认只有当表⼤⼩占缓冲区⾼速缓存的⼀⼩部分时才将⼩表加载到内存中;对于⾮常⼤的表,数据库通常使⽤直接读取的路径,该路径将直接加载到PGA中并绕过SGA,以避免填充缓冲区缓存;对于中等⼤⼩的表,如果它决定使⽤缓存读取,那么数据库将把块放在LRU列表的冷端,以防⽌有效的缓存块被清除。
2、Redo Log Buffer
即 重做⽇志缓冲区, 是SGA中的循环缓冲区,⽤于存储 描述对数据库所做更改 的 重做条⽬。重做记录是⼀种数据结构,它包含了通过DML或DDL操作对数据库进⾏重构或重做的所需信息。数据库恢复时将重做条⽬应⽤于数据⽂件以重建丢失的更改。
数据库进程将重做记录从⽤户内存空间复制到SGA中的重做⽇志缓冲区。重做记录在缓冲区中占据连续的、连续的空间。后台进程中的⽇志写⼊进程(LGWR)将重做⽇志缓冲区写到磁盘上活动的重做⽇志⽂件(Redo Log File)组中。
LGWR会按顺序写⼊磁盘,⽽DBW是将数据块分散写⼊磁盘。分散写⼊往往⽐顺序写⼊慢得多。由于LGWR使⽤户可以避免等待DBW完成其慢速写⼊,因此数据库可以提供更好的性能。当DBW将数据块写到磁盘上时,LGWR会按顺序重写到磁盘。分散的写往往⽐顺序写慢得多。由于LGWR使⽤户能够避免等待DBW完成其慢写操作,因此数据库提供了更好的性能。
3、In-Memory Column Store
即 内存列存储(IM列存储),是12C开始的⼀个可选的静态SGA池,在IM列存储中的数据以列状格式进⾏存储。内存中的列存储不会替换数据库缓冲区中的缓存,它们是相互补充的,两个存储区可以以不同的格式存储相同的数据。可以为表、物化视图、分区和表空间这些数据库对象启⽤内存列存储;在表空间级别启⽤内存列存储会⾃动启⽤内存列存储的表空间中的所有表和物化视图。
IM列存储使数据库能够在执⾏扫描、连接和聚合等操作时拥有更⾼的性能。可⽤于 对⼤型表格执⾏快速全⾯扫描;扫描⼤量的⾏和应⽤过滤器,例如<,>,=,和IN;从⼤量列中查询列的⼀⼩部分,例如从100列的表中选择5列;将⼀个⼩表加⼊⼤表中,特别是在连接条件过滤⼤部分⾏时。
即 共享池,⽤于存放SQL语句、PL/SQL代码(程序单元)、数据字典、系统参数和其他控制信息。
共享池来缓存许多不同类型的数据。缓存的数据包括PL/SQL块和SQL语句、字典缓存数据、结果缓存数据和其他数据的⽂本和可执⾏形式。 共享池分为⼏个⼦组件:Library Cache、Data Dictionary Cache、Server Result Cache、Reserved Pool等。
4.1 Library Cache
即 库缓存,是⼀个存储最近引⽤的可执⾏SQL和PL/SQL代码的共享池内存结构,包含了共享SQL区域、PL/SQL区域、其他的如锁和库缓存句柄的控制结构。
4.1.1 Shared SQL Areas
即 共享SQL区域,Oracle会为每⼀条SQL语句的运⾏(每运⾏⼀条语句Oracle都会打开⼀个游标)提供⼀个共享SQL区(Shared SQL Areas)和私有SQL区(Private SQL Areas,属于PGA)。
共享SQL区存储的是最近执⾏的SQL语句、解析后的语法树和优化后的执⾏计划,后续执⾏相同的SQL语句就直接利⽤在共享SQL区中缓存的解析信息,不必再重复做语法解析。
私⽤SQL区存储的是在执⾏SQL语句的会话或⽤户的私有的相关信息,不同的会话即使执⾏相同的SQL语句也不会使⽤这些信息,⽐如绑定变量、执⾏环境和会话参数等。
Oracle在执⾏⼀条的SQL语句时:先为会话分配⼀个私有SQL区域;然后检查共享池,查看共享的SQL区域是否存在语法和语义相同的语句,如果存在则使⽤共享的SQL区域中的缓存信息来执⾏语句,这称为软解析;如果不存在在⼀个相同的即语法相同的语句,那么数据库将在共享池内存中分配⼀个新的共享SQL区域,这称为硬解析;如果存在相同语法但不同语义的语句则使⽤共享⽗游标⽣成⼦游标的⽅式来执⾏语句,也称为硬解析。
4.1.2 Program Units
即 程序单元, 库缓存中包含的PL/SQL程序和Java类的可执⾏形式,称为程序单元。
数据库处理程序单元类似于SQL语句,也会分配⼀个共享的区域来保存解析的、已编译的PL/SQL程序,同时也分配⼀个私有的区域来保存运⾏该程序的会话的信息,包括本地变量、全局变量和包变量以及执⾏SQL的缓冲区。每个运⾏相同的程序单元的⽤户,都共享⼀个共享区域,同时维护各⾃的私区域⽤户保存会话特定的变量值。
⼀般情况下,共享池中的项会⼀直保持,直到根据最近使⽤的(LRU)算法删除它。使⽤ALTER SYSTEM FLUSH
SHARED_POOL语句可以⼿动删除共享池中的所有信息,⽣产环境慎⽤。
4.2 Data Dictionary Cache
即数据字典缓存,保存的是数据库相关的对象信息,包含数据库的结构、表和视图的定义、⽤户及其⼝令和权限等信息。所有的服务器进程共享这些缓存以访问数据字典信息。数据库在SQL语句的解析过程中通过访问该缓存来确定对象是否存在和具有权限等。字典缓存的内容是按⾏(Row)存储的,其他数据通常按数据块(Buffer)存储,所以⼜被称为 Row Cache,其信息可以通过 v$rowcache 查询。
4.3 Server Result Cache
即服务器结果缓存,存在于共享池中的内存池。与缓冲区(Buffer Cache)不同,服务器结果缓存包含的是结果集,⽽不是数据块。服务器结果缓存包含 SQL Query Result Cache 和 PL/SQL Function Result Cache,它们共享相同的基础结构。客户端结果缓存与服务器结果缓存不同,客户端缓存是在应⽤程序级别配置的,它位于客户机内存中,⽽不是在数据库内存中。
4.3.1 SQL Query Result Cache
即 SQL查询结果缓存,是存储查询和查询⽚段结果的服务器结果缓存的⼀个⼦集。⼀个重复运⾏同⼀个SELECT语句的应⽤程序,如果结果被缓存,那么数据库将⽴即得到返回,避免了重新读取块和重新计算结果的昂贵操作,⼤多数应⽤程序都得益于这种性能的改进。
执⾏查询时,数据库先搜索内存中的查询结果缓存来确认结果是否已经被缓存,如果结果存在则从直接内存中检索结果,⽽不是执⾏查询;如果结果没有被缓存则执⾏查询,将结果作为输出返回,然后将结果缓存在查询结果缓存中;当事务修改了⽤于构造查询缓存结果的数据库对象中的数据或元数据时,数据库会⾃动地使查询结果缓存中结果失效。
4.3.2 PL/SQL Function Result Cache
即 PL/SQL函数结果缓存,是存储函数结果集的服务器结果缓存的⼀个⼦集。如果没有缓存,每秒1000个函数的调⽤将花费1000秒。通过缓存,具有相同输⼊的1000个函数调⽤可能需要1秒。利⽤结果缓存⽽执⾏效果好调⽤,通常是依赖于相对静态的数据的函数。
PL/SQL函数代码可以包含缓存其结果的请求。在调⽤这个函数时,系统检查缓存。如果缓存包含了具有相同参数值的前⼀个函数调⽤的结果,则系统将缓存的结果返回给调⽤者,并且不会重新执⾏函数体。如果缓存不包含结果,则系统将执⾏该函数体,并将结果(对于这些参数值)添加到缓存中,然后将控制权返回给调⽤者。
缓存可以累积许多的结果,每个结果缓存是⼀个缓存函数和被调⽤的参数值的唯⼀组合。如果数据库需要更多的内存,它会⽼化⼀个或多个缓存的结果。
4.4 Reserved Pool
即 保留池,是共享池中的⼀个内存区域,Oracle数据库可以使⽤它来分配⼤量连续的内存块。
数据库从共享池中分配内存,块允许⼤型对象(⼤于5k)加载到缓存中,⽽不需要单个连续区域,这样,数据库就减少了由于碎⽚⽽耗尽连续内存的可能性。通常,Java、PL/SQL或SQL游标可能会从⼤于5kb的共享池中进⾏分配。为了使这些分配最有效地进⾏,数据库将少量的共享池隔离在保留池中。
即Java池,也是SGA中的⼀块可选内存区,它也属于SGA中的可变区,⽤于存储所有会话特定的Java代码和和Java虚拟机中的数据。该内存包括在结束调⽤时迁移到Java会话空间的Java对象。
对于专⽤服务器的连接,Java池包括每个Java类的共享部分,包括⽅法和只读内存,⽐如代码向量,但不包括每个会话的每个会话Java状态。对于共享服务器,池包括每个类的共享部分以及每个会话状态的⼀些UGA。每个UGA都根据需要增长和收缩,但是UGA的总⼤⼩必须适合于Java池空间。
Java Pool Advisor统计信息提供了有关于Java的库缓存内存的信息,并预测Java池⼤⼩的变化如何影响分析效率。当
statistics_level设置为TYPICAL或更⾼时,Java Pool Advisor在内部打开。当advisor关闭时,这些统计信息将被重置。
6、Large Pool
即⼤池,是SGA中的⼀块可选内存池,根据需要时配置。数据库实例使⽤以下功能时应考虑配置⼤型池:为共享服务器配置⼤型池来分配⽤户全局区域(UGA);为并⾏查询配置⼤型池来缓存并⾏执⾏消息缓冲区;为恢复管理器(RMAN)的备份和恢复配置⼤型池来缓存I/O 缓冲区;使⽤分布式事务处理的Oracle XA接⼝时配置⼤型池。
如果没有创建⼤池,则这些需要⼤量内存空间的操作将占⽤share pool的内存,通过在⼤池中分配会话内存给共享服务、Oracle XA、并⾏查询以及备份和恢复操作,可以减少share pool因为频繁的为⼤对象分配和回收内存⽽产⽣的碎⽚,提⾼shared pool的使⽤效率,防⽌由于共享SQL缓存收缩导致的性能消耗。
⼤池是属于SGA的可变区,没有LRU链表,当数据库将⼤型池的内存分配给⼀个会话时,在会话完成使⽤之前不能被释放,且只要⼀块内存被释放,其他进程就可以使⽤它。
7、Streams Pool
即流池,也是可选内存区,属于SGA中的可变区。流池⽤于存储缓冲队列消息,并为Oracle流捕获进程和应⽤程序提供内存。流池仅供Oracle流使⽤。除⾮专门配置它,否则流池的⼤⼩从0开始并根据Oracle流的需要动态增长。
8、Fixed SGA
即 固定SGA,是⼀个内部管理区域。
固定的SGA包含有关后台进程需要访问的数据库和实例状态的⼀般信息和进程之间交流的信息如关于锁的信息等
固定SGA的⼤⼩由Oracle数据库设置,不能⼿动更改。 固定SGA的⼤⼩可以从释放到释放。
三、PGA
即进程全局区域,是⼀个内存区域,在⼀个服务器进程或后台进程启动是创建,包含服务器进程和后台进程的相关数据和控制信息;PGA是特定于进程的⾮共享的内存区域,⼀个PGA只能被拥有它的那个进程所访问;PGA不在SGA中分配。
PGA被细分为不同的区域,每个区域都有不同的作⽤,包括Private SQL Area和SQL Work Areas等。
1、Private SQL Area
即 私有SQL区域,⼀个私有SQL区域包含关于⼀个已解析的SQL语句和其他特定于会话的信息的处理信息。当服务器进程执⾏SQL 或PL/SQL代码时,进程使⽤专⽤SQL区域存储绑定变量值,查询执⾏状态信息和查询执⾏⼯作区域。
不要将PGA中的私有SQL区域与在SGA中存储执⾏计划的共享SQL区域混淆。相同或不同会话中的多个私有SQL区域可以指向SGA 中的单个执⾏计划来共享,但每次执⾏的私有SQL区域因为可能包含不同的值和数据⽽不共享。
游标是特定私有SQL区域的名称或句柄,可以将游标视为客户端上的指针,并将其视为服务器端的状态。由于游标与私有SQL区域密切相关,因此这些术语有时可以互换使⽤。
⼀个私有SQL区域⼜被划分为run-time area和persistent area两个⼦区域。
1.1 The run-time area
即运⾏时区域,该区域包含查询执⾏状态信息。例如,运⾏时区域跟踪到⽬前为⽌在全表扫描中检索到的⾏数。
Oracle数据库创建运⾏时区域作为执⾏请求的第⼀步。对于DML语句,当SQL语句关闭即执⾏结束时,运⾏时区域将被释放。
1.2 The persistent area
即持久化区域,该区域包含绑定变量值。在执⾏语句时向SQL语句提供绑定变量值。只有当游标关闭时,持久区域才被释放。
客户端进程负责管理私有SQL区域,它的分配和释放很⼤程度上取决于应⽤程序,尽管客户端进程可以分配的私有SQL区域的数量受到初始化参数OPEN_CURSORS的限制。
虽然⼤多数⽤户依赖数据库实⽤程序的⾃动游标处理,但Oracle数据库编程接⼝为开发⼈员提供了对游标的更多控制。通常,应⽤程序应关闭所有打开的游标,这些游标不会再次⽤于释放持久区域,并尽量减少应⽤程序⽤户所需的内存。
2、SQL Work Areas
⼯作区域是⽤于内存密集型操作的PGA内存的私有分配。当启⽤⾃动PGA内存管理时,数据库会⾃动调整⼯作区域的⼤⼩,也可以⼿
动控制和调整⼯作区域的⼤⼩。
例如,Sort操作符使⽤排序区域对⼀组⾏进⾏排序。类似地,Hash连接操作符使⽤哈希区域从它的左侧输⼊构建⼀个哈希表,⽽bitmap merge使⽤位图合并区域来合并从多个位图索引的扫描中检索到的数据。
⼀般来说,较⼤的⼯作区域可以显著的提⾼性能,但会以较⾼的内存消耗为代价。最佳的是,⼯作区域的⼤⼩⾜以容纳由其关联的SQL操作符分配的输⼊数据和辅助内存结构。如果没有,响应时间增加,
因为输⼊数据的⼀部分必须缓存到磁盘上;⽽在极端情况下,如果⼯作区域的⼤⼩与输⼊数据⼤⼩相⽐太⼩,则数据库必须对数据块执⾏多次传递,从⽽显着增加响应时间。
三、UGA
oracle游标的使用即 ⽤户全局区域,UGA是会话内存,它是为会话变量分配的内存,如登录信息以及数据库会话所需的其他信息。实质上,UGA存储了会话状态。
在会话期间,必须向数据库会话提供UGA,因此,在使⽤共享服务器连接时UGA不能存储在PGA中,因为PGA特定于单个进程,所以UGA在使⽤共享服务器连接时存储在SGA中,使任何共享服务器进程都能访问它。当使⽤专⽤服务器连接时,UGA存储在PGA中。
如果会话将PL/SQL包加载到内存中,则UGA包含包状态,即在特定时间内存储在所有包变量中的⼀组值。当包⼦程序更改变量时,包状态会发⽣变化。默认情况下,包变量是唯⼀的,并在会话的整个⽣命周期中保持不变。
OLAP page pool也存储在UGA中。这个池管理OLAP数据页⾯,这相当于数据块。页⾯池在OLAP会话开始时分配,并在会话结束时释放。每当⽤户查询多维度对象(如多维数据集)时,OLAP会话都会⾃动打开。
四、Software Code Areas
即 软件代码区域,软件代码区是内存的⼀部分,⽤于存储正在运⾏或可以运⾏的代码。 Oracle数据库代码存储在通常⽐⽤户程序的位置更独特和受保护的软件区域中。
软件区域通常是固定的,只有在更新或重新安装软件时才会更改。这些区域所需的⼤⼩因操作系统⽽异。
软件区域是只读的,可以安装共享或⾮共享。⼀些数据库⼯具和实⽤程序如SQL*Plus可以安装共享,但有些不能。在可能的情况下,共享数据库代码,这样所有⽤户都可以访问它,⽽不会在内存中有多个副本,从⽽减少主内存和整体性能的改善。如果在同⼀台计算机上运⾏,数据库的多个实例可以使⽤不同数据库的相同数据库代码区。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。