ITPUB论坛-中国最专业的IT技术社区

 找回密码
 注册
查看: 12633|回复: 7

[每日一题] PL/SQL Challenge 每日一题:2017-2-15 分析程序的内存开销

[复制链接]
论坛徽章:
454
秀才
日期:2015-08-18 09:49:27秀才
日期:2015-09-09 10:33:01秀才
日期:2015-09-09 10:33:01状元
日期:2015-09-09 10:34:21榜眼
日期:2015-09-09 10:34:21秀才
日期:2015-09-09 10:33:01秀才
日期:2015-09-09 10:33:01秀才
日期:2015-09-09 10:33:01秀才
日期:2015-09-09 10:33:01秀才
日期:2015-09-09 10:33:01
发表于 2017-2-18 05:37 | 显示全部楼层 |阅读模式
(原发表于 2011-6-14)
最先答对且答案未经编辑的puber将获得纪念章一枚(答案不可编辑但可发新贴补充或纠正),其他会员如果提供有价值的分析、讨论也可获得纪念章一枚。

每两周的优胜者可获得itpub奖励的技术图书一本。

以往旧题索引:
http://www.itpub.net/forum.php?m ... eid&typeid=1808

原始出处:
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
论坛徽章:
393
雪佛兰
日期:2013-12-04 20:30:02马上有钱
日期:2014-03-11 11:59:122014年世界杯参赛球队:喀麦隆
日期:2014-07-11 12:10:53马上有对象
日期:2014-04-09 16:19:542014年世界杯参赛球队: 洪都拉斯
日期:2014-06-25 08:25:55itpub13周年纪念徽章
日期:2014-09-28 10:55:55itpub13周年纪念徽章
日期:2014-10-01 15:27:22itpub13周年纪念徽章
日期:2014-10-09 12:04:18马上有钱
日期:2014-10-14 21:37:37马上有钱
日期:2015-01-22 00:39:13
发表于 2017-2-18 10:32 | 显示全部楼层
pl/sql的变量占用pga

使用道具 举报

回复
论坛徽章:
233
双鱼座
日期:2016-04-29 17:13:05处女座
日期:2016-10-27 22:16:58天枰座
日期:2015-12-28 11:03:38巨蟹座
日期:2015-12-20 15:00:56巨蟹座
日期:2015-12-14 21:46:03天枰座
日期:2015-11-30 15:57:24天蝎座
日期:2016-08-16 09:49:11秀才
日期:2015-11-23 10:00:44白羊座
日期:2015-11-29 10:44:09红宝石
日期:2015-11-18 17:14:00
发表于 2017-2-19 22:05 | 显示全部楼层
答案为 D

专有服务器模式下UGA 本身包含在PGA中的,所以结果只能是  l_uga <= l_pga,
另外代码中
         plch_global.g_list_of_strings (indx) := 'abc';
         l_list_of_strings (indx) := 'abc';
第一行是给PLSQL 包变量赋值,消耗的应该是UGA, 第二行是普通变量,应该消耗的是非UGA

使用道具 举报

回复
论坛徽章:
32
祖国60周年纪念徽章
日期:2009-10-09 08:28:00九尾狐狸
日期:2012-12-19 11:08:372013年新春福章
日期:2013-02-25 14:51:24ITPUB季度 技术新星
日期:2013-07-30 16:04:58迷宫蛋
日期:2013-06-28 11:09:23红孩儿
日期:2014-03-04 16:40:38优秀写手
日期:2013-12-18 09:29:132014年新春福章
日期:2014-02-18 16:43:09马上有钱
日期:2014-02-18 16:43:09懒羊羊
日期:2015-03-04 14:52:11
发表于 2017-2-20 09:50 | 显示全部楼层
solomon_007 发表于 2017-2-19 22:05
答案为 D

专有服务器模式下UGA 本身包含在PGA中的,所以结果只能是  l_uga

