SGA

一、12c:官档

  • Books → Concepts → Part V Oracle Instance Architecture → 14 Memory Architecture → 14.4 Overview of the System Global Area (SGA)

二、系统全局区概述 (SGA)

SGA 是一个可读写的内存区,与 Oracle 后台进程一起组成数据库实例。 所有以用户名义执行的服务器进程,都可以读取 SGA 实例中的信息。在数据库操作过程中, 有几个进程会对 SGA 进行写入操作。

Note:

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

每个数据库实例都有其自己的 SGA。当实例启动时 Oracle 数据库自动为其SGA 分配内存,并在该实例关闭时回收内存。当您使用 SQL*Plus 或Oracle 企业管理器启动实例时, 会显示 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.

如图 1 所示, SGA 由几个内存组件组成,它们是用来满足特定类别的内存分配请求的内存池。除重做日志缓冲区外,所有 SGA 组件按称为颗粒的连续内存单元来分配和释放空间。颗粒大小是特定于平台的,由 SGA 的总大小决定。 


图 1:Oracle 数据库内存结构

您可以查询 V$ SGASTAT 视图,来查看有关 SGA 组件的信息。

最重要的 SGA 组件如下所示:
  • Database Buffer Cache
  • In-Memory Area
  • Redo Log Buffer
  • Shared Pool
  • Large Pool
  • Java Pool
  • Streams Pool
  • Fixed SGA
See Also:
  • 《Introduction to the Oracle Database Instance》
  • 《Oracle Database Performance Tuning Guide》了解如何确定颗粒的尺寸

1 Database Buffer Cache

数据库缓冲区高速缓存,也称为缓冲区高速缓存,是用于存储从数据文件读取的数据块副本的内存区域。

缓冲区是缓冲区管理器用来暂时缓存当前或最近使用的数据块的主内存地址。所有同时都连接到一个数据库实例的用户,以共享方式访问缓冲区高速缓存。

1.1 Database Buffer Cache 的作用

Oracle 数据库使用缓冲区高速缓存,来实现以下目标:

  • 优化物理 I/O
    数据库更新缓存中的数据块,并将有关更改的元数据存储在重做日志缓冲区。 COMMIT 之后,数据库将重做缓冲区写入磁盘,但不一定会立即将数据块写入磁盘。相反,数据库写入器 (DBWn) 在后台执行惰性写入操作。将频繁访问的块保持在缓冲区高速缓存中,而将不常存取的块写到磁盘
  • 当启用了数据库智能闪存高速缓存(flash cache)时,缓冲区高速缓存的一部分可能驻留在闪存缓存中。此缓冲区高速缓存扩展存储在闪存磁盘设备上,这是一种使用闪存的固态存储设备。通过将缓冲区缓存到闪存中,而不是从磁盘读取,数据库可以提高性能。
    使用 DB_FLASH_CACHE_FILE 和 DB_FLASH_CACHE_SIZE 初始化参数去配置多块闪存缓存。缓冲区缓存跟踪每个设备并将缓冲区均匀分配给设备。

Note:

数据库智能闪存高速缓存仅在 Solaris 和 Oracle 企业 Linux 中可用。

See Also:

  • 《Oracle Database Reference》学习关于 DB_FLASH_CACHE_FILE 初始化参数

1.2 缓冲区状态

数据库使用内部算法来管理高速缓存中的缓冲区。

缓冲区可以处于下列互斥状态之一:

  • Unused
    缓冲区可供使用,因为它从未使用过,或者当前未使用。这种类型的缓冲区是数据库最容易使用的。
  • Clean
    此缓冲区在之前曾被使用过,而现在包含某个数据块在某个时间点的读取一致版本。块包含数据但是干净的,因此它不需要将执行检查点操作。数据库可以订住该块并重用它。
  • Dirty
    缓冲区包含已修改、但尚未写入到磁盘的数据。数据库在重用该数据块之前必须对其执行检查点操作。

每个缓冲区具有两种访问模式之一: 订住的或空闲的 (未订住)。缓冲区被"订住"在缓存中,以便当其被某个用户会话访问时,它不会因为内存不足被换出内存。多个会话不能在同一时间修改某个已被订住的缓冲区。

1.3 缓冲区模式

