Oracle | Concepts(11g)内存结构

       

目录

    Oracle数据库内存结构简介

     基本内存结构   

     Oracle数据库内存管理

    UGA概述

    PGA概述

     私有SQL区(Private SQL Area)

     运行区域(The run-time area)

     持久区域(The persistent area)

     SQL工作区(SQL Work Areas)

    专用和共享服务器模式下使用PGA的差异

    SGA概述

     Database Buffer Cache(数据库高速缓冲池)

     缓冲区的状态

     Buffer池(Buffer Pool)

     Redo日志缓冲区(Redo Log Buffer)

     共享池(Shared Pool)

     库缓存(Library Cache)

     共享SQL区(Shared SQL Areas)

     数据字典缓存(Data Dictionary Cache)

     服务器结果缓存(Server Result Cache)

     SQL查询结果缓存(SQL Query Result Cache)

     保留池(Reserved Pool)

     大池(Large Pool)

     Java池(Java Pool)

     流池(Streams Pool)

     固定SGA区(Fixed SGA)

    软件代码区概述


       今天翻出Oracle 11g的Concepts进行回顾,真是许久未见,发现最基础的内功部分都忘得差不多了,书还是得反复的读,现将Concepts(11g)内存结构部分的知识整理如下。

       内存结构部分在Concepts(11g)的第14章节,开篇说明本章包括5个部分,分别是介绍Oracle内存结构、UGA概述、PGA概述、SGA概述以及软件代码区概述。

    Oracle数据库内存结构简介

       启动实例时,Oracle数据库会分配一个内存区域并启动后台进程。内存区域存储如下信息:

  • 程序代码
  • 每个已连接会话的相关信息,即使它当前未处于活动状态
  • 程序运行中需要的信息,例如从已获取行取得当前查询的状态
  • 在进程间被共享和传递的信息, 如锁信息
  • 缓存的数据,如数据块和重做记录,同样也存在于磁盘上

     基本内存结构   

       Oracle的数据库的基本内存结构包括系统全局区(SGA)、程序全局区(PGA)、用户全局区(UGA)和软件代码区。

  • 系统全局区 (System global area)

       SGA是一组称之为SGA组件的共享内存结构,它包含数据库实例的数据和控制信息。SGA由所有的服务器进程和后台进程共享。例如在SGA中存储的数据,包括数据块缓存和共享SQL区。

  • 程序全局区(Program global area)    

       PGA是一个非共享内存区域,它包含数据和控制信息,仅供一个Oracle进程使用。当一个Oracle进程启动时,Oracle会创建PGA。每个服务器进程和后台进程都有一个PGA。所有PGA大小的总和是实例的总PGA,或者称之为实例PGA。数据库初始化参数设置的是实例 PGA大小,而不是单个PGA 的大小。

  • 用户全局区(User global area )

       UGA是与某个用户会话相关联的内存。

  • 软件代码区(Software code areas)       

       软件代码区域是内存的一部分,它用于存储正在运行或可以运行的代码。Oracle数据库代码存储在一个软件区域中,该软件区域通常位于与用户程序不同的位置—一个更独占或受保护的位置。

       

Figure 14-1 Oracle Database Memory Structures

     Oracle数据库内存管理

       内存管理涉及配置Oracle 实例内存结构的最优大小,Oracle数据库根据与内存相关的初始化参数的设置管理内存。内存管理的基本选项如下:

  • 自动内存管理(Automatic memory management)

       AMM,指定实例内存的目标大小。数据库实例自动调优目标内存大小,根据需要在SGA和实例PGA之间重新分配内存。

  • 自动共享内存管理(Automatic shared memory management)

       ASMM,这种管理模式是部分自动化的。您可以为SGA设置目标大小,然后可以选择为PGA设置总大小,或单独管理PGA的各个区域。

  • 手动内存管理(Manual memory management)

       您可不指定总的内存大小,可以通过一些初始化参数单独管理SGA的各个组件及PGA。

    UGA概述

       UGA是会话内存,它是分配给会话变量的内存,例如登录信息和数据库会话所需的其他信息。实际上,UGA存储的是会话状态。

