oracle 每日一题-分析程序的内存开销(sga,pga,uga)

原始出处:
http://www.plsqlchallenge.com/

作者:Steven Feuerstein 

运行环境:SQLPLUS, SERVEROUTPUT已打开

我创建了如下的包,含有一个集合变量:

CREATE OR REPLACE PACKAGE plch_global
IS
   g_list_of_strings   DBMS_SQL.varchar2_table;
END plch_global;
/

然后我执行了下列代码块。假设:
(a)我的用户具有访问这个代码用到的V$视图的权限,使得它编译不出错,并且
(b)我的会话具备足够的内存来填充这两个集合。

注意:假设Oracle是以专用服务器(dedicated server)方式运行

DECLARE
   l_list_of_strings   DBMS_SQL.varchar2_table;
   l_uga               NUMBER;
   l_pga               NUMBER;

   FUNCTION statval (statname_in IN VARCHAR2)
      RETURN NUMBER
   IS
      l_memory   PLS_INTEGER;
   BEGIN
      SELECT s.VALUE
        INTO l_memory
        FROM v$sesstat s
           , v$statname n
           , (SELECT *
                FROM v$session
               WHERE audsid = USERENV ('SESSIONID')) my_session
       WHERE     s.statistic# = n.statistic#
             AND s.sid = my_session.sid
             AND n.name = statname_in;

      RETURN l_memory;
   END statval;

   PROCEDURE consume_memory
   IS
   BEGIN
      FOR indx IN 1 .. 100000
      LOOP
         plch_global.g_list_of_strings (indx) := 'abc';
         l_list_of_strings (indx) := 'abc';
      END LOOP;
   END;
BEGIN
   consume_memory;
   
   l_uga := statval ('session uga memory');
   l_pga := statval ('session pga memory');
   
   sys.DBMS_OUTPUT.put_line (
      CASE
         WHEN l_uga = l_pga THEN 'EQUAL'
         WHEN l_uga < l_pga THEN 'PGA BIGGER'
         WHEN l_uga > l_pga THEN 'UGA BIGGER'
         ELSE 'AT LEAST ONE NULL'
      END);
END;
/

代码块执行之后会显示什么?


(A) 
EQUAL

(B) 
UGA BIGGER

(C) 
AT LEAST ONE NULL

(D) 
PGA BIGGER





PACKAGE同PACKAGE BODY的区别?

一个包的两个主体部分,
可以这样理解
把一个包看成一本书,那里面的PACKAGE就是书的目录,而BODY就是书的详细内容.
就好比java的接口和实现的类的区别!
接口只提供抽象方法的定义,然后由别的类来继承这个接口,并实现抽象方法体!
package也是提供方法和变量的定义,然后由package body来实现每一个方法体!
写了个最简单的
create or replace package xyd is
  type aa is ref cursor; -------定义type 
procedure xyd_pro1(p1 out sys_refcursor); ----------定义存储过程

end xyd;
-----------------------------上面是PACKAGE
---------------------------下面是PACKAGE BODY
create or replace package body xyd is
procedure xyd_pro1 (p1 out sys_refcursor)        ------------存储过程具体实现
is
begin
open p1 for select empno from emp;
end xyd_pro1;
end xyd;

DBMS_SQL.Varchar2_Table 

type Varchar2_Table is table of varchar2(2000) index by binary_integer;
简单理解就是一个字符串类型的数组
PLS_INTEGER可以存储一个有符号的整形值,其精度范围和BINARY_INTEGER一样,是:-2^31~2^31。

PLS_INTEGER和NUMBER比较起来,其优点是:
1).占有较少的存储空间;
2).可以直接进行算术运算(在NUMBER上不能直接进行算术运算,如果要计算,NUMBER必须先被转换成二进制)。所以在进行算术的时候PLS_INTEGER比NUMBER和BINARY_INTEGER快一些。

PLS_INTEGER和BINARY_INTEGER区别:
PLS_INTEGER进行的运算发生溢出的时候,会触发异常。但是当BINARY_INTEGER运算发生溢出时,如果可以指派给一个NUMBER变量(没有超出NUMBER的精度范围)的话就不会触发异常。
oracle内存详细资料  http://www.cnblogs.com/xqzt/p/4999513.html

一、 系统全局区  (System Global Area, SGA):

SGA是一组共享内存结构, 被所有的服务和后台进程所共享。当数据库实例启动时,系统全局区内存被自动分配。当数据库实例关闭时,SGA内存被回收。 SGA是占用内存最大的一个区域,同时也是影响数据库性能的重要因素。

二、进程全局区(Porcess Global Area, PGA)