当一个客户端请求数据时, Oracle 数据库以下列两种模式之一从数据库缓冲区高速缓存中检索缓冲区:

  • 当前模式
    当前模式获取,也称为数据库块获取,这是一种对当前已出现在缓冲区高速缓存中的块的检索。例如,如果一个未提交事务已更新某个块中的两行,则当前模式获取会检索这个具有未提交行的块。数据库最常使用数据库块获取的情况是在修改语句期间,它只需更新块的当前版本。
  • 一致模式
    一致读取获取是对某个块的一致读取版本的检索。此检索可能会使用撤消数据。例如,如果一个未提交事务已更新某个块中的两行,而在另一个独立会话中的查询请求该块,则数据库使用撤消数据来创建该块的一个读取一致版本(称为一致读取克隆),它不包括未提交的更新。通常,查询以一致模式检索块。

See Also:

  • 《Read Consistency and Undo Segments》
  • 《Oracle Database Reference》 关于数据库统计信息的描述,例如, 数据库块获取和一致读取获取

1.4 缓冲区 I/O

逻辑 I/O, 也称为缓冲区 I/O,指的是读取和写入缓冲区高速缓存中的缓冲区。

当在内存中找不到请求的缓冲区时,数据库将执行一个物理 I/O,将缓冲区从闪存缓存或磁盘复制到内存,然后再执行一个逻辑 I/O,以读取缓存的缓冲区。

1.4.1 缓存置换算法

为了使缓冲区访问效率高,数据库必须决定在内存中缓存哪些缓冲区,以及从磁盘访问哪些缓冲区。

数据库使用以下算法:
  • 基于LRU、块级的置换算法
    这是个复杂的,默认的算法,使用最近最少使用(LRU)列表包含脏和不脏缓冲区的指针。LRU列表具有热端和冷端。冷缓冲区是最近没有使用过的缓冲区。热缓冲区经常被访问并且最近被使用。从概念上讲,只有一个LRU,但是对于数据并发,数据库实际上使用了几条LRUs。
  • 基于热度、对象级的置换算法
    从Oracle Database 12c Release 1(12.1.0.2)开始,自动大表缓存特性允许表扫描在以下场景中使用不同的算法:
    • 并行查询
      在单实例和Oracle Real application Cluster (Oracle RAC)数据库中,当db_big_table_cache__target初始化参数设置为非零值,并将PARALLEL_DEGREE_POLICY设置为auto或adaptive时,并行查询可以使用大表缓存。
    • 串行查询
      在单实例配置中,当db_big_table_cache__target初始化参数设置为非零值时,串行查询可以使用大表缓存。

当一个表不适合内存时,数据库根据访问模式决定缓存哪些缓冲区。例如,如果只有95%的受欢迎的表适合内存,那么数据库可能会选择将5%的块放在磁盘上,而不是循环读取块到内存中,并写入块来进行磁盘清理——这一现象被称为thrashing。当缓存多个大型对象时,数据库会考虑更受欢迎的表,这些表更热,更不受欢迎的表更冷,这会影响缓存哪些块。DB_BIG_TABLE_CACHE_PERCENT_TARGET初始化参数设置使用该算法的缓冲区缓存的百分比。

Note:

本文档说明了基于LRU、块级的置换算法。

See Also:

  • 《Oracle Database VLDB and Partitioning Guide》学习更多关于基于热度的置换算法
1.4.2 缓冲区写

数据库写入器 (DBWn) 进程定期将冷的、 脏的缓冲区写入磁盘。 

DBWn 在以下情况下会将缓冲区写出:

  • 服务器进程找不到干净的缓冲区, 以将新块读入数据库缓冲区高速缓存。
    随着缓冲区变脏, 可用缓冲区的数量就会减少。如果该数值低于一个内部阈值, 而又需要干净的缓冲区,则服务器进程将通知 DBWn 执行写出操作。
    数据库使用 LRU 来确定哪些脏缓冲区被写出。当脏缓冲区到达 LRU的冷端时,数据库将其从 LRU 上移出到写出队列。 DBWn 将队列中的缓冲区写到磁盘,如果可能使用多块写,则用之。此机制可以防止LRU 尾端被脏缓冲区塞满,并保证有干净的缓冲区可供重用。
  • 数据库必须推进检查点,即重做线程中进行实例恢复的起点。
  • 表空间被更改为只读状态,或脱机。

See Also:
  • 《Database Writer Process (DBW)》
  • 《Oracle Database Performance Tuning Guide》了解如何诊断和调整缓冲区写出的问题