Figure 14-2 User Global Area (UGA)

       如果会话将PL/SQL包加载到内存中,那么UGA会包含包的状态,它是在指定时间存储在所有包变量中的一组值(参考“PL/SQL包”)。当包的子程序更改变量时,包的状态就会更改。默认情况下,包变量对与会话是惟一的,并且在会话的生命周期中一直存在。

       OLAP页面池也存储在UGA中。这个池管理了相当于数据块的OLAP数据页。页面池在OLAP会话开始时分配,并在会话结束时释放。每当用户查询多维对象(如CUBE)时,OLAP会话就会自动打开。

       在会话的生命周期内,UGA必须对数据库会话可用。因此,当使用共享服务器连接时,UGA不能存储在PGA中,因为PGA是特定于单个进程的。因此,当使用共享服务器连接时,UGA存储在SGA中,允许任何共享服务器进程访问它。当使用专用服务器连接时,UGA存储在PGA中。

    PGA概述

       PGA是属于某个特定操作进程或线程的内存,它不被系统上的其他进程或线程共享。因为PGA是特定于进程的,所以它从来不在SGA中分配。

       PGA是一个内存堆,它包含专用或共享服务器进程所需的会话相关变量。在PGA中分配服务器进程需要的内存结构。

       PGA可以理解为是文件管理员使用工作台的一个临时区。在这个比喻中,文件管理员是负责客户(客户端进程)工作的服务器进程。工作人员清理出工作台的一部分后,使用这部分区域存储有关客户请求的详细信息,并对客户请求的文件夹进行排序,然后在完成工作后释放空间。

       图14-3展示了专用服务器模式下实例PGA(所有PGA)结构。可以使用初始化参数设置实例PGA最大的目标大小(参考“内存管理概述”)。单个PGA可以根据需要增长到这个目标大小。每一个PGA可以根据需要增长到这个目标大小。

Figure 14-3 Instance PGA

Note:

后台进程也会分配自己的PGA。本节只关注服务器进程PGA。

       PGA的结构

       PGA被细分为不同的区域,每个区域都有不同的功能。图14-4展示了专用服务器会话的PGA的内容。在不同的场景中,个别PGA区域可能不存在。

Figure 14-4 PGA Contents

     私有SQL区(Private SQL Area)

       私有SQL区域保存相关已解析SQL语句的信息和其他特定于会话的信息,以便进行处理。当服务器进程执行SQL或PL/SQL代码时,该进程使用私有SQL区域存储绑定变量值、查询执行状态信息和查询执行工作区域。

       不要将UGA中的私有SQL区域与SGA中存储执行计划的共享SQL区域混淆。相同或不同会话中的多个私有SQL区域可以指向SGA中的一个执行计划。例如,在一个会话中执行20次SELECT * FROM employees操作,在另一个会话中执行相同查询的10次操作,可以共享相同的计划。每个执行的私有SQL区域不共享,可能包含不同的值和数据。

       游标是特定私有SQL区域的名称或句柄。如图14-5所示,可以将游标理解为它是在服务端上存放的客户端指针状态。因为游标与私有SQL区域密切相关,所以这些术语有时可以互换使用。

Figure 14-5 Cursor

       私有SQL区被划分为以下两个部分:

     运行区域(The run-time area)

       这个区域包含查询执行状态信息。例如,运行时区域跟踪到目前为止在全表扫描中检索到的行数。

       Oracle数据库创建运行时区域作为执行请求的第一步。对于DML语句,在SQL语句关闭时运行区域将释放。

     持久区域(The persistent area)

       这个区域包含绑定变量值。在语句执行时将提绑定变量值供给SQL语句。只有在关闭游标时才释放持久区域。

 

       客户机进程负责管理私有SQL区域。尽管客户端进程可以分配的私有SQL区域的数量受到初始化参数open_cursor的限制,私有SQL区域的分配和释放主要还是取决于应用程序。

       尽管大多数用户依赖于数据库实用程序的自动游标处理,但Oracle数据库编程接口为开发人员提供了对游标的更多控制。一般情况下,应用程序应该关闭所有打开的游标,这些游标不会再次被用于释放持久性区域,并最小化应用程序用户所需的内存。

参考:

       共享SQL区

       Oracle Database Advanced Application Developer's GuideOracle Database PL/SQL Language Reference,学习如何使用游标(cursor)

     SQL工作区(SQL Work Areas)

       工作区是在PGA 为内存密集型操作分配的私有内存区。 例如,排序操作使用排序区来对一组行进行排序。同样,哈希联接操作将其左侧数据为输入,并使用哈希区来创建一个哈希表,而位图合并操作则使用位图合并区来合并从扫描多个位图索引检索到的数据。

       样例14-1展示了 employees 表和 departments 表相联接的查询计划。

SQL> SELECT * 
  2  FROM   employees e JOIN departments d 
  3  ON     e.department_id=d.department_id 
  4  ORDER BY last_name;
