PGA(Program Global Area程序全局区)是一块包含一个服务进程的数据和控制信息的内存区域。它是Oracle在一个服务进程启动是创建的,是非共享的。一个Oracle进程拥有一个PGA内存区。一个PGA也只能被拥有它的那个服务进程所访问,只有这个进程中的Oracle代码才能读写它。因此,PGA中的结构是不需要Latch保护的。
我们可以设置所有服务进程的PGA内存总数受到实例分配的总体PGA(Aggregated PGA)限制。
在专有服务器(Dedicated Server)模式下,Oracle会为每个会话启动一个Oracle进程;而在多线程服务(Multi-Thread Server MTS)模式下,由多个会话共享通一个Oracle服务进程。
PGA中包含了关于进程使用到的操作系统资源的信息,以及一些关于进程状态的信息。而关于进程使用的Oracle共享资源的信息则是在SGA中。这样做可以使在进程以外中止时,能够及时释放和清除这些资源。
1.2.1. PGA的组成PGA由两组区域组成:固定PGA和可变PGA(或者叫PGA堆,PGA Heap【堆——Heap就是一个受管理的内存区】)。固定PGA和固定SGA类似,它的大小时固定的,包含了大量原子变量、小的数据结构和指向可变PGA的指针。
可变PGA时一个内存堆。它的内存段可以通过视图X$KSMPP(另外一个视图X$KSMSP可以查到可变SGA的内存段信息,他们的结构相同)查到。PGA堆包含用于存放X$表的的内存(依赖与参数设置,包括DB_FILES、CONTROL_FILES)。
总的来说,PGA的可变区中主要分为以下三部分内容:
o 私有SQL区;
o 游标和SQL区
o 会话内存
1.2.1.1. 私有SQL区(Private SQL Area)前面已经说过,私有SQL区包含了绑定变量值和运行时期内存结构信息等数据。每一个运行SQL语句的会话都有一个块私有SQL区。所有提交了相同SQL语句的用户都有各自的私有SQL区,并且他们共享一个共享SQL区。因此,一个共享SQL区可能和多个私有共享区相关联。
一个游标的私有SQL区又分为两个生命周期不同的区:
o 永久区。包含绑定变量信息。当游标关闭时被释放。
o 运行区。当执行结束时释放。
创建运行区是一次执行请求的第一步。对于INSERT、UPDATE和DELETE语句,Oracle在语句运行结束时释放运行区。对于查询操作,Oracle只有在所有记录被fetch到或者查询被取消时释放运行区。
1.2.1.2. 游标和SQL区(Cursors and SQL Areas)一个Oracle预编译程序或OCI程序的应用开发人员能够很明确的打开一个游标,或者控制一块特定的私有SQL区,将他们作为程序运行的命名资源。另外,oracle隐含的为一些SQL语句产生的递归调用(前面有介绍,读取数据字典信息)也使用共享SQL区。
私有SQL区是由用户进程管理的。如何分配和释放私有SQL区极大的依赖与你所使用的应用工具。而用户进程可以分配的私有SQL区的数量是由参数OPEN_CURSORS控制的,它的默认值是50。
在游标关闭前或者语句句柄被释放前,私有SQL区将一直存在(但其中的运行区是在语句执行结束时被释放,只有永久区一直存在)下去。应用开发人员可以通过将所有打开的不再使用的游标都关闭来释放永久区,以减少用户程序所占用的内存。
1.2.1.3. 会话内存(Session Memory)会话内存是一段用于保存会话变量(如登录信息)和其他预会话相关信息的内存。对于共享服务器模式下,会话内存是共享的,而不是私有的。
对于复杂的查询(如决策支持系统中的查询),运行区的很大一部分被那些内存需求很大的操作分配给SQL工作区(SQL Work Area)。这些操作包括:
o 基于排序的操作(ORDER BY、GROUP BY、ROLLUP、窗口函数);
o Hash Join
o Bitmap merge
o Bitmap create
例如,一个排序操作使用工作区(这时也可叫排序区Sort Area)来将一部分数据行在内存排序;而一个Hash Join操作则使用工作区(这时也可以叫做Hash区 Hash Area)来建立Hash表。如果这两种操作所处理的数据量比工作区大,那就会将输入的数据分成一些更小的数据片,使一些数据片能够在内存中处理,而其他的就在临时表空间的磁盘上稍后处理。尽管工作区太小时,Bitmap操作不会将数据放到磁盘上处理,但是他们的复杂性是和工作区大小成反比的。因此,总的来说,工作区越大,这些操作就运行越快。
工作区的大小是可以调整的。一般来说,大的工作区能让一些特定的操作性能更佳,但也会消耗更多的内存。工作区的大小足够适应输入的数据和相关的SQL操作所需的辅助的内存就是最优的。如果不满足,因为需要将一部分数据放到临时表空间磁盘上处理,操作的响应时间会增长。
1.2.2. PGA内存自动管理SQL工作区可以是自动的、全局的管理。DBA只要设置参数PGA_AGGREGATE_TARGET给一个实例的PGA内存指定总的大小。设置这个参数后,Oracle将它作为一个总的全局限制值,尽量使所有Oracle服务进程的PGA内存总数不超过这个值。
在这个参数出现之前,DBA要调整参数SORT_AREA_SIZE、 HASH_AREA_SIZE,、BITMAP_MERGE_AREA_SIZE 和CREATE_BITMAP_AREA_SIZE(关于这些参数,我们会在后面介绍),使性能和PGA内存消耗最佳。对这些参数的调整是非常麻烦的,因为即要考虑所有相关的操作,使工作区适合它们输入数据大小,又要使PGA内存不消耗过大导致系统整体性能下降。
9i以后,通过设置了参数PGA_AGGREGATE_TARGET,使所有会话的工作区的大小都是自动分配。同时,所有*_AREA_SIZE参数都会失效。在任何时候,实例中可用于工作区的PGA内存总数都是基于参数PGA_AGGREGATE_TARGET的。工作区内存总数等于参数PGA_AGGREGATE_TARGET的值减去系统其他组件(如分配给会话的PGA内存)的内存消耗。分配给Oracle进程的PGA内存大小是根据它们对内存的需求情况来的。
参数WORKAREA_SIZE_POLICY决定是否使用PGA_AGGREGATE_TARGET来管理PGA内存。它有两个值:AUTO和MANUAL。默认是AUTO,即使用PGA_AGGREGATE_TARGET来管理PGA内存。其实,从参数WORKAREA_SIZE_POLICY的名字上可以看出,Oracle的PGA内存自动管理只会调整工作区部分,而非工作区部分(固定PGA区)则不会受影响。
还有注意一点就是:10g之前,PGA_AGGREGATE_TARGET只在专用服务模式下生效。而10g以后,PGA内存自动管理在专有服务模式(Dedicated Server)和MTS下都有效。另外,9i在OpenVMS系统上还不支持PGA内存自动管理,但10g支持。
设置了PGA_AGGREGATE_TARGET以后,每个进程PGA内存的大小也是受限制的:
o 串行操作时,每个进程可用的PGA内存为MIN(PGA_AGGREGATE_TARGET * 5%, _pga_max_size/2),其中隐含参数_pga_max_size的默认值是200M,同样不建议修改它。
o 并行操作时,并行语句可用的PGA内存为PGA_AGGREGATE_TARGET * 30% / DOP (Degree Of Parallelism 并行度)。
1.2.3. 专有服务(Dedicated Server)和共享服务(Shared Server)对PGA内存的管理和分配,很大程度上依赖与服务模式。下面这张表显示了在不同模式下,PGA内存不同部分的分配的异同:
内存区
专有服务
共享服务
会话内存 私有的 共享的 永久区所在区域 PGA SGA SELECT语句的运行区所在区域 PGA PGA DML/DDL语句的运行区所在区域 PGA PGA 1.2.4. 重要参数PGA的管理和分配是由多个系统参数控制的,下面介绍一下这些参数:
1.2.4.1. PGA_AGGREGATE_TARGET这个参数前面介绍了。它控制了所有进程PGA内存的总的大小。
在专有服务模式下,推荐使用PGA_AGGREGATE_TARGET。
PGA_AGGREGATE_TARGET的取值范围是10M~(4096G - 1 )bytes。
对于PGA_AGGREGATE_TARGET大小的设置,Oracle提供了一个以下建议方案(参见Metalink Note: 223730.1):
o 对于OLTP系统,PGA_AGGREGATE_TARGET = (物理内存大小 * 80%) * 20%
o 对于DSS系统,PGA_AGGREGATE_TARGET = (物理内存大小 * 80%) * 50%
例如,你的系统是一个OLTP系统,物理内存为8G,那么推荐PGA_AGGREGATE_TARGET设置为 (8 * 80%) * 20% = 1.28G。
1.2.4.2. WORKAREA_SIZE_POLICY参数WORKAREA_SIZE_POLICY决定是否使用PGA_AGGREGATE_TARGET来管理PGA内存。它有两个值:AUTO和MANUAL。默认是AUTO,即使用PGA_AGGREGATE_TARGET来管理PGA内存。
1.2.4.3. sort_area_sizeOracle在做排序操作(ORDER BY、GROUP BY、ROLLUP、窗口函数)时,需要从工作区中分配一定内存区域对数据记录做内存排序。在排序完成后,数据返回之前,Oracle会释放这部分内存,。SORT_AREA_SIZE指定了这部分内存的大小。设置了PGA_AGGREGATE_TARGET后,该参数无效。
除非在共享服务模式下,一般不推荐设置这个参数,而推荐使用PGA_AGGREGATE_TARGET进行PGA内存自动管理。如果需要设置此参数,可以考虑设置在1M~3M。
Oracle也许会为一个查询分配多个排序区。通常情况下,一条语句只有1、2个排序操作,但是对于复杂语句,可能存在多个排序操作,每个排序操作都有自己的排序区。因此,语句的复杂性也影响到每个进程PGA内存的大小。
1.2.4.4. sort_area_retained_size这个参数与SORT_AREA_SIZE配合使用。它指定了在排序操作完成后,继续保留用户全局区(User Global Area UGA,关于UGA与PGA、SGA关系在UGA部分介绍)内存的最大大小,以维护内存中的排序,直到所有数据行被返回后才释放(上面提到,SORT_AREA_SIZE的内存在排序完成、数据行返回之前被释放)回UGA(注意:是释放回UGA,而不会被操作系统回收)。
SORT_AREA_RETAINED_SIZE在共享服务中是从SGA中分配的(因为此时UGA从SGA中分配),在专有服务模式中是从PGA中分配的。而SORT_AREA_SIZE无论在那种模式下都从PGA中分配。
同样,设置了PGA_AGGREGATE_TARGET后,该参数无效。
1.2.4.5. hash_area_sizeHASH_AREA_SIZE设置了在做Hash Join时,hash内存表可占用的内存空间。同样,设置了PGA_AGGREGATE_TARGET后,该参数无效。它的默认值大小是sort_area_size的1.5倍。
此外,由于Hash Join只有在优化器为CBO(Cost-Base Optimizer)模式下才有效,因此这个参数也只有CBO模式下才有意义。
1.2.4.6. hash_join_enable这个参数决定是否启用Hash Join。默认为TRUE。
由于Hash Join只有在优化器为CBO(Cost-Base Optimizer)模式下才有效,因此这个参数也只有CBO模式下才有意义。
10g中,这个参数是隐含参数。
1.2.4.7. bitmap_merge_area_size在使用位图索引(Bitmap Index)时,oracle为索引位图段建立一张位图。在进行位图索引扫描时,需要将扫描到的位图索引排序后与位图合并(Merge),Oracle会在PGA中开辟一片区域用于排序和合并。参数BITMAP_MERGE_AREA_SIZE指定了这篇区域的大小。默认值是1M。
同样,设置了PGA_AGGREGATE_TARGET后,该参数无效。
1.2.4.8. create_bitmap_area_size在字段的集的势(Cardinality 参照记录行数,字段的不同值的一个因子。记录数越多,不同值越少,则集的势越小)很小,并且表的数据变化不大时,可以考虑为字段建立位图索引以提高对该字段的检索效率。这个参数指定可在创建位图索引时的内存空间占用大小。它的默认大小是8M。
同样,设置了PGA_AGGREGATE_TARGET后,该参数无效。
1.2.4.9. open_cursors这个参数设置一个会话可以同时打开的游标数。由于每打开一个游标,都需要一部分PGA内存分配出来作为私有SQL区。因此这个参数也影响了每个进程的PGA内存的占用大小。
1.2.4.10. _pga_max_size这是一个隐含参数。它规定了一个PGA的最大大小。可参见1.2.2。
1.2.5. 重要视图 1.2.5.1. V$PGASTAV$PGASTAT提供了PGA内存使用情况的统计信息和当自动PGA内存管理启动时的统计信息。视图里面的累加数据是自从实例启动后开始累加的。
字段
数据类型
说明
NAME
VARCHAR2(64)
统计的名称,包括:
aggregate PGA target parameter – 当前参数PGA_AGGREGATE_TARGET的值。如果参数没有设置,则值为0并且PGA内存自动管理被关闭。
aggregate PGA auto target – 在自动管理模式下,可用于工作区的总的PGA内存数。这个数值是动态的,和PGA_AGGREGATE_TARGET 的值以及当前工作区的负载有关,Oracle会动态调整它。
这个值相对与PGA_AGGREGATE_TARGET来说很小。其他很大一部分的PGA内存都被用于系统的其他组件(如PLSQL和Java的内存)。DBA必须保证在自动模式下有足够的PGA内存用于工作区。
global memory bound – 自动模式下可用的工作区的最大大小。Oracle根据当前工作区的负载动态调整这个值。当系统中活动的工作区数量增加时,global memory bound一般会下降。如果global bound 降到低于1M,则要考虑增加PGA_AGGREGATE_TARGET了。
total PGA allocated – 当前实例分配的总的PGA内存大小。Oracle会试图保持这个值在PGA_AGGREGATE_TARGET以内。然而,当工作区负载增加得非常快或者PGA_AGGREGATE_TARGET被设置得很小时,这个值也许会在一段时间内超过PGA_AGGREGATE_TARGET。
total PGA used – 当前被工作区消耗得PGA内存。这个数值也可以用于计算有多少PGA内存被其他组件(如PLSQL或Java)所消耗。
total PGA used for auto workareas – 自动模式下,当前多少PGA内存被工作区所消耗。这个数值也可以用于计算有多少PGA内存被其他组件(如PLSQL或Java)所消耗。
total PGA used for manual workareas –手动模式下,当前多少PGA内存被工作区所消耗。这个数值也可以用于计算有多少PGA内存被其他组件(如PLSQL或Java)所消耗。
over allocation count – 这个数值是自从实例启动后累加的。当PGA_AGGREGATE_TARGET设置非常小或工作区负载增长很快时,会超额分配PGA内存(分配的值大于PGA_AGGREGATE_TARGET)。这种情况发生时,Oracle不能限制PGA内存小于PGA_AGGREGATE_TARGET,只能分配实际需要的PGA内存。此时,建议通过建议器视图V$PGA_TARGET_ADVICE来增加PGA_AGGREGATE_TARGET的大小。
bytes processed – 自从实例启动后,被内存SQL操作处理的字节数。
extra bytes read/written – 自从实例启动后,需要额外输入数据所处理的字节数。当工作区无法在最佳状态下运行时,就需要进行这个额外处理。
cache hit percentage – Oracle计算出来的一个与PGA内存组件性能相关的数据,是自从实例启动后累加的。如果这个值是100%,则表示实例启动后,所有系统使用到的工作区都分配了最佳的PGA内存。
当工作区无法在最佳状态下运行,就需要进行额外的数据输入处理,这将会降低cache hit percentage。
VALUE
NUMBER
统计数据
UNITS
VARCHAR2(12)
数据的单位 (microseconds, bytes, or percent)
1.2.5.2. V$PGA_TARGET_ADVICE
这个视图是可以显示PGA优化建议器的估算预测结果,它显示了在各种PGA_AGGREGATE_TARGET值时,V$PGASTAT可能会显示的PGA性能统计数据。选取所用来预测的PGA_AGGREGATE_TARGET值是当前PGA_AGGREGATE_TARGET左右的的值。而估算出的统计值是根据实例启动后的负载模拟出来的。
只有当建议器打开(隐含参数_smm_advice_enabled为TRUE),并且参数STATISTICS_LEVEL值不是BASIC时,视图中才会有内容。实例重启后,所有预测数据都会被重写。
字段
数据类型
说明
PGA_TARGET_FOR_ESTIMATE
NUMBER
用于预测的PGA_AGGREGATE_TARGET值。
PGA_TARGET_FACTOR
NUMBER
预测的PGA_AGGREGATE_TARGET与当前PGA_AGGREGATE_TARGET的比。
ADVICE_STATUS
VARCHAR2(3)
建议器状态(ON或OFF)
BYTES_PROCESSED
NUMBER
预测的被所有工作区处理的字节数。
ESTD_EXTRA_BYTES_RW
NUMBER
当PGA_AGGREGATE_TARGET设置为预测值时,需要额外读写的字节数。
ESTD_PGA_CACHE_HIT_PERCENTAGE
NUMBER
当PGA_AGGREGATE_TARGET设置为预测值时,缓存命中率。这个值等于BYTES_PROCESSED / (BYTES_PROCESSED + ESTD_EXTRA_BYTES_RW)
ESTD_OVERALLOC_COUNT
NUMBER
当PGA_AGGREGATE_TARGET设置为预测值时,需要超额分配的PGA内存。如果非0则说明PGA_AGGREGATE_TARGET设置得太小。
1.2.5.3. V$SYSSTAT 、V$SESSTAT
这两个视图显示了系统(会话)的统计数据。他们的统计项目基本相同,但不同之处在于一个是系统级的、一个是会话级的。
通过这两个视图我们可以查出像sort这样操作对工作区的使用情况:
SQL> select * from V$SYSSTAT
2 where name like '%sort%';
STATISTIC# NAME CLASS VALUE
---------- ---------------------------------------------------------------- ---------- ----------
245 sorts (memory) 64 2876455
246 sorts (disk) 64 483
247 sorts (rows) 64 116554720
SQL>
1.2.5.4. V$SQL_WORKAREA
这个视图显示了被SQL游标使用的工作区的信息。存储在Shared Pool中的每条SQL语句都有一个或多个子游标,它们能被V$SQL显示。而V$SQL_WORKAREA显示需要被这些游标所使用的工作区信息。可以将它与V$SQL进行join查询。
通过这个视图可以解决以下一些问题:
1、 请求最多的工作区;
2、 在自动模式下,占用内存最多的工作区。
字段
数据类型
说明
ADDRESS
RAW(4 | 8)
游标句柄的地址。
HASH_VALUE
NUMBER
游标句柄的Hash值。这个字段和ADDRESS字段join V$SQLAREA可以定位出相关语句。
CHILD_NUMBER
NUMBER
使用此工作区的子游标数。
WORKAREA_ADDRESS
RAW(4 | 8)
工作区句柄的地址。唯一定位了一条记录
OPERATION_TYPE
VARCHAR2(20)
工作区的操作类型(SORT, HASH JOIN, GROUP BY, BUFFERING, BITMAP MERGE, or BITMAP CREATE)
OPERATION_ID
NUMBER
唯一定位查询计划中的一个操作的值,可以和视图V$SQL_PLAN join。
POLICY
VARCHAR2(10)
工作区的模式(MANUAL或AUTO)
ESTIMATED_OPTIMAL_SIZE
NUMBER
估计需要此工作区来执行内存中操作的所需的大小。
ESTIMATED_ONEPASS_SIZE
NUMBER
估计需要此工作区来一次执行内存中操作的所需的大小。
LAST_MEMORY_USED
NUMBER
最后一次执行游标所使用的工作区大小。
LAST_EXECUTION
VARCHAR2(10)
最后一次执行游标,工作区请求内存的方式,OPTIMAL, ONE PASS, ONE PASS 或MULTI-PASS。
LAST_DEGREE
NUMBER
最后一次执行并行操作的并行度(Degree of parallelism DOP)。
TOTAL_EXECUTIONS
NUMBER
此工作区激活的次数。
OPTIMAL_EXECUTIONS
NUMBER
此工作区运行于optimal模式的次数
ONEPASS_EXECUTIONS
NUMBER
此工作区运行于one-pass 模式的次数
MULTIPASSES_EXECUTIONS
NUMBER
此工作区运行于one-pass内存请求情况下的次数
ACTIVE_TIME
NUMBER
此工作区激活的评价时间数。
MAX_TEMPSEG_SIZE
NUMBER
实例化此工作区所创建的临时段的最大大小。
LAST_TEMPSEG_SIZE
NUMBER
最后一次实例化此工作区所创建的临时段的大小。
1.2.5.5. V$SQL_WORKAREA_ACTIVE这个视图包含了系统当前分配的工作区的瞬间信息。可以通过字段WORKAREA_ADDRESS join V$SQL_WORKAREA来查询工作区信息。如果工作区溢出到磁盘,则这个视图就包含了这个工作区所溢出的临时段的信息。通过与视图V$TEMPSEG_USAGE join,可以得到更多的临时段信息。
这个视图可以解决以下问题:
1、 当前系统分配最大的工作区;
2、 超额分配内存的百分比(EXPECTED_SIZE < ACTUAL_MEM_USED),和未超额分配内存的百分比(EXPECTED_SIZE > ACTUAL_MEM_USED);
3、 哪个活动的工作区使用了超出内存管理预期的内存大小;
4、 那个活动的工作区溢出到磁盘了。
字段
数据类型
说明
WORKAREA_ADDRESS
RAW(4 | 8)
工作区句柄的地址。唯一定位了一条记录。
OPERATION_TYPE
VARCHAR2(20)
使用此工作区的操作 (SORT, HASH JOIN, GROUP BY, BUFFERING, BITMAP MERGE, 或 BITMAP CREATE)
OPERATION_ID
NUMBER
唯一定位查询计划中的一个操作的值,可以和视图V$SQL_PLAN join。
POLICY
VARCHAR2(6)
工作区的模式(MANUAL或AUTO)
SID
NUMBER
会话ID
QCINST_ID
NUMBER
查询协调(查询协调在并行查询中出现)者实例ID。
QCSID
NUMBER
查询协调者的会话ID。
ACTIVE_TIME
NUMBER
此工作区激活的平均时间(厘秒为单位)
WORK_AREA_SIZE
NUMBER
被当前操作使用的最大工作区大小。
EXPECTED_SIZE
NUMBER
工作区的预期大小。预期大小是内存管理器设置的。当WORK_AREA_SIZE 大于EXPECTED_SIZE 时,内存会超额分配。
ACTUAL_MEM_USED
NUMBER
当前分配个工作区的PGA内存大小(KB)。这个值在0和 WORK_AREA_SIZE之间。
MAX_MEM_USED
NUMBER
这个工作区使用的最大大小(KB)。
NUMBER_PASSES
NUMBER
这个工作区的通道数(如果在OPTIMAL模式下为0)
TEMPSEG_SIZE
NUMBER
用于此工作区的临时段大小。
TABLESPACE
VARCHAR2(31)
创建临时段给这个工作区的表空间名字。
SEGRFNO#
NUMBER
创建临时段的表空间的文件ID。
SEGBLK#
NUMBER
给工作区创建临时段的block数。
1.2.5.6. V$PROCESS这个视图显示了所有Oracle进程的信息。其中以下几个字段则说明了进程PGA内存的使用情况。
PGA_USED_MEM:进程使用的PGA内存
PGA_ALLOCATED_MEM:分配给进程的PGA内存
PGA_MAX_MEM:进程使用的最大的PGA内存。