1.4.3 缓冲区读取

当干净的或未使用的缓冲区的数量变得很少时,数据库就必须将某些缓冲区从缓冲区高速缓存删除。 

其算法取决于是否启用了闪存缓存:

  • 禁用了闪存高速缓存
    数据库中根据需要覆盖并重新利用每个干净的缓冲区。如果以后需要重用被覆盖的缓冲区,则数据库必须从磁盘重新读取。
  • 启用了闪存高速缓存
    DBWn 将干净缓冲区的正文写入到闪存缓存,使其in-memory的缓冲区可以被重用。数据库在主内存中保留 LRU 列表的缓冲区头,以跟踪在闪存缓存中的缓冲区体的状态和位置。如果以后需要该缓冲区,则数据库可以从闪存缓存中读取它,而不用从磁盘读取。

当客户端进程请求一个缓冲区时,服务器进程在缓冲区高速缓存中搜索缓冲区。如果数据库在内存中找到缓冲区,则发生缓存命中。搜索顺序如下所示:

  1. 服务器进程在缓冲区高速缓存中搜索整个缓冲区。
    如果该进程发现整个缓冲区,则数据库对此缓冲区执行一个逻辑读取。
  2. 服务器进程在闪存缓存 LRU 列表中搜索缓冲区头。
    如果该进程找到了缓冲区头,则数据库执行一个优化的物理读取,将缓冲区正文从闪存缓存读入到in-memory缓存。
  3. 如果该进程没有在内存中找到该缓冲区(缓存未命中),则服务器进程将执行以下步骤:
    • 将该块从数据文件复制到内存中 (物理读取)
    • 对已读入到内存中的缓冲区执行一个逻辑读取

图 2 说明了缓冲区的搜索顺序。扩展的缓冲区高速缓存包括包含整个缓冲区的in-memory缓冲区缓存,和包含缓冲区正文的闪存缓存。在图中, 数据库在缓冲区高速缓存中搜索某个缓冲区,但未能找到,因此将其从磁盘中读入到内存。


图 2:缓冲区搜索

一般情况下,通过缓存命中访问数据比通过缓存未命中要快。缓冲区高速缓存命中率用于测量数据库在缓冲区高速缓存中找到请求的块,而不需要从磁盘中读取的比率。

数据库可能从数据文件或临时文件执行物理读取。在数据文件读取之后,会紧跟着有逻辑 I/O。临时文件读取发生在当内存不足时,迫使数据库将数据写入一个临时表,稍后又将其读回。这种物理读取会绕过缓冲区高速缓存,并不会导致逻辑的 I/O。

See Also:

  • 《Oracle Database Performance Tuning Guide》 了解如何计算缓冲区高速缓存命中率。
1.4.4 缓冲区触发计数

数据库使用触发计数来测量对 LRU 列表上的缓冲区进行访问的频率。这种机制使得当某个缓冲区被订住时数据库可以增加一次计数,而不用不断地移动 LRU 列表上的缓冲区。

Note:

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

当缓冲区被订住时,数据库将确定其触发计数的最后一次递增是何时发生的。如果计数递增发生在超过三秒钟前,则计数将增加 1 ;否则,计数保持不变。三秒钟规则防止对该缓冲区的一系列突发订住会产生过多计数。 例如,一个会话可能会在一个数据块中插入几行, 但数据库将这些插入作为一个触发看待。

如果某个缓冲区是在 LRU 的冷端上,但其触摸计数很高,则该缓冲区将移动到热端。 如果触发计数很低,则缓冲区将从缓存中老化移出。

1.5 缓冲区池