.
.
.
----------------------------------------------------------------------------------
| Id  | Operation           | Name        | Rows  | Bytes | Cost (%CPU)| Time    |
----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |             |   106 |  9328 |    7  (29)| 00:00:01 |
|   1 |  SORT ORDER BY      |             |   106 |  9328 |    7  (29)| 00:00:01 |
|*  2 |   HASH JOIN         |             |   106 |  9328 |    6  (17)| 00:00:01 |
|   3 |    TABLE ACCESS FULL| DEPARTMENTS |    27 |   540 |    2   (0)| 00:00:01 |
|   4 |    TABLE ACCESS FULL| EMPLOYEES   |   107 |  7276 |    3   (0)| 00:00:01 |
----------------------------------------------------------------------------------

       在这个例子中,运行时区域跟踪全表扫描的进度。此会话在哈希区中执行一个哈希联接,以匹配两个表中的行。而 ORDER BY 排序操作在排序区中进行。

       如果该操作要处理的数据量太大,工作区域不能满足,那么Oracle数据库将输入数据分成更小的部分。通过这种方式,数据库在内存中处理一些数据块,同时将其余的数据写到临时磁盘存储中以便稍后处理。

       当启用自动PGA内存管理时,数据库自动调整工作区大小。您还可以手动控制和调优工作区域的大小。有关更多信息,请参考“内存管理”。

       一般来说,较大的工作区域可以显著提高性能,但代价是会有更多的内存消耗。理想情况下,工作区的大小足以容纳输入数据和由其关联的SQL运算所分配的辅助内存结构。否则,响应时间会增加,因为部分输入数据必须缓存在磁盘上。在极端情况下,如果与输入数据大小相比,工作区的大小太小,那么数据库必须对数据块执行多次传递,极大的增加了响应的时间。

参考:

       Oracle Database Administrator's Guide,学习如何使用自动PGA管理

       Oracle Database Performance Tuning Guide,学习如何优化PGA内存 

    专用和共享服务器模式下使用PGA的差异

       PGA内存分配取决于数据库是使用专用的还是共享的服务器连接。表14-1说明了差异。

内存区域专用服务器共享服务器
会话内存的性质私有的共享的
持久区的位置PGASGA
DDL/DML运行区的位置PGAPGA

参考:

       Oracle Database Net Services Administrator's Guide ,学习如何配置共享服务器

    SGA概述

       SGA是一个可读写的内存区域,它与Oracle后台进程组成一个数据库实例。所有用户的服务器进程都可以读取实例SGA中的信息。在数据库运行作期间,有一些进程会向SGA写入数据。

Note:

       服务器进程和后台进程不驻留在SGA中,而是存在于单独的内存空间中。

       每个数据库实例都有自己的SGA。Oracle数据库在实例启动时自动为SGA分配内存,并在实例关闭时回收内存。当您使用SQL*Plus或Oracle Enterprise Manager启动实例时,SGA的大小如下例所示:

SQL> STARTUP
ORACLE instance started.
 
Total System Global Area  368283648 bytes
Fixed Size                  1300440 bytes
Variable Size             343935016 bytes
Database Buffers           16777216 bytes
Redo Buffers                6270976 bytes
Database mounted.
Database opened.

       如图14-1所示,SGA由几个内存组件组成,这些内存组件是用于满足特定类型内存分配请求的内存池。除了重做日志缓冲区之外,所有SGA组件都在称为颗粒化的连续内存单元中分配和释放空间。颗粒大小是平台特定的,由总SGA大小决定。

       您可以通过查询V$SGASTAT视图来获得SGA组件的信息。

       SGA中最重要的组件如下:

参考:

       "Introduction to the Oracle Database Instance",数据库实例的介绍

       Oracle Database Performance Tuning Guide ,了解更多关于颗粒大小的信息

     Database Buffer Cache(数据库高速缓冲池)

       数据库高速缓冲池,它是存储从数据文件中读取的数据块副本的内存区域。缓冲区是缓冲区管理器用来暂时缓存当前或最
近使用的数据块的主内存地址。所有用户可以同时连接到数据库告诉缓冲池中并以共享模式进行访问。

       Oracle使用数据库高速缓冲池有如下两个目的:

  • 优化物理I/O

       数据库更新缓存中的数据块,并在重做日志缓冲区中存储已更改的元数据。提交之后,数据库将重做缓冲区写入磁盘,但不会立即将数据块写入磁盘。数据库写进程(DBW)在后台执行惰性写入。

  • 将经常访问的块保存在缓冲区缓存中,并将不经常访问的块写入磁盘

       当启用数据库智能闪存高速缓存(Flash Cache)时,缓存的一部分可以驻留在闪存高速缓存中。这个高速缓存扩展存储在闪存设备上,这是一个使用闪存的固态存储设备。该数据库可以通过在闪存中缓存缓冲区而不是从磁盘读取来提高性能。