一个PGA是一块独占内存区域,Oracle进程以专有的方式用它来存放数据和控制信息。当Oracle进程启动时,PGA也就由Oracle数据库创建了。当用户进程连接到数据库并创建一个对应的会话时,Oracle服务进程会为这个用户专门设置一个PGA区,用来存储这个用户会话的相关内容。当这个用户会话终止时,系统会自动释放这个PGA区所占用的内存。

三、用户全局区  (User Global Area, UGA)

专用服务器模式下,进程和会话是一对一的关系,UGA被包含在PGA中,在联机服务器模式下,进程和会话是一对多的关系,所以UGA就不再属于 PGA了,而会在大型池(Large Pool)中分配。但如果从大型池中分配失败,如大型池太小,或是根本没有设置大型池,则从共享池(Shared Pool)中分配。


   
   
答案D,
在专用服务器(dedicated server)模式下, UGA 是放在 PGA 内部的,因为所有其它的服务器进程都不需要访问它。

g_list_of_strings 和 l_list_of_strings所分配的内存大致相同。
PGA内存的增量大约是UGA内存的两倍,因为PGA包含了UGA。
你可以用下面这个包来检查你应用的内存消耗:

CREATE OR REPLACE PACKAGE plsql_memory
/*
Overview: Calculate and show UGA and PGA memory consumption
          by the current session.

Author: John Beresniewicz and Steven Feuerstein

Dependencies:

    SELECT privileges required on:
       v$sesstat
       v$statname

    Here are the statements you should run:

    GRANT SELECT ON v$sesstat TO schema;
    GRANT SELECT ON v$statname TO schema;
*/
IS
   PROCEDURE reset_analysis;

   PROCEDURE start_analysis;

   PROCEDURE show_memory_usage (pga_only_in IN BOOLEAN DEFAULT FALSE);
END plsql_memory;
/

CREATE OR REPLACE PACKAGE BODY plsql_memory
IS
   g_uga_start   PLS_INTEGER;
   g_pga_start   PLS_INTEGER;

   FUNCTION statval (statname_in IN VARCHAR2)
      RETURN NUMBER
   IS
      l_memory   PLS_INTEGER;
   BEGIN
      SELECT s.VALUE
        INTO l_memory
        FROM v$sesstat s
           , v$statname n
           , (SELECT *
                FROM v$session
               WHERE audsid = USERENV ('SESSIONID')) my_session
       WHERE     s.statistic# = n.statistic#
             AND s.sid = my_session.sid
             AND n.name = statname_in;

      RETURN l_memory;
   END statval;

   PROCEDURE reset_analysis
   IS
   BEGIN
      g_uga_start := NULL;
      g_pga_start := NULL;
   END reset_analysis;

   PROCEDURE get_memory_data (uga_out   OUT PLS_INTEGER
                            , pga_out   OUT PLS_INTEGER)
   IS
   BEGIN
      uga_out := statval ('session uga memory');
      pga_out := statval ('session pga memory');
   END get_memory_data;

   PROCEDURE start_analysis
   IS
   BEGIN
      get_memory_data (g_uga_start, g_pga_start);
   END start_analysis;

   PROCEDURE show_memory_usage (pga_only_in IN BOOLEAN DEFAULT FALSE)
   IS
      l_uga_usage   PLS_INTEGER;
      l_pga_usage   PLS_INTEGER;

      PROCEDURE show_one (type_in    IN VARCHAR2
                        , usage_in   IN INTEGER
                        , start_in   IN INTEGER)
      IS
      BEGIN
         IF g_uga_start IS NULL
         THEN
            DBMS_OUTPUT.put_line (
               '   ' || type_in || ' memory: ' || usage_in);
         ELSE
            DBMS_OUTPUT.put_line (
                  '   Change in '
               || type_in
               || ' memory: '
               || TO_CHAR (usage_in - start_in)
               || ' (Current = '
               || TO_CHAR (usage_in)
               || ')');
         END IF;
      END show_one;
   BEGIN
      get_memory_data (l_uga_usage, l_pga_usage);

      IF NOT pga_only_in
      THEN
         show_one ('UGA', l_uga_usage, g_uga_start);
      END IF;

      show_one ('PGA', l_pga_usage, g_pga_start);
   END show_memory_usage;
END plsql_memory;
        plch_global.g_list_of_strings (indx) := 'abc';
         l_list_of_strings (indx) := 'abc';
第一行是给PLSQL 包变量赋值,消耗的应该是UGA, 第二行是普通变量,应该消耗的是非UGA
猜测:包头中的全局变量被赋值后,其他用户也是可见的,所以放在共享的用户全局区UGA,其他不放



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值