缓冲池是缓冲区的集合。
数据库缓冲区高速缓存被划分为一个或多个的缓冲池,以同样的方式管理块。对于老化或缓存块,池没有完全不同的算法。您可以手动配置多个单独的缓冲池,要么将数据保留在缓冲区高速缓存中,或在使用了数据块之后、使缓冲区立即可用于新的数据。然后,你可以将模式对象分配给适当的缓冲池,以控制数据块如何从缓存中老化移出。例如,您可以将段划分为热的、热的和冷的缓冲池。可能的缓冲池如下所示:
  • 默认池
    该池是块通常被缓存的地方。除非您手动配置单独的池,默认池将是唯一的缓冲池。其他池的可选配置对默认池没有影响。
    从Oracle 12c版本开始,大表缓存是默认池的可选部分,它使用基于热度的、对象级别的置换算法。在单实例和Oracle RAC数据库中,当db_big_table_cache__target初始化参数设置为非零值,PARALLEL_DEGREE_POLICY设置为auto 或 adaptive时,并行查询可以使用大表缓存。在单实例配置中,在设置DB_BIG_TABLE_CACHE_PERCENT_TARGET时,串行查询可以使用大表缓存。
  • 保留池
    该池用于被频繁访问的块, 使其不会由于缺省池的空间不足而被移出。保留缓冲池的目标是将对象保留在内存中,从而避免 I/O 操作。
    Note:
    保持池以与其他池相同的方式管理缓冲区:它不使用特殊的算法来插入缓冲区。“保持”这个词是一种命名惯例。您可以放置您想要保存在较大的keep池中的表,并放置您不想保存在较小的循环池中的表。
  • 循环池
    该池用于不被频繁使用的块。循环池防止对象在缓存中占用不必要的空间。

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

图 3 显示了使用多种缓冲池时的缓冲区高速缓存结构。包含默认池、保留池、和循环池。缺省块大小为 8 KB。缓存为各种使用 2 KB、4 KB 和16 KB 的非标准块大小的表空间包含单独的缓冲池。


图 3:数据库缓冲区高速缓存
See Also:
  • 《Database Block Size》
  • 《Oracle Database Administrator’s Guide》 了解更多关于缓存池
  • 《Oracle Database Performance Tuning Guide》 了解如何使用多个缓冲池
  • 《Oracle Database Reference》 了解  DB_BIG_TABLE_CACHE_PERCENT_TARGET 初始化参数

1.6 缓冲区和全表扫描

数据库使用一种复杂的算法来管理表扫描。默认情况下,当缓冲区必须从磁盘读入时, 数据库会将缓冲区插入到 LRU 列表的中部。通过这种方式,热块可以保留在缓存中,以使他们不需要再次从磁盘读取。

全表扫描顺序读取表高水位(HWM)下的所有行,这可能引发一个问题。假设表段中块的总大小大于缓冲区高速缓存的大小。在此表上的全表扫描可能会清除高速缓存, 致使数据库不能将频繁访问的块维持在高速缓存中。

See Also:

  • 《Segment Space and the High Water Mark》
1.6.1 全表扫描的默认模式

默认情况下,数据库采用保守的方法进行全表扫描,只有当表大小是缓冲区缓存的一小部分时,才将小表加载到内存中。

为了确定中等大小的表是否应该被缓存,数据库使用了一个算法,它包含了上一次表扫描的间隔、缓存的老化时间戳和缓冲区缓存中剩余的空间。对于非常大的表,数据库通常使用直接读取的路径,该路径将直接加载到PGA中并绕过SGA,以避免填充缓冲区缓存。对于中等大小的表,数据库可以使用直接读或缓存读取。如果它决定使用缓存读取,那么数据库将在LRU列表的末尾放置块,以防止扫描有效清除缓冲区缓存。

从Oracle Database 12c Release 1(12.1.0.2)开始,数据库实例的 buffer cache 将自动执行内部计算,以确定内存是否足以在实例SGA中充分缓存数据库,如果访问缓存表对性能有好处。如果整个数据库能够完全符合内存,并且满足各种其他内部条件,那么Oracle数据库将数据库中的所有表视为小表,并认为它们有资格进行缓存。但是,数据库并不缓存标有NOCACHE属性的lob。

1.6.2 并发查询执行

在执行全表扫描时,数据库有时可以通过使用多个并行执行服务器来提高响应时间。

在某些情况下,当数据库有大量的内存时,数据库可以在系统全局区域(SGA)中缓存并行查询数据,而不是使用直接路径读入程序全局区域(PGA)。通常,由于潜在的资源使用情况,并发查询会出现在低并发数据仓库中。
See Also:
  • 《Oracle Database Data Warehousing Guide》 了解数据仓库
  • 《Oracle Database VLDB and Partitioning Guide》学习并发执行
1.6.3 CACHE 属性

在不需要默认缓存行为的情况下,您可以使用ALTER TABLE…CACHE 以更改从大型表中读取的块如何读取到数据库缓冲区缓存中。