Note:

       数据库智能闪存高速缓存只在Solaris和Oracle Enterprise Linux中可用。

     缓冲区的状态

  • Unused

       缓冲区之所以可用,是因为它从未使用过或当前未使用。这种类型的缓冲区是数据库最容易使用的。

  • Clean

       这个缓冲区以前使用过,现在包含一个块的读取一致性版本。该块包含数据,但它是“干净的”,因此不需要检查。数据库可以固定块并重用它。

  • Dirty

       缓冲区包含尚未写入磁盘的修改数据。数据库在重用块之前必须要检查它。

       每个缓冲区都有一个访问模式:pinned或free(unpinned)。缓冲区被“pinned”在缓存中,这样当用户会话访问它时,它不会在内存之外。多个会话不能同时修改固定的缓冲区。

       数据库使用一种复杂的算法来提高缓冲区访问的效率。指向脏缓冲区和非脏缓冲区的指针存在于相同的最近最少使用链表 (LRU)中,该链表有热端和冷端。冷缓冲区是最近没有使用过的缓冲区。热缓冲区经常被访问,并且最近才被使用。

Note:

       从概念上讲,只有一个LRU,但是考虑到并发性,数据库实际上使用多个LRU。

       Buffer模式

       当客户端请求数据时,Oracle数据库会从数据库缓存中用以下模式之一检索缓冲区:

  • 当前模式

       当前模式获取,也称为db block get,是对当前出现在缓冲区缓存中的块的检索。例如,如果一个未提交的事务在一个块中更新了两行,那么当前模式获取会检索这个具有未提交行的块。在修改语句期间,数据库最常使用数据库块获取,它只需更新块的当前版本。

  • 一致模式

       一致读取获取是对块的读取一致版本的检索。此检索可能使用undo数据。例如,如果未提交的事务在一个块中更新了两行,并且单独会话中的查询请求该块,则数据库将使用撤消数据创建该块的读取一致性版本(称为一致读取克隆),该版本不包括未提交的更新。通常,查询以一致模式检索块。

参考:

       "Read Consistency and Undo Segments",了解一致读和回滚段

       Oracle Database Reference ,了解数据库统计信息的描述,例如, 数据库块获取和一致读取获取

       Buffer I/O

       逻辑I/O,也称为缓冲区I/O,指的是在高速缓冲区中对buffer进行读写操作。当在内存中找不到请求的buffer时,数据库会通过物理I/O将buffer从闪存缓存或磁盘复制到内存中,然后通过逻辑I/O读取高速缓冲区。

       Buffer写

       数据库写进程(DBW)定期将冷buffer、脏buffer写入磁盘。DBWn在以下情况下执行写操作:

       在数据库告诉缓冲区中,服务器进程找不到能将新块读入数据库告诉缓冲区缓存的“干净的”buffer。

       随着脏buffer增多,free buffer的数量就会减少。如果该数值低于一个内部阈值,而又需要干净的缓冲区,那么服务器进程将发出DBWn写的信号。

       数据库使用LRU链表来确定哪些脏buffer需要执行写操作。当脏buffer在LRU的冷端时,数据库会将它们从LRU移动到写队列。DBWn将队列中的缓冲区写入磁盘,尽可能使用多块写入。多块写机制可以防止LRU的末端被脏buffer阻塞,保证有足够多的干净的buffer进行重用。

       数据库必须推进检查点,检查点是重做线程恢复实例时的起点位置。

       表空间修改为只读或脱机状态。

参考:

       "Database Writer Process (DBWn)"

       Oracle Database Performance Tuning Guide,了解如何诊断和调优缓冲区写问题

       Buffer读

      当干净的buffer或free的buffer数量较少时,数据库必须从高速缓冲区缓存中移除buffer。这个算法取决于当前是否启用了闪存高速缓存(flash cache)功能:

       关闭闪存高速缓存功能

       数据库根据需要覆盖并重用每个干净的buffer。如果以后需要覆盖的buffer,那么数据库必须从磁盘读取。

       开启闪存高速缓存功能

       DBWn 将干净的buffer的正文写入到闪存高速缓存,使其内存中的缓冲区可以被重用。数据库在主内存的LRU中保留buffer头部信息,以跟踪它在闪存高速缓存中状态和位置。如果以后需要该buffer,数据库可以从闪存高速缓存中读取它,而不用从磁盘中读取。

       

       当客户端进程请求一个buffer时,服务器进程在高速缓冲区中搜索buffer。如果数据库在内存中找到该buffer,就会发生buffer命中(hit)。搜索流程如下:

       1.服务器进程在高速缓存区中搜索全部的buffer,如果进程命中了buffer,数据库执行逻辑读      

       2.服务器进程在闪存缓存 LRU 链标中搜索buffer头,如果进程找到了buffer头,那么数据库将执行一个优化物理读,将buffer正文信息从闪存高速缓存读入内存高速缓存中。

       3.如果在内存中没有找到这个buffer(a cache miss),那么服务器进程将执行以下操作:

         a.将该块从数据文件复制到内存中(物理读)

         b.对已读入到内存中的buffer执行一个逻辑读

       图14-6说明了buffer的搜索顺序。扩展的高速缓冲区缓存区包括内存中的缓冲区缓存(包含整个缓冲区)和闪存高速缓存区(包含buffer正文)。在图中,数据库搜索缓冲区缓存中的buffer,但是没有找到指定buffer,而是从磁盘将其读入内存。

