Oracle 数据库内存结构简介
当实例启动时, Oracle 数据库分配内存区,并启动后台进程。
-
程序代码
-
有关每个已连接会话的信息,无论其当前是否处于活动状态
-
在程序执行期间所需的信息,例如,正在索取数据的查询的当前状态
-
在多个进程之间被共享和传递的信息,如锁信息
-
缓存数据,如数据块和重做记录等,它们也存在于磁盘上
另见:
基本内存结构
Oracle数据库包含多个内存区域,每个内存区域包含多个子组件。
与 Oracle 数据库相关联的基本内存结构包括:
-
系统全局区 (SGA)
SGA 是一组称为 SGA 组件的共享内存结构, 其中包含一个 Oracle数据库实例的数据和控制信息。 SGA 由所有服务器进程和后台进程共享。 例如, SGA 中存储的数据包括数据块缓存和共享 SQL 区。 -
程序全局区 (PGA)
PGA 是一个非共享的内存区域,其中包含专门供某个 Oracle 进程使用的数据和控制信息。 Oracle 进程启动时, Oracle 数据库会为其创建 PGA。每个服务器进程和后台进程都存在一个 PGA。 所有单个 PGA 的集合即是总实例 PGA,或实例 PGA。数据库初始化参数设置实例 PGA 的大小, 而不是单个 PGA 的大小。 -
用户全局区 (UGA)
UGA 是与某个用户会话相关联的内存区。
-
软件代码区
软件代码区是用来存储正在运行或可能要运行的代码的那部分内存。Oracle 数据库代码通常存储在与用户程序不同的位置, ——一个更专门或更受保护的位置。
下图说明了这些内存结构之间的关系。
Oracle 数据库内存管理
内存管理的基本选项如下所示:
-
自动内存管理
您指定实例内存的目标大小。数据库实例自动优化到这个目标内存大小,根据需要在 SGA 和 PGA 实例之间重新分配内存。 -
自动共享内存管理
这种管理模式是部分自动化的。您设置一个 SGA 的目标大小,然后设置 PGA 总目标大小, 或单独管理 PGA 的各个工作区。 -
手工内存管理
你不必设置总的内存大小,但您需要设置许多初始化参数,以单独管理 SGA 和 PGA 实例中的各个组件。.
另见:
-
"Memory Management"有关供数据库管理员使用的内存管理选项的详细信息
-
《Oracle Database Administrator’s Guide》有关内存管理的选项
用户全局区概述
下图描述了 UGA。
另见:
-
《Oracle Database Net Services Administrator's Guide》了解共享服务器连接
-
《Oracle OLAP User’s Guide》关于 Oracle OLAP 的概述
程序全局区概述 (PGA)
下图显示某个未配置为共享服务器的实例的 PGA(所有 PGA 的集合) 。您可以使用一个初始化参数设置实例 PGA 的目标最大大小。根据需要,各个 PGA 可以按需增大到这个目标大小。
PGA 的内容
PGA 被进一步细分为多个不同区域,每一个都有不同的目的。
下图显示一个专用服务器会话的 PGA 中可能包含的内容。不是所有的 PGA 区域在任何情况下都存在。
私有 SQL 区
私有 SQL 区又分为以下几个区域:
-
run-time 区
此区域包含查询执行状态信息。 例如, 运行时区域会跟踪到目前为止在全表扫描中检索到的行数。
Oracle 数据库将创建运行时区域,作为一个执行请求的第一步。对于 DML 语句,其运行时区域将在 SQL 语句关闭时被释放。 -
持久区
此区域包含绑定变量的值。绑定变量是执行 SQL 语句时,在运行时提供给 SQL 语句的值。仅当关闭该游标时, 持久区域才被释放。
SQL 工作区
工作区是在 PGA 中为内存密集型操作分配的私有内存区。
如下示例显示了 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 Database Administrator’s Guide》了解如何使用自动 PGA 管理
-
《Oracle Database Performance Tuning Guide》了解如何调整 PGA 内存
在专用和共享服务器模式中使用 PGA
PGA 内存分配取决于数据库是使用专用的还是共享的服务器连接。
下表显示了差异之处。
表 14-1 专用和共享服务器之间的内存分配差异
内存区 | 专用服务器 | 共享服务器 |
---|---|---|
会话内存的性质 | 私有的 | 共享的 |
持久区域的位置 | PGA | SGA |
DML/DDL 语句的运行时区域的位置 | PGA | PGA |
另见:
《Oracle Database Administrator’s Guide》了解如何将数据库配置为共享服务器
系统全局区概述 (SGA)
SGA 是一个可读写的内存区, 与 Oracle 后台进程一起组成数据库实例。
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.
您可以查询 V$ SGASTAT 视图, 来查看有关 SGA 组件的信息。
最重要的 SGA 组件如下所示:
另见:
数据库缓冲区高速缓存
数据库缓冲区高速缓存的目标
Oracle数据库使用缓冲区缓存来实现多个目标。
这些目标包括:
-
优化物理 I/O
数据库更新缓存中的数据块,并将有关更改的元数据存储在重做日志缓冲区。 提交之后,数据库将重做缓冲区写入磁盘,但不一定会立即将数据块写入磁盘。相反,数据库写入器 (DBWn) 在后台执行惰性写入操作。 - 将频繁访问的块保持在缓冲区高速缓存中,而将不常存取的块写到磁盘当启用了数据库智能闪存高速缓存 (flash 高速缓存) 时, 缓冲区高速缓存的一部分可能驻留在闪存缓存中。此缓冲区高速缓存扩展存储在闪存磁盘设备上,这是一种使用闪存的固态存储设备。通过将缓冲区缓存到闪存中, 而不是从磁盘读取,数据库可以提高性能。
使用 DB_FLASH_CACHE_FILE 和 DB_FLASH_CACHE_SIZE 初始化参数配置多个flash设备。缓冲区缓存跟踪每个设备并将缓冲区均匀地分配到设备。
另见:
《Oracle Database Reference》了解DB_FLASH_CACHE_FILE初始化参数
缓冲区状态
数据库使用内部算法来管理高速缓存中的缓冲区。
-
未使用的
缓冲区可供使用,因为它从未使用过,或者当前未使用。这种类型的缓冲区是数据库最容易使用的。 -
干净的
此缓冲区在之前曾被使用过,而现在包含某个数据块在某个时间点的读取一致版本。块包含数据但是干净的,因此它不需要将执行检查点操作。数据库可以订住该块并重用它。 -
脏的
缓冲区包含已修改、 但尚未写入到磁盘的数据。数据库在重用该数据块之前必须对其执行检查点操作。
缓冲区模式
当客户端请求数据时,Oracle数据库以当前模式或一致模式从数据库缓冲区缓存中检索缓冲区。
模式的区别如下:
-
当前模式
当前模式获取, 也称为数据库块获取, 这是一种对当前已出现在缓冲区高速缓存中的块的检索。 例如, 如果一个未提交事务已更新某个块中的两行, 则当前模式获取会检索这个具有未提交行的块。数据库最常使用数据库块获取的情况是在修改语句期间,它只需更新块的当前版本。 -
一致模式
一致读取获取是对某个块的一致读取版本的检索。此检索可能会使用撤消数据。 例如, 如果一个未提交事务已更新某个块中的两行, 而在另一个独立会话中的查询请求该块,则数据库使用撤消数据来创建该块的一个读取一致版本(称为一致读取克隆) ,它不包括未提交的更新。通常,查询以一致模式检索块。
另见:
-
《Oracle Database Reference》关于数据库统计信息的描述,例如, 数据库块获取和一致读取获取
缓冲区 I/O
缓冲区替换算法
为了使缓冲区访问更有效,数据库必须决定在内存中缓存哪些缓冲区,以及从磁盘访问哪些缓冲区。
数据库使用以下算法:
-
基于 lru 的块级替换算法
这个复杂的算法是默认的,它使用一个包含指向脏缓冲区和非脏缓冲区指针的least recently used (LRU)列表。LRU列表有热端和冷端。冷缓冲区是最近没有使用过的缓冲区。热缓冲区经常被访问,并且最近才被使用。从概念上讲,只有一个LRU,但是对于数据并发性,数据库实际上使用多个LRU。
-
基于热度的对象级替换算法
从Oracle Database 12c Release 1(12.1.0.2)开始,自动大表缓存特性使表扫描能够在以下场景中使用不同的算法:
-
并发查询
在单实例和Oracle Real Applications Cluster (Oracle RAC)数据库中,当将DB_BIG_TABLE_CACHE_PERCENT_TARGET初始化参数设置为非零值,并将PARALLEL_DEGREE_POLICY设置为auto或adaptive时,并行查询可以使用大表缓存。
-
串行查询
在单实例配置中,当DB_BIG_TABLE_CACHE_PERCENT_TARGET初始化参数设置为非零值时,串行查询可以使用大表缓存。
当表不适合放入内存时,数据库根据访问模式决定缓存哪些缓冲区。例如,如果一个受欢迎的表中只有95%适合内存,那么数据库可能会选择将5%的块留在磁盘上,而不是循环地将块读入内存并将块写入磁盘——这种现象称为抖动。当缓存多个大型对象时,数据库会考虑更受欢迎的表更热,而不太受欢迎的表更冷,这将影响缓存哪些块。使用初始化参数 DB_BIG_TABLE_CACHE_PERCENT_TARGET 设置此算法的缓冲区缓存的百分比。
-
另见:
《Oracle Database VLDB and Partitioning Guide》了解更多关于基于热度的算法
缓冲区写出
数据库写入器 (DBWn) 进程定期将冷的、 脏的缓冲区写入磁盘。
- 服务器进程找不到干净的缓冲区, 以将新块读入数据库缓冲区高速缓存。随着缓冲区变脏, 可用缓冲区的数量就会减少。如果该数值低于一个内部阈值, 而又需要干净的缓冲区,则服务器进程将通知 DBWn 执行写出操作。数据库使用 LRU 来确定哪些脏缓冲区被写出。当脏缓冲区到达 LRU 的冷端时,数据库将其从 LRU 上移出到写出队列。 DBWn 将队列中的缓冲区写到磁盘,如果可能使用多块写,则用之。此机制可以防止 LRU 尾端被脏缓冲区塞满,并保证有干净的缓冲区可供重用。
-
数据库必须推进检查点,即重做线程中进行实例恢复的起点。
-
表空间被更改为只读状态,或脱机。
另见:
-
《Oracle Database Performance Tuning Guide》了解如何诊断和调整缓冲区写出的问题
缓冲区读取
其算法取决于是否启用了闪存缓存:
-
禁用了闪存高速缓存
数据库中根据需要覆盖并重新利用每个干净的缓冲区。如果以后需要重用被覆盖的缓冲区, 则数据库必须从磁盘重新读取。 -
启用了闪存高速缓存
DBWn 将干净缓冲区的正文写入到闪存缓存,使其内存中的缓冲区可以被重用。数据库在主内存中保留 LRU 列表的缓冲区头,以跟踪在闪存缓存中的缓冲区体的状态和位置。如果以后需要该缓冲区, 则数据库可以从闪存缓存中读取它, 而不用从磁盘读取。
-
服务器进程在缓冲区高速缓存中搜索整个缓冲区。
如果该进程发现整个缓冲区, 则数据库对此缓冲区执行一个逻辑读取。
-
服务器进程在闪存缓存 LRU 列表中搜索缓冲区头。
如果该进程找到了缓冲区头,则数据库执行一个优化的物理读取,将缓冲区正文从闪存缓存读入到内存内缓存。 - 如果该进程没有在内存中找到该缓冲区(缓存未命中),则服务器进程将执行以下步骤:
-
将该块从数据文件复制到内存中 (物理读取)
-
对已读入到内存中的缓冲区执行一个逻辑读取
-
另见:
《Oracle Database Performance Tuning Guide》了解如何计算缓冲区高速缓存命中率
缓冲区触摸计数
缓冲区池
缓冲池是缓冲区的集合。
您可以手动配置多个单独的缓冲池,要么将数据保留在缓冲区高速缓存中,或在使用了数据块之后、 使缓冲区立即可用于新的数据。然后,你可以将模式对象分配给适当的缓冲池,以控制数据块如何从缓存中老化移出。例如,可以将段分隔为热缓冲池、暖缓冲池和冷缓冲池。
可能的缓冲池如下所示:
-
缺省池
该池是块通常被缓存的地方。除非您手动配置单独的池,默认池将是唯一的缓冲池。
从Oracle Database 12c Release 1(12.1.0.2)开始,大表缓存是默认池中的一个可选部分,它使用基于热度的对象级替换算法。在单实例和 Oracle RAC 数据库中,当DB_BIG_TABLE_CACHE_PERCENT_TARGET 初始化参数设置为非零值,PARALLEL_DEGREE_POLICY 设置为auto或adaptive时,并行查询可以使用大表缓存。仅在单实例配置中,当设置 DB_BIG_TABLE_CACHE_PERCENT_TARGET 时,串行查询可以使用大表缓存。
-
保留池
该池用于被频繁访问的块, 使其不会由于缺省池的空间不足而被移出。保留缓冲池的目标是将对象保留在内存中, 从而避免 I/O 操作。 -
循环池
该池用于不被频繁使用的块。循环池防止对象在缓存中占用不必要的空间。
数据库有一个标准的块大小。您可以创建一个块大小不同于标准大小的表空间。每个非默认的块大小都有自己的缓冲池。Oracle 数据库使用与默认池中相同的方式, 来管理中这些不同块大小的缓冲池中的块。
下图显示了使用多种缓冲池时的缓冲区高速缓存结构。包含缺省池、保留池和循环池。缺省块大小为 8 KB。缓存为各种使用 2 KB、4 KB 和 16 KB 的非标准块大小的表空间包含单独的缓冲池。
另见:
-
《Oracle Database Administrator’s Guide》了解有关缓冲池的更多信息
-
《Oracle Database Performance Tuning Guide》学习如何使用多个缓冲池
-
《Oracle Database Reference》要了解DB_BIG_TABLE_CACHE_PERCENT_TARGET初始化参数
缓冲区和全表扫描
数据库使用复杂的算法来管理表扫描。默认情况下,当缓冲区必须从磁盘读入时, 数据库会将缓冲区插入到 LRU 列表的中部。 通过这种方式, 热块可以保留在缓存中,以使他们不需要再次从磁盘读取。
全表扫描的默认模式
默认情况下,数据库对全表扫描采用一种保守的方法,仅当表大小占缓冲区缓存的一小部分时才将小表加载到内存中。
为了确定是否应该缓存中等大小的表,数据库使用了一种算法,该算法包含最后一次表扫描之间的时间间隔、缓冲区缓存的老化时间戳和缓冲区缓存中剩余的空间。
对于非常大的表,数据库通常使用直接读取路径,该路径直接将块加载到PGA并完全绕过SGA,以避免填充缓冲区缓存。对于中等大小的表,数据库可以使用直接读取或缓存读取。如果决定使用缓存读取,则数据库将这些块放在LRU列表的末尾,以防止扫描有效地清除缓存。
从Oracle Database 12c Release 1(12.1.0.2)开始,数据库实例的缓冲区缓存自动执行内部计算,以确定内存是否足够将数据库完全缓存到实例SGA中,以及访问时缓存表是否有利于性能。如果整个数据库可以完全装入内存,并且满足其他各种内部条件,那么Oracle数据库将数据库中的所有表都视为小表,并认为它们有资格进行缓存。但是,数据库不缓存标记为NOCACHE属性的lob。
并发查询执行
在执行全表扫描时,数据库有时可以通过使用多个并行执行服务器来提高响应时间。
在某些情况下,当数据库有大量内存时,数据库可以在系统全局区域(SGA)中缓存并行查询数据,而不是使用直接路径读取程序全局区域(PGA)。通常,由于潜在的资源使用,并行查询发生在低并发性数据仓库中。
另见:
-
《Oracle Database Data Warehousing Guide》有关数据仓库的介绍
-
《Oracle Database VLDB and Partitioning Guide》了解有关并行执行的更多信息
缓存属性
在不需要默认缓存行为的罕见情况下,可以使用 ALTER TABLE ... CACHE 更改将大表中的块读入数据库缓冲区缓存的方式。
对于具有缓存属性集的表,数据库不会强制或固定缓冲区缓存中的块。相反,数据库以与任何其他表块相同的方式将块从缓存中取出。在执行此选项时要小心,因为对大表的完整扫描可能会清除缓存中的大多数其他块。
KEEP 属性
对于大型表,可以使用 ALTER TABLE…STORAGE BUFFER_POOL KEEP 使扫描将这些表的块加载到KEEP池中。
将表放入keep池将更改存储块的缓冲区缓存的部分。数据库不是将块缓存到默认缓冲池中,而是将它们缓存到keep缓冲池中。没有单独的算法控制 KEEP 池缓存。
另见:
-
《Oracle Database SQL Language Reference》有关缓存子句和KEEP属性的信息
-
《Oracle Database Performance Tuning Guide》了解如何解释缓冲区缓存咨询统计信息
强制使用全数据库缓存模式
为了提高某些情况下的性能,可以显式地执行 ALTER DATABASE ... FORCE FULL DATABASE CACHING 语句,以启用强制全数据库缓存模式。
与默认模式(自动模式)相反,强制全数据库缓存模式认为整个数据库(包括NOCACHE lob)都适合在数据库缓冲区缓存中进行缓存。从Oracle数据库12c Release 1(12.1.0.2)开始,可以使用这种模式。
Oracle建议,只有当每个实例的缓冲区缓存大小大于数据库大小时,才启用强制全数据库缓存模式。该准则适用于单实例和Oracle RAC数据库。但是,当Oracle RAC应用程序被很好地分区时,当所有实例的组合缓存大于数据库大小时,您可以启用强制的全数据库缓存模式,并且有额外的空间来处理实例之间的重复缓存块。
另见:
-
《Oracle Database Administrator’s Guide》了解如何启用强制全数据库缓存模式
-
《Oracle Database SQL Language Reference》了解 ALTER DATABASE ... FORCE FULL DATABASE CACHING 语句
重做日志缓冲区
重做记录是一种数据结构,它包含用于重建(或重做) 由 DML 或 DDL 操作对数据库所做更改所需的信息。数据库恢复将重做条目应用到数据文件,以重建丢失的更改。
共享池
共享池缓存各种类型的程序数据。
共享池分为几个子组件,其中最重要的几个显示在图 14-9 中。
库缓存
库缓存是存储可执行 SQL 和 PL/SQL 代码的共享池内存结构。
共享 SQL 区
数据库所运行的每个 SQL 语句,会存在于共享SQL区和私有 SQL 区。
数据库执行以下步骤:
- 检查共享池,看是否存在某个语法和语义上都相同的语句的共享SQL 区:
- 如果存在这样一个相同的语句,则数据库为该语句的后续新实例使用这个共享 SQL 区,从而减少内存消耗。
- 如果不存在这样一个相同的语句,则数据库在共享池中分配一个新的共享 SQL 区。 语法相同、 但语义不同的语句会使用一个子游标。
在这两种情况下, 用户的私有 SQL 区都指向包含语句和执行计划的共享 SQL 区。 -
-
为该会话分配一个私有 SQL 区
私有 SQL 区的位置取决于该会话所建立的连接。如果会话是通过共享服务器连接的, 则该私有 SQL 区中的一部分被保存在 SGA 中。
另见:
-
《Oracle Database Development Guide》有关共享 SQL 的详细信息
程序单元和库缓存
共享池中的内存分配和重用
ALTER SYSTEM FLUSH SHARED_POOL 语句删除共享池中的所有信息,以及更改全局数据库名称。
另见:
-
《Oracle Database SQL Tuning Guide》有关共享SQL区域的生命周期的概述
-
《Oracle Database SQL Language Reference》有关使用ALTER SYSTEM FLUSH SHARED_POOL的信息
-
《Oracle Database Reference》有关 V$SQL 和 V$SQLAREA 动态视图的信息
数据字典缓存
Oracle 数据库在解析 SQL 语句期间, 会频繁访问数据字典。Oracle 数据库如此频繁地访问数据字典,所以指定了以下这些特别的内存位置来保存字典数据:
-
数据字典缓存
此缓存保存有关数据库对象的信息。 此缓存也称为行缓存,因为它按行、 而不是按缓冲区保存数据。 -
库缓存
所有服务器进程都共享这些缓存来对数据字典信息进行访问。
另见:
-
《Oracle Database Performance Tuning Guide》了解如何为数据字典缓存分配额外的内存
服务器结果缓存
与缓冲池保存数据块不同, 服务器结果缓存保存的是结果集。
另见:
-
《Oracle Database Administrator’s Guide》有关设置结果缓存大小的信息
-
《Oracle Database PL/SQL Packages and Types Reference》关于 DBMS_RESULT_CACHE 包的信息
-
《Oracle Database Performance Tuning Guide》有关客户端结果缓存的详细信息
SQL 查询结果缓存
SQL查询结果高速缓存是存储查询和查询片段的服务器结果缓存的子集。
大多数应用程序都从这种性能改进中获益。考虑一个重复运行相同SELECT语句的应用程序。如果结果会被缓存,则数据库会将其立即返回。通过这种方式, 数据库避免了重读块和重计算结果等昂贵操作。
执行查询时,数据库搜索内存以确定结果是否存在于结果缓存中。如果结果存在,那么数据库将从内存中检索结果,而不是执行查询。如果结果没有缓存,那么数据库执行查询,将结果作为输出返回,然后将结果存储在结果缓存中。每当事务修改了数据或用于构造该缓存结果的数据库对象元数据时,数据库自动使其高速缓存结果无效。
另见:
-
《Oracle Database Reference》了解 RESULT_CACHE_MODE 初始化参数
-
《Oracle Database SQL Language Reference》了解 RESULT_CACHE 提示
PL/SQL 函数结果缓存
PL/SQL函数结果缓存是存储函数结果集的服务器结果缓存的子集。
另见:
-
《Oracle Database Development Guide》了解 PL/SQL 函数结果缓存
-
《Oracle Database PL/SQL Language Reference》了解 PL/SQL 函数结果缓存
保留池
数据库以块的形式从共享池分配内存。大块使得大型对象(超过 5 KB)可以被加载到缓存中, 而不需要一个单一的连续区域。这样一来, 数据库中由于碎片引起的连续内存不足的可能性降低了。
另见:
《Oracle Database Performance Tuning Guide》了解如何配置保留池
大池
大池可以提供以下大内存分配:
- 共享服务器的 UGA 和 Oracle XA 接口(用于与多个数据库进行交互的事务)
-
并行执行中使用的消息缓冲区
-
恢复管理器 (RMAN) I/O 从属进程的缓冲区
-
用于延迟插入的缓冲区(使用 MEMOPTIMIZE_WRITE 提示插入)
下图是大池的图形显示方式
另见:
-
"Query Coordinator"有关为并行执行分配内存的信息
-
"Dispatcher Request and Response Queues"了解为共享服务器分配会话内存
-
《Oracle Database Development Guide》了解 Oracle XA
-
《Oracle Database Performance Tuning Guide》有关大池的详细信息
大池内存管理
大池管理内存的方式与共享池不同,共享池使用LRU列表,以便部分内存可以老化退出。
大池没有LRU列表。当数据库将大池内存分配给数据库会话时,除非会话释放该内存,否则不能释放该内存。一旦释放了一部分内存,其他进程就可以使用它。通过从大池中分配会话内存,数据库避免了共享池中可能出现的碎片。
用于延迟插入的大池缓冲区
对于一种称为延迟插入的特殊插入类型,数据库从大池中分配缓冲区。
对于来自物联网(IoT)应用程序的快速“fire and forget”插入,数据库基础设施会造成性能开销。例如,代码路径包括缓冲区缓存导航、缓冲区引脚和并发保护。数组插入将这些成本最小化,但是数组必须构建在客户端,这对于物联网应用程序来说并不常见。要解决这个问题,Oracle应用程序可以使用提示将行插入到指定为 MEMOPTIMIZE FOR WRITE 的表中。
插入被延迟,因为它们被缓冲在大池中,然后稍后由后台进程异步地写入磁盘。数据库处理延迟插入的过程如下:
-
应用程序将MEMOPTIMIZE_WRITE插入发送到中间层,中间层可以聚合数据。虽然物联网应用程序几乎总是将插入发送到中间层,但也可以直接将插入发送到数据库。例如,使用SQL*Plus将插入直接发送到数据库。
-
中间层将插入的聚合写入数据库服务器。
-
中间层客户机可以选择保留上一步中编写的数据的本地副本。
-
服务器进程将数据写入一个或多个大池中的缓冲区。
为了避免争用,每个缓冲区都有自己的内部锁定机制。这种锁定机制与数据库缓冲区缓存用于其缓冲区的锁定机制是分开的。基本的编写过程如下:
-
实例启动后,第一个MEMOPTIMIZE_WRITE 插入从大池中分配缓冲区。
-
写入器从可用缓冲区列表中选择一个缓冲区。
-
如果选择的缓冲区没有被锁定,并且这个缓冲区有空闲空间,那么客户端就会向缓冲区写入数据,并使用特定于会话的序列号标记每个缓冲区的写入。如果没有,则写入器返回到前面的步骤,并以这种方式继续,直到在大池中找到缓冲区或释放了足够的空间。
-
-
数据库从缓冲数据创建一个服务器端数组。
-
空间管理协调器(SMCO)及其助手进程(Wnnn)使用标准数据块格式异步地将数组写入磁盘。
与标准插入不同,延迟插入是自动提交的,不能回滚。数据库按照插入在会话中出现的顺序将插入提交给给定对象。无法保证对象或会话之间的顺序。
与常规插入一样,数据库支持约束和索引维护。但是,数据库在写到磁盘的过程中执行计算,而不是在写到大池的过程中。
-
如果在后台进程写入数据文件时发生主键冲突,则数据库将标记的行写入应用进程的跟踪文件。
下图描述了延迟插入的工作流。
另见:
-
《Oracle Database Performance Tuning Guide》学习如何将表指定为 MEMOPTIMIZE FOR WRITE
-
《Oracle Database SQL Language Reference》用于 INSERT 语法和语义
-
《Oracle Database Reference》了解更多关于MEMOPTIMIZE_POOL_SIZE的信息
Java 池
另见:
-
《Oracle Database Performance Tuning Guide》了解包含 Java 池顾问统计信息的有关视图
固定 SGA
固定 SGA 是内部的内务管理区域。
例如, 固定 SGA 包含:
-
有关数据库及其实例状态的一般信息, 后台进程需要访问这些信息
-
进程间通讯的信息, 如有关锁的信息
可选的与性能相关的SGA子区域
一些SGA子区域只支持特定的性能特性。
In-Memory 区
In-Memory 区是一个可选的SGA组件,它包含内存中的列存储(IM列存储)。
IM列存储包含表、分区和物化视图的副本,其列格式经过优化,适合快速扫描。IM列存储补充了数据库缓冲区缓存,后者以传统的行格式存储数据。
另见:
《Oracle Database In-Memory Guide》了解有关 In-Memory 区和IM列存储的更多信息
Memoptimize 池
memoptimize 池为堆组织的表存储缓冲区和相关结构,这些表指定为MEMOPTIMIZE FOR READ。
这种结构为基于键的查询提供了高性能和可伸缩性,比如SELECT * FROM cust WHERE cid = 10。为了减少端到端响应时间,客户机通过网络直接从SGA中提取请求的缓冲区,从而避免CPU和操作系统开销。应用程序可以从 memoptimize 池中获益,而不需要更改代码。
memoptimize 池包含两部分
-
Memoptimize 缓冲区
为了避免磁盘I/O,数据库永久锁定 memoptimize 池中 MEMOPTIMIZE FOR READ 表的缓冲区,直到表被标记为NO MEMOPTIMIZE FOR READ。memoptimize 缓冲区使用与数据库缓冲区缓存中的缓冲区相同的结构。但是,memoptimize 池中的缓冲区完全独立于数据库缓冲区缓存,并且不计入其大小。memoptimize 缓冲区占memoptimize 池的75%。
-
Hash 索引
哈希索引是一种非持久性的段数据结构。数据库将哈希索引分配为多个非连续的内存单元。每个单元包含许多散列桶。一个单独的映射结构将一个内存单元与一个主键关联起来。哈希索引占 memoptimize 池的25%。
要启用 memoptimize 池,请将 MEMOPTIMIZE_POOL_SIZE 初始化参数设置为整数值(默认情况下该池被禁用)。该值指定要分配给池的SGA数量。MEMOPTIMIZE_POOL_SIZE值不计入SGA_TARGET,但是数据库不会自动增长和收缩 memoptimize 池。例如,如果SGA_TARGET是 10 GB,如果 MEMOPTIMIZE_POOL_SIZE 是 1 GB,那么除 memoptimize 池外,SGA内存总共有 9 GB 可用。
要更改 memoptimize 池的大小,必须手动设置 MEMOPTIMIZE_POOL_SIZE 并重新启动数据库实例。不能使用 ALTER SYSTEM 动态更改池大小。
DBMS_MEMOPTIMIZE 包允许显式地将表填充到memoptimize 池中。
另见:
-
《Oracle Database Performance Tuning Guide》了解如何通过启用memoptimize 池来提高查询性能
-
《Oracle Database PL/SQL Packages and Types Reference》了解关于 DBMS_MEMOPTIMIZE 包的更多信息
-
《Oracle Database SQL Language Reference》了解关于 CREATE TABLE ... MEMOPTIMIZE FOR READ
-
《Oracle Database Reference》
了解关于
MEMOPTIMIZE_POOL_SIZE
软件代码区概述
软件代码区是用于存储正在运行或可以运行的代码的那部分内存。Oracle 数据库代码的存储位置通常比用户程序更专用、更受保护。