对于具有CACHE 属性集的表,数据库不强制或将块放入缓冲区缓存中。相反,数据库以与其他表块相同的方式将块从缓存中删除。在执行这个选项时要小心,因为一个大表的完整扫描可能会清除缓存中的大部分其他块。

Note:

执行 ALTER TABLE ... CACHE 不会导致表被缓存。
1.6.4 KEEP 属性

对于大表,你可以使用 ALTER TABLE ... STORAGE BUFFER_POOL KEEP 对这些表进行扫描,以将这些表加载到 keep pool 中。

将一个表放在keep pool中,可以更改存储块的缓冲区缓存的部分。数据库在keep buffer pool中缓存它们,而不是在默认 buffer pool 中缓存块。没有单独的算法控制保持池缓存。

See Also:

  • 《Oracle Database SQL Language Reference》 了解 CACHE 语句和 KEEP 属性
  • 《Oracle Database Performance Tuning Guide》 学习如何解释缓冲区缓存咨询统计数据。
1.6.5 强制全库缓存模式

为了在某些情况下提高性能,您可以显式地执行ALTER DATABASE ... FORCE FULL DATABASE CACHING语句,以启用强制完整的数据库缓存模式。

与默认模式(自动)形成对比的是,强制完整数据库缓存模式认为整个数据库(包括NOCACHE lob)可以在buffer cache中缓存。此模式从Oracle数据库12c发布1(12.1.0.2)开始。

Note:

启用完整的数据库缓存模式不会强迫数据库进入内存。相反,整个数据库都有资格被完全缓存到缓冲区缓存中。Oracle数据库只在访问表时缓存这些表。

Oracle建议,只有当每个实例的缓冲区缓存大小大于数据库大小时,才能启用完整的数据库缓存模式。这条准则适用于单实例和Oracle RAC数据库。但是,当Oracle RAC应用程序被很好地分区时,当所有实例的合并缓冲区缓存(在实例之间处理重复缓存块)时,可以启用完整的数据库缓存模式,这比数据库的大小要大。

See Also:

  • 《Oracle Database Administrator’s Guide》了解如何启用完整的数据库缓存模式。
  • 《Oracle Database SQL Language Reference》 了解使用 ALTER DATABASE ... FORCE FULL DATABASE CACHING语句

2 In-Memory AreaIn-Memory Area 

是一个可选的SGA组件,包含内存中的列存储(IM列存储)。

IM列存储包含表、分区和物化视图的副本,这些视图以柱状格式优化,以进行快速扫描。IM列存储补充数据库缓冲区缓存,它以传统的行格式存储数据。
Note:

要启用IM列存储,必须使用Oracle数据库内存选项。

See Also:

  • 《Oracle Database In-Memory Guide》要了解更多关于内存区域和 In-Memory 列存储的信息。 

3 Redo Log Buffer

重做日志缓冲区是 SGA 中的一个循环式缓冲区,用来存储对数据库所做更改的重做条目。

重做条目包含用于重建(或重做) 由 DML 或 DDL 操作对数据库所做更改所需的信息。数据库恢复将重做条目应用到数据文件,以重建丢失的更改。

Oracle 数据库进程将重做条目从用户内存空间复制到 SGA 的重做日志缓冲区中。重做条目占用缓冲区中连续、顺序的空间。 日志写入器(LGWR)后台进程将重做日志缓冲区写入磁盘上的活动联机重做日志组。图 4 显示了这种重做缓冲区活动。


图 4:重做日志缓冲区

LGWR 进程将重做信息顺序写入磁盘, 而 DBWn 进程将数据块分散写入磁盘。分散写入往往要比顺序写入慢得多。 LGWR 使用户能够避免等待 DBWn完成其缓慢的写入,为数据库提供了更好的性能。

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

See Also:

  • 《Log Writer Process (LGWR)》 和 《Importance of Checkpoints for Instance Recovery》
  • 《Oracle Database Administrator’s Guide》 有关联机重做日志的信息

4 Shared Pool

共享池缓存各种类型的程序数据。 

例如,共享池存储已解析的 SQL、PL/SQL 代码、系统参数、和数据字典信息。几乎数据库中发生的每个操作都涉及到共享池。例如,如果用户执行一个 SQL 语句,则 Oracle 数据库会访问共享池。共享池分为几个子组件,其中最重要的几个显示在图 5 中。


图 5: 共享池本

节包括以下主题:

  • Library Cache
  • Data Dictionary Cache
  • Server Result Cache
  • Reserved Pool