Figure 14-6 Buffer Search

       一般情况下,通过缓存命中访问数据比通过缓存未命中要快。缓冲区高速缓存命中率(buffer cache hit ratio)用于衡量数据库在缓冲区高速缓存中找到请求的buffer与未找到请求buffer的比率。

       数据库可以对数据文件或临时文件执行物理读,紧跟着会发生逻辑I/O。当内存不足时会迫使数据库将数据写入临时表,然后从临时表中读取数据。这些物理读会绕过高速缓冲区,不会产生逻辑I/O。

参考:

       Oracle Database Performance Tuning Guide,学习如何计算缓冲区缓存命中率

       Buffer触碰计数

       数据库使用触碰计数来衡量LRU链表上buffer的访问频率。这种机制允许数据库在buffer被pin住时增加计数,而不是在LRU链表中不断的调整buffer。

Note:

       数据库不会物理地移动内存中的块。这种移动只是改变列表中指针的位置。

       当一个buffer被pin住时,数据库确定它的最后一次触碰发生在何时。如果计数是在三秒之前递增,则计数递增;否则,计数保持不变。三秒钟规则可以避免记录了buffer短时间内多次被pin的触碰计数。例如,一个会话可以在一个数据块中插入几行,数据库会将这些插入操作视为一次触碰。

       如果buffer位于LRU的冷端,但是它的触碰计数很高,那么这个buffer将会移动到热端。如果触碰计数很低,那么这个buffer就会被移出告诉缓冲区中。

       Buffer和全表扫描

       当必须从磁盘读取buffer时,数据库会将buffer插入到LRU的中间位置。通过这种方式,热块可以保留在高速缓存中,这样就不需要再次从磁盘读取它们。

       发生全表扫描时会产生一个问题,它按顺序读取表高水位线标记下的所有行(参考 "Segment Space and the High Water Mark")。假设表段中块的总大小大于缓冲区高速缓存的大小,那么在此表上的全表扫描可能会清除高速缓存,导致数据库不能将频繁访问的块维持在高速缓存中。

       对大表进行全面扫描后读取到数据库缓存的块的操作与其他类型的读操作不同。这些块可以立即重用,以防止该扫描真正清理了缓冲区高速缓存。

       个别情况下,如果不想使用这种默认的机制,您可以更改表的CACHE 属性。在这种情况下,数据库不会在告诉缓存中强制或pin住块, 而是与任何其他块相同的方式让其从高速缓存中移除。使用此选项时务必要小心,因为大表的全表扫描可能会将大部分的其他块从高速缓存中清理掉。

参考:

       Oracle Database SQL Language Reference,了解关于CACHE的信息

       Oracle Database Performance Tuning Guide,了解如何解释高速缓冲区缓存建议统计信息

     Buffer池(Buffer Pool)

       Buffer池是buffer的集合。数据库高速缓冲区被划分为一个或多个buffer池。

       您可以手动配置多个buffer池,要么将这些缓冲池的数据保存在高速缓冲区中,要么在使用数据块之后立即为新数据提供缓冲区。你可以将指定的模式对象分配给合适的缓冲池,以控制数据块以何种方式从缓存中移出。

       Buffer池的构成如下:

  • 默认池(Default pool)

       该池是块通常被缓存的地方。除非手动配置单独的池,否则默认池是唯一的缓冲池。

  • 保留池(Keep pool)

       该池用于被频繁访问的块,使其不会由于缺省池的空间不足而被移出。保留缓冲池的目标是将对象保留在内存中,从而避免 I/O 操作。

  • 回收池(Recycle pool)

       这个池用于不经常使用的块。回收池可以防止对象占用高速缓存中不必要的空间。

       数据库有标准的块大小(参考 "Database Block Size"),您可以使用非默认大小块创建表空间。每个非默认大小的块都有自己的池。Oracle 数据库使用与默认池中相同的方式来管理中这些不同块大小的缓冲池中的块。

       图14-7显示了使用多个池时的高速缓冲区的结构。高速缓冲区包含默认池、保留池和回收池。默认的块大小为8 KB。缓存包含使用非标准块大小(2 KB、4 KB和16 KB)的表空间单独的池。

Figure 14-7 Database Buffer Cache