为什么两个变量的赋值使用的是不同的内存区域?

使用道具 举报

回复
论坛徽章:
3
ITPUB15周年纪念
日期:2016-10-13 13:15:34秀才
日期:2017-03-20 13:42:20秀才
日期:2017-03-28 15:59:38
发表于 2017-2-20 14:29 | 显示全部楼层
答案是D,专用服务器模式uga是从pag中分配,共享服务器模式则从sga中分配,pga分配内存是“堆”的结构,至于楼上的提到的变量赋值用到的不同区域同样不解。坐等高手解答

使用道具 举报

回复
论坛徽章:
233
双鱼座
日期:2016-04-29 17:13:05处女座
日期:2016-10-27 22:16:58天枰座
日期:2015-12-28 11:03:38巨蟹座
日期:2015-12-20 15:00:56巨蟹座
日期:2015-12-14 21:46:03天枰座
日期:2015-11-30 15:57:24天蝎座
日期:2016-08-16 09:49:11秀才
日期:2015-11-23 10:00:44白羊座
日期:2015-11-29 10:44:09红宝石
日期:2015-11-18 17:14:00
发表于 2017-2-20 20:39 | 显示全部楼层
regonly1 发表于 2017-2-20 09:50
为什么两个变量的赋值使用的是不同的内存区域?

包头中的全局变量被赋值后,其他用户也是可见的,所以放在共享的用户全局区UGA,其他不放,我猜是这样。。。

使用道具 举报

回复
论坛徽章:
454
秀才
日期:2015-08-18 09:49:27秀才
日期:2015-09-09 10:33:01秀才
日期:2015-09-09 10:33:01状元
日期:2015-09-09 10:34:21榜眼
日期:2015-09-09 10:34:21秀才
日期:2015-09-09 10:33:01秀才
日期:2015-09-09 10:33:01秀才
日期:2015-09-09 10:33:01秀才
日期:2015-09-09 10:33:01秀才
日期:2015-09-09 10:33:01
 楼主| 发表于 2017-2-21 09:54 | 显示全部楼层
答案D, 3楼得奖。

在专用服务器(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;
/

使用道具 举报

回复
论坛徽章:
32
祖国60周年纪念徽章
日期:2009-10-09 08:28:00九尾狐狸
日期:2012-12-19 11:08:372013年新春福章
日期:2013-02-25 14:51:24ITPUB季度 技术新星
日期:2013-07-30 16:04:58迷宫蛋
日期:2013-06-28 11:09:23红孩儿
日期:2014-03-04 16:40:38优秀写手
日期:2013-12-18 09:29:132014年新春福章
日期:2014-02-18 16:43:09马上有钱
日期:2014-02-18 16:43:09懒羊羊
日期:2015-03-04 14:52:11
发表于 2017-2-21 09:55 | 显示全部楼层
solomon_007 发表于 2017-2-20 20:39
包头中的全局变量被赋值后,其他用户也是可见的,所以放在共享的用户全局区UGA,其他不放,我猜是这样。 ...

是怎么看到的?我用下面的方法不行么:
session1:
SQL> begin
  2      pkg1.global_value := 2;
  3      dbms_output.put_line(pkg1.global_value);
  4  end;
  5  /
2
PL/SQL procedure successfully completed

sesssion 2:
SQL> begin
  2      dbms_output.put_line(pkg1.global_value);
  3  end;
  4  
  5  /
1
PL/SQL procedure successfully completed

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则

TOP技术积分榜 社区积分榜 徽章 电子杂志 团队 统计 虎吧 老博客 知识索引树 读书频道 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档 | IT博客
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛 | SAP ERP系统
CopyRight 1999-2011 itpub.net All Right Reserved. 北京皓辰网域网络信息技术有限公司版权所有 联系我们 网站律师 隐私政策 知识产权声明
京ICP证:060528号 北京市公安局海淀分局网监中心备案编号:1101082001 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表