4.1 Library Cache

library cache 是存储可执行 SQL 和 PL/SQL 代码的共享池内存结构。

此缓存包含共享 SQL 和 PL/SQL 区,以及锁和库缓存句柄之类的控制结构。在共享服务器体系结构中, 库缓存还包含私有 SQL 区。

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

4.1.1 Shared SQL Areas

该数据库表示它在共享SQL区域和私有SQL区域中运行的每个SQL语句。

数据库使用 shared SQL area 来处理第一个SQL语句的出现。该区域可被所有用户访问,并包含语句解析树和执行计划。惟一的语句只存在于一个shared SQL area中。发出SQL语句的每个会话在其PGA中都有一个 private SQL area。提交相同语句的每个用户都有一个指向相同shared SQL area 的 private SQL area。因此,单独的pga中的许多 private SQL area 可以与相同的 shared SQL area 相关联。

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

数据库执行以下步骤:

  1. 检查共享池,看是否存在某个语法和语义上都相同的语句的共享SQL 区:
    • 如果存在这样一个相同的语句,则数据库为该语句的后续新实例使用这个共享 SQL 区,从而减少内存消耗。
    • 如果不存在这样一个相同的语句,则数据库在共享池中分配一个新的共享 SQL 区。 语法相同、 但语义不同的语句会使用一个子游标。
  2. 在这两种情况下, 用户的私有 SQL 区都指向包含语句和执行计划的共享 SQL 区。
  3. 为该会话分配一个私有 SQL 区
    私有 SQL 区的位置取决于该会话所建立的连接。如果会话是通过共享服务器连接的, 则该私有 SQL 区中的一部分被保存在 SGA 中。
图 6 显示了一个专用服务器架构, 其中两个会话在其 PGA 中保留了同一 SQL 语句的副本。 若在共享服务器中, 此副本会位于大池的 UGA 中,或当大池不存在时位于共享池中。


图 6:私有 SQL 区和共享 SQL 区
See Also:
  • 《Private SQL Area》
  • 《Oracle Database Performance Tuning Guide》了解库缓存管理
  • 《Oracle Database Development Guide》有关共享 SQL 的详细信息
4.1.2 程序单元和 Library Cache

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

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

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

4.1.3 Shared Pool 的内存分配和重用

当解析新的 SQL 语句(除了DDL语句)时,数据库将分配共享池内存。内存大小取决于语句的复杂性。

通常,共享池中的项目会一直保留,直到按 LRU 算法将其移除。数据库允许共享池中用于多个会话的项目被保留在内存中,只要他们还有用, 即使创建该项目的进程已经终止。 这一机制能最小化开销和对 SQL 语句的处理。

你可以使用 ALTER SYSTEM FLUSH SHARED_POOL 语句,手动删除共享池中的所有信息,以评估实例重新启动后预期的性能。

See Also:

  • 《Oracle Database SQL Tuning Guide》描述共享SQL区的生命周期
  • 《Oracle Database SQL Language Reference》 有关使用 ALTER SYSTEM FLUSH SHARED_POOL 的信息
  • 《Oracle Database Reference》有关 V$SQL 和 V$SQLAREA 动态视图的信息

4.2 Data Dictionary Cache

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

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

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

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

See Also:

  • 《Data Dictionary and Dynamic Performance Views》
  • 《Oracle Database Performance Tuning Guide》了解如何为数据字典缓存分配额外的内存

4.3 Server Result Cache

server result cache 是 shared pool 中的内存池。与缓冲池保存数据块不同,服务器结果缓存保存的是结果集。

服务器结果缓存包含 SQL 查询结果缓存和 PL/SQL 函数结果缓存,它们共享相同的基础结构。

Note:

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

See Also:

  • 《Oracle Database Administrator’s Guide》 有关设置结果缓存大小的信息
  • 《Oracle Database PL/SQL Packages and Types Reference》关于DBMS_RESULT_CACHE 包的信息
  • 《Oracle Database Performance Tuning Guide》有关客户端结果缓存的详细信息
4.3.1 SQL 查询 Result Cache

SQL query result cache 是存储查询和查询片段结果的 server result cache 的一个子集。

大多数应用程序都得益于这种性能改进。假设应用程序将重复执行相同的 SELECT 语句。如果结果会被缓存,则数据库会将其立即返回。通过这种方式, 数据库避免了重读块和重计算结果等昂贵操作。