参考:

       Oracle Database 2 Day DBA 和 Oracle Database Administrator's Guide,了解更多关于缓冲池的信息

       Oracle Database Performance Tuning Guide,了解如何使用多个缓冲池

     Redo日志缓冲区(Redo Log Buffer)

       重做日志缓冲区是 SGA 中的循环式缓冲区,用来存储对数据库所做更改的重做条目。重做条目包含重建(或重做)DML、DDL操作对数据库所做的更改所需的信息。数据库恢复时需要将重做信息应用于数据文件,用来重做丢失的更改。

       Oracle数据库进程将重做条目从用户内存空间复制到SGA的重做日志缓冲区中。重做条目占用缓冲区中连续、顺序的空间。 日志写进程(LGWR)将重做日志缓冲区的内容写入到磁盘上的活动联机重做日志组。图14-8说明了这种重做缓冲区工作流程。

Figure 14-8 Redo Log Buffer

       LGWR将redo信息按顺序写入磁盘,而DBWn将数据块分散写入磁盘。分散写入比顺序写入慢得多。LGWR可以让用户不需要等待DBWn完成缓慢的写操作,因此redo机制为数据库提供了更好的性能。

       初始化参数LOG_BUFFER指定了Oracle数据库在缓冲重做条目时可以使用的内存大小。与其他的 SGA 组件不同, 重做日志缓冲区和固定的SGA缓冲区不按颗粒度划分内存。

参考:

     共享池(Shared Pool)

       共享池缓存各种类型的程序数据。例如,共享池存储已解析的SQL、PL/SQL代码、系统参数和数据字典信息。共享池几乎涉及数据库中发生的每个操作。例如,如果用户执行SQL语句,那么Oracle数据库将访问共享池。

       共享池被划分为几个子组件,其中最重要的子组件如图14-9所示。

Figure 14-9 Shared Pool

       这部分包括以下几个主题:

     库缓存(Library Cache)

       库缓存是一个共享池内存结构,用于存储可执行SQL和PL/SQL代码。这个缓存包含共享的SQL和PL/SQL区域,以及诸如锁和库缓存句柄之类的控制结构。在共享服务器体系结构中,库缓存还包含私有SQL区域。

       当执行SQL语句时,数据库尝试重用以前执行过的代码。如果一个SQL语句的解析存在于库缓存中且可以共享,那么数据库将重用代码,这称为软解析(soft parse)或库缓存命中(library cache hit)。否则,数据库必须构建应用程序代码的新的可执行版本,称为硬解析(hard parse)或库缓存未命中(library cache miss)。

     共享SQL区(Shared SQL Areas)

       在数据库中执行的每条SQL代码,将会存放在以下区域之一:

       共享SQL区

       数据库使用共享SQL区域来处理第一次出现的SQL语句。所有用户都可以访问这个区域,并包含语句解析树和执行计划。对于唯一语句,只存在一个共享SQL区域。

       私有SQL区

       每个发出 SQL 语句的会话在其PGA中有一个私有SQL区(参考"Private SQL Area"),每个提交相同语句的用户都有一个指向同一共享SQL区域的私有SQL区域。因此,独立PGA中的许多私有SQL区域可以与相同的共享SQL区域关联。

       当应用程序提交类似的 SQL 语句时,数据库会自动决定怎么做。数据库会同时考虑从用户和应用程序直接发出的语句,及其它语句从内部发出的递归SQL 语句。

       数据库执行以下步骤:

       1.检查共享池,看是否存在某个语法和语义上都相同的语句的共享SQL 区:

       如果存在相同的语句,那么数据库将使用共享SQL区域执行语句,从而减少内存消耗。

       如果不存在相同的语句,那么数据库将在共享池中分配一个新的共享SQL区域。具有相同语法但不同语义的语句使用子游标。

       在这两种情况下,用户的私有SQL区域都指向包含语句和执行计划的共享SQL区域。

       2.为该会话分配一个私有 SQL 区

       私有SQL区域的位置取决于为建立连接会话的方式。如果会话通过共享服务器连接,那么部分的私有SQL区将保存在SGA中。

       图14-10说明了一个专用的服务器体系结构,其中两个会话在自己的PGA中保存同一SQL语句的副本。在共享服务器中,此副本位于UGA中,UGA位于大池中,或者在没有大池时位于共享池中。

Figure 14-10 Private SQL Areas and Shared SQL Area

 

参考:

       Oracle Database Performance Tuning Guide,了解更多有关管理库缓存的信息

       Oracle Database Advanced Application Developer's Guide,了解更多关于共享SQL的信息

       程序单元和库缓存

       库缓存包含PL/SQL程序和Java类的可执行形式。这些项目统称为程序单元。

       数据库处理程序单元与处理SQL语句类似。例如,数据库分配一个共享区域来保存经过解析、编译的PL/SQL程序。数据库分配一个私有区域来保存特定于运行程序的会话的值,包括本地、全局和包变量,以及用于执行SQL的缓冲区。如果多个用户运行相同的程序,则每个用户维护其私有SQL区域的单独副本,该副本包含特定于会话的值,并访问特定的共享SQL区域。

       数据库按以上描述进行处理PL/SQL程序单元内的单个SQL语句。尽管它们源于同一 PL/SQL 程序单元, 但这些 SQL 语句将使用一个共享区域来保存其已分析的表示形式,并为运行语句的每个会话使用一个私有区域。

       共享池内存的分配与重用

       当解析新的SQL语句时,数据库分配共享池内存。内存大小取决于语句的复杂度。

       通常,共享池中的项目会一直被保留着,直到LRU算法将其移除。就算创建该项目的进程已经终止,只要这些项目有用,数据库就允许共享池中用于多个会话的项目被保留在内存中。这种机制最小化了处理SQL的开销。

       在以下情况下,数据库还会从共享池中删除共享SQL区域:

       如果为表、表簇、索引收集了统计信息,在一段时间之后, 默认情况下数据库会逐步删除所有包含引用了已分析对象的语句的共享SQL区。下次运行某个已删除的语句时,数据库将在一个新的共享SQL区中对其进行解析并将新的统计信息反馈给模式对象。

       如果一个模式对象在某个SQL语句中被引用, 而之后此对象被某个DDL语句修改,则这个共享 SQL区无效。优化器必须在语句下一次运行时重新解析它。

       如果更改了全局数据库名称,则数据库将从共享池中删除所有信息。

       您可以使用ALTER SYSTEM FLUSH SHARED_POOL语句手动清空共享池中的所有信息,以评估实例重启后的性能。

参考:

       Oracle Database SQL Language Reference,了解关于ALTER SYSTEM FLUSH SHARED_POOL命令信息

       Oracle Database Reference,了解有关v$sql和v$sqlarea动态视图的信息

     数据字典缓存(Data Dictionary Cache)

       数据字典是数据库表和视图的集合,其中包含关于数据库及其结构信息及用户的参考信息。Oracle数据库在SQL语句解析过程中会频繁的访问数据字典。

       Oracle数据库经常访问数据字典,因此指定了以下特殊的内存位置来保存字典数据:

  • 数据字典缓存

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

  • 库缓存

       所有服务器进程共享这些缓存以访问数据字典信息。

参考:

       Chapter 6, "Data Dictionary and Dynamic Performance Views"

       Oracle Database Performance Tuning Guide,了解如何为数据字典缓存分配额外的内存

     服务器结果缓存(Server Result Cache)

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

       客户端结果缓存与服务器结果缓存不同。客户端缓存是在应用程序级别配置的,并且位于客户端内存中,而不是数据库内存中。

参考:

       Oracle Database Administrator's Guide,了解有关设置结果缓存大小的信息

       Oracle Database PL/SQL Packages and Types Reference,关于DBMS_RESULT_CACHE包的信息

       Oracle Database Performance Tuning Guide,了解客户端结果缓存的信息

     SQL查询结果缓存(SQL Query Result Cache)

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

       例如,假设应用程序重复运行相同的SELECT语句。如果结果被缓存,那么数据库将结果立即返回给它们。这样,数据库就避免了重新读取块和重新计算结果的昂贵操作。每当事务修改了数据或用于构造该缓存结果的数据库对象元数据时,数据库自动使其高速缓存结果无效。

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

参考:

       Oracle Database Reference,了解更多关于RESULT_CACHE_MODE参数的信息

       Oracle Database SQL Language Reference,了解结果缓存hint

       PL/SQL函数结果缓存(PL/SQL Function Result Cache)

       PL/SQL函数结果缓存存储了函数的结果集。如果不使用缓存,当每次调用一个函数1秒钟时,那么调用1000次将需要1000秒。使用缓存,1000个具有相同输入的函数调用总共需要1秒时间。对于经常调用依赖于静态数据的函数的情况,是个好的选择。

       PL/SQL函数代码可以包括一个缓存其结果的请求。调用此函数时,系统将检查缓存。如果高速缓存中包含之前使用相同参数值调用该函数的结果缓存,则系统将缓存结果返回给调用程序,而不会重新执行函数体。如果缓存中不包含其结果,则系统执行函数体,并在将控制返回给调用程序前,将其(针对这些参数值的)结果添加到缓存中。

Note:

       您可以指定用于计算缓存结果的数据库对象,如果其中任何对象被更新,则缓存结果变为无效且必须重新计算。

       缓存中可能会积累很多的结果缓存——当调用每个结果缓存函数时,每个不同的参数组合都形成一个结果缓存。如果数据库需要更多内存,则它会移除一个或多个缓存结果。