当一个查询执行时,数据库搜索内存,以确定结果是否存在。如果结果被缓存,则数据库会从内存中返回结果以代替执行查询。如果结果没被缓存,则数据库会执行这个查询,染回输出结果,然后存储结果到result cache。每当事务修改了数据或用于构造该缓存结果的数据库对象元数据时,数据库自动使其高速缓存结果无效。

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

See Also:

  • 《Oracle Database Reference》了解 RESULT_CACHE_MODE 初始化参数
  • 《Oracle Database SQL Language Reference》了解hint RESULT_CACHE

4.3.2 PL/SQL 函数 Result Cache

PL/SQL 函数 Result Cache 是 result cache 存储函数的结果集的一个内存区。

若不使用缓存功能, 每次调用花 1 秒钟的函数,调用该函数 1000 次将花时间 1000 秒。而缓存后,以相同的输入调用函数 1000 次总共仅需要时间 1 秒。 对于在相对静态的数据上被频繁调用的函数,结果缓存是一个很好的选择。

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

Note:

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

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

See Also:

  • 《Oracle Database Development Guide》了解 PL/SQL 函数 Result Cache
  • 《Oracle Database PL/SQL Language Reference》 了解 PL/SQL 函数 result cache

4.4 Reserved Pool

Reserved Pool 是共享池中的一个内存区, Oracle 数据库使用它来分配大的连续内存块。

从共享池中分配内存是按大块执行的。大块使得大型对象(超过 5 KB)可以被加载到缓存中,而不需要一个单一的连续区域。这样一来,数据库中由于碎片引起的连续内存不足的可能性降低了。

有时,Java、PL/SQL、或 SQL 游标也可能会从共享池中分配大于 5 KB 的内存块。 为使这种分配更有效,数据库从共享池中为保留池隔离出少量内存。

See Also:

  • 《Oracle Database Performance Tuning Guide》了解如何配置保留池

5 Large Pool

大池是一个可选的内存区域,它所提供的内存分配往往比共享池分配的内存更大。

大池可以提供以下大内存分配:

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

通过从大池中分配会话内存,数据库可以避免由收缩共享 SQL缓存引起的性能开销。通过为 RMAN 操作、 I/O 服务器进程、 和并行缓冲区等分配大的缓冲区内存,大池可以比共享池更好地满足大型内存请求。数据库避免了数据库从共享池中分配内存时可能出现的内存碎片。当数据库将 large pool 分配给一个会话时,除非会话释放该内存,否则该内存不能被释放。相反,数据库以LRU的方式管理共享池中的内存,这意味着内存的部分可以过期。


图 7:大池

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

See Also:

  • 《Query Coordinator》有关为并行执行分配内存的信息
  • 《Dispatcher Request and Response Queues》了解为共享服务器分配会话内存
  • 《Oracle Database Development Guide》了解 Oracle XA
  • 《Oracle Database Performance Tuning Guide》有关大池的详细信息

6 Java Pool

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

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

Java 池顾问统计提供有关用于 Java 的 library cache 内存信息,并预测 Java 池大小的更改如何影响解析率。 当 statistics_level 设置为 TYPICAL或更高时,Java 池顾问在内部会被打开。这些统计信息在顾问被关闭时会被重置。

See Also:

  • 《Oracle Database Java Developer’s Guide》
  • 《Oracle Database Performance Tuning Guide》了解包含 Java 池顾问统计信息的有关视图

7 Streams Pool

Streams pool 用于存储缓冲的队列消息,并为 Oracle 流的捕获进程和应用进程提供内存。Streams pool 专门由 Oracle 流使用。

如果您没有专门配置Streams pool, 则其大小从零开始。Streams pool 的大小由 Oracle 流按需动态增长。

See Also:

  • 《Oracle Streams Replication Administrator's Guide》和《Oracle Streams Replication Administrator's Guide》

8 Fixed SGA

Fixed SGA 是内部的内务管理区域。

例如, 固定 SGA 包含:
  • 有关数据库及其实例状态的一般信息, 后台进程需要访问这些信息
  • 进程间通讯的信息,如有关锁的信息

固定 SGA 的大小由 Oracle 数据库设置,且不能手动更改。固定 SGA 大小可能会因为版本不同而不同。

See Also:

  • 《Overview of Automatic Locks》
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值