参考:

       Oracle Database Advanced Application Developer's Guide,了解更多有关PL/SQL函数结果缓存的信息

       Oracle Database PL/SQL Language Reference,了解更多有关PL/SQL函数结果缓存的信息

     保留池(Reserved Pool)

       保留池是共享池中的一个内存区域,Oracle数据库可以使用它来分配大的连续内存块。

       共享池中的内存分配以块的形式执行。分配块的过程中允许将大对象(超过5kb)加载到缓存中,而不需要单个连续区域。通过这种方式,数据库降低了由于碎片而耗尽连续内存的可能性。

       在个别情况种,Java、PL/SQL或SQL游标可能会从大于5 KB的共享池中进行分配。为了使这些分配能够最有效地进行,数据库会将少量共享池隔离为保留池。

参考:

       Oracle Database Performance Tuning Guide,了解如何配置保留池

     大池(Large Pool)

       大池是一个可选的内存区域,用于分配比共享池更大的内存。大池可以为以下用途提供大内存分配:

  • 共享服务器的UGA,和Oracle XA 接口(用于与多个数据库进行交互的事务)
  • 语句并行执行中使用的消息缓冲区
  • 恢复管理器(RMAN) I/O从属进程的缓冲区

       通过从大池中为共享SQL分配会话内存,数据库避免了由于收缩共享SQL缓存而导致的性能开销。通过为RMAN操作、I/O服务器进程和并行缓冲区分配大缓冲区中的内存,大池可以比共享池更好地满足大内存请求。

       图14-11是大池的描述。

Figure 14-11 Large Pool

       共享池中的保留空间与其它内存分配都使用同一LRU链表,而大池没有 LRU 列表。这些被分配的内片段直到操作完成后才会被释放。一旦释放了一个大块内存,其他进程就可以使用它。

参考:

       "Dispatcher Request and Response Queues",了解如何为共享服务器分配会话内存 

       Oracle Database Advanced Application Developer's Guide,了解关于Oracle XA

       Oracle Database Performance Tuning Guide,了解更多关于大池的信息

       "Parallel Execution",了解并行执行内存分配的信息

     Java池(Java Pool)

       Java 池是一个存储 Java 虚拟机(JVM)内所有会话特定的Java代码和数据的内存区。该内存包括在调用结束时迁移到Java会话空间的Java对象。

       对于专用服务器连接,Java 池包括每个Java 类的共享部分,包括方法和只读内存,如代码向量,但不包括每个会话的 Java 状态。对于共享服务器,Java 池包括每个Java类的共享部分、用于每个会话状态的一些UGA。每个UGA根据需要增大和缩小,但总的UGA大小必须适应Java池。

       Java池顾问统计器提供了关于用于Java的库缓存内存的信息,并预测Java池大小的变化如何影响解析速度。当将statistics_level设置为TYPICAL或更高时,Java池顾问器在内部打开。当关闭顾问时,这些统计数据将重置。

参考:

       Oracle Database Java Developer's Guide

       Oracle Database Performance Tuning Guide,了解关于包含Java池咨询统计信息的视图

     流池(Streams Pool)

       流池存储缓冲队列消息,并为Oracle流捕获进程和应用进程提供内存。流池只由Oracle流使用。

       如果没有配置过流池,它的大小将从零开始。流池大小将根据Oracle流的需要动态增长。

参考:

       Oracle Database 2 Day + Data Replication and Integration GuideOracle Streams Replication Administrator's Guide

     固定SGA区(Fixed SGA)

       固定SGA是一个内部管理区域。例如,固定SGA包含:

  • 关于数据库及其实例状态的一般信息, 后台进程需要访问这些信息
  • 进程之间通信的信息,例如关于锁的信息(参考 "Overview of Automatic Locks")

       固定的SGA大小由Oracle数据库设置,不能手动更改。固定的SGA大小可以随着版本的不同而变化。

    软件代码区概述

       软件代码区域是存储正在运行或可以运行的代码的内存部分。Oracle数据库代码存储在一个软件区域中,该区域通常比用户程序的位置更具排他性和受保护性。

       软件区域的大小通常是静态的,只有在软件更新或重新安装时才会改变。这些区域所需的大小因操作系统而异。

       软件区是只读的,并且可以按共享或非共享方式安装。数据库一些工具如Oracle Forms 和 SQL*Plus,可以共享安装,但有些却不能。可能的情况下,这些数据库代码会被共享,以便所有用户都可以访问它,而无需在内存中存在多个副本,从而减少主内存并提升整体性能。数据库的多个实例可以与同一台计算机上运行的不同的数据库使用相同的数据库代码区域。

Notes:

       安装共享软件的选项并不适用于所有操作系统,例如,在运行在PC上的Windows。有关更多信息,请参考特定操作系统的文档。

 

Tank

2019.8.5

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值