[20170426]为什么是4秒.txt

简介: [20170426]为什么是4秒.txt --//在开发程序时我一般会强调开发尽量不要写一些自定义函数,往往可能导致CPU忙。今天测试遇到一个问题: --//原始的测试来之nimishgarg.blogspot.com/2016/03/avoiding-unnecessary-function-calls-to.html --//先重复测试。

[20170426]为什么是4秒.txt

--//在开发程序时我一般会强调开发尽量不要写一些自定义函数,往往可能导致CPU忙。今天测试遇到一个问题:
--//原始的测试来之nimishgarg.blogspot.com/2016/03/avoiding-unnecessary-function-calls-to.html

--//先重复测试。

1.环境:
SCOTT@book> @ &r/ver1
PORT_STRING                    VERSION        BANNER
------------------------------ -------------- --------------------------------------------------------------------------------
x86_64/Linux 2.4.xx            11.2.0.4.0     Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production

2.普通函数:
CREATE OR REPLACE FUNCTION get_dept (p_deptno dept.deptno%TYPE)
   RETURN dept.dname%TYPE
IS
   l_dname   dept.dname%TYPE;
BEGIN
   DBMS_LOCK.sleep (1);

   SELECT dname
     INTO l_dname
     FROM dept
    WHERE deptno = p_deptno;

   RETURN l_dname;
END;
/

SCOTT@book> select empno, ename, deptno, get_dept(deptno) c20 from emp;
     EMPNO ENAME          DEPTNO C20
---------- ---------- ---------- --------------------
      7369 SMITH              20 RESEARCH
      7499 ALLEN              30 SALES
      7521 WARD               30 SALES
      7566 JONES              20 RESEARCH
      7654 MARTIN             30 SALES
      7698 BLAKE              30 SALES
      7782 CLARK              10 ACCOUNTING
      7788 SCOTT              20 RESEARCH
      7839 KING               10 ACCOUNTING
      7844 TURNER             30 SALES
      7876 ADAMS              20 RESEARCH
      7900 JAMES              30 SALES
      7902 FORD               20 RESEARCH
      7934 MILLER             10 ACCOUNTING
14 rows selected.
Elapsed: 00:00:14.02

--//这样每一次调用都需要1秒。如果改用标量子查询。

SCOTT@book> select empno, ename, deptno, (select get_dept(deptno) from dual )c20 from emp;
     EMPNO ENAME          DEPTNO C20
---------- ---------- ---------- --------------------
      7369 SMITH              20 RESEARCH
      7499 ALLEN              30 SALES
      7521 WARD               30 SALES
      7566 JONES              20 RESEARCH
      7654 MARTIN             30 SALES
      7698 BLAKE              30 SALES
      7782 CLARK              10 ACCOUNTING
      7788 SCOTT              20 RESEARCH
      7839 KING               10 ACCOUNTING
      7844 TURNER             30 SALES
      7876 ADAMS              20 RESEARCH
      7900 JAMES              30 SALES
      7902 FORD               20 RESEARCH
      7934 MILLER             10 ACCOUNTING
14 rows selected.
Elapsed: 00:00:03.01

--//因为标量子查询,缓存了相同的结果,deptno仅仅有3个值,这样需要3秒。自己还真没想到标量子查询有这样效果!!

3. DETERMINISTIC Functions:

--//一般如果在在某个函数定义索引,需要DETERMINISTIC,表示返回结果固定。其实即使不固定,也可以这样定义。
CREATE OR REPLACE FUNCTION get_dept (p_deptno dept.deptno%TYPE)
   RETURN dept.dname%TYPE
   DETERMINISTIC
IS
   l_dname   dept.dname%TYPE;
BEGIN
   DBMS_LOCK.sleep (1);

   SELECT dname
     INTO l_dname
     FROM dept
    WHERE deptno = p_deptno;

   RETURN l_dname;
END;
/

SCOTT@book> select empno, ename, deptno, get_dept(deptno) c20 from emp;
     EMPNO ENAME          DEPTNO C20
---------- ---------- ---------- --------------------
      7369 SMITH              20 RESEARCH
      7499 ALLEN              30 SALES
      7521 WARD               30 SALES
      7566 JONES              20 RESEARCH
      7654 MARTIN             30 SALES
      7698 BLAKE              30 SALES
      7782 CLARK              10 ACCOUNTING
      7788 SCOTT              20 RESEARCH
      7839 KING               10 ACCOUNTING
      7844 TURNER             30 SALES
      7876 ADAMS              20 RESEARCH
      7900 JAMES              30 SALES
      7902 FORD               20 RESEARCH
      7934 MILLER             10 ACCOUNTING
14 rows selected.
Elapsed: 00:00:04.02

--//4秒,为什么呢?仅仅3个值,按照道理应该3秒,而不是4秒,这个问题先放在后面解析。

4.RESULT CACHE
CREATE OR REPLACE FUNCTION get_dept (p_deptno dept.deptno%TYPE)
   RETURN dept.dname%TYPE
   RESULT_CACHE
IS
   l_dname   dept.dname%TYPE;
BEGIN
   DBMS_LOCK.sleep (1);

   SELECT dname
     INTO l_dname
     FROM dept
    WHERE deptno = p_deptno;

   RETURN l_dname;
END;
/

SCOTT@book> select empno, ename, deptno, get_dept(deptno) c20 from emp;
..
14 rows selected.
Elapsed: 00:00:03.01

--//再次执行因为结果缓存了。很快返回。

SCOTT@book> select empno, ename, deptno, get_dept(deptno) dname from emp;
14 rows selected.
Elapsed: 00:00:00.00

5.回到前面,采用 DETERMINISTIC Functions为什么是4秒呢?

--//重新定义函数
CREATE OR REPLACE FUNCTION get_dept (p_deptno dept.deptno%TYPE)
   RETURN dept.dname%TYPE
   DETERMINISTIC
IS
   l_dname   dept.dname%TYPE;
BEGIN
   DBMS_LOCK.sleep (1);

   SELECT dname
     INTO l_dname
     FROM dept
    WHERE deptno = p_deptno;

   RETURN l_dname;
END;
/

--//如果仔细阅读原文:
As we can see here that execution time went down to near 4 seconds which was originally near 14 seconds. We can notice
that using scalar sub-query was little faster because Deterministic cache is maintained per fetch instead of total SQL
execution. I prefer to modify my function to deterministic only when I know that this function is used in various SQLs
and all SQL can not be modified (or required alot of effort) with scalar sub-query.

SCOTT@book> show array
arraysize 200
--//仔细看就明白了,实际与array大小有关,这样就很容易理解为什么是4秒,因为返回第1行是单独1个逻辑读。

--如果我设置array=2
20          1
30 30       1
20 30       2
30 10       2
20 10       2
30 20       2
30 20       2
10          1
--//这样13秒验证是否正确。

SCOTT@book> set array 2
SCOTT@book> select empno, ename, deptno, get_dept(deptno) c20 from emp;
14 rows selected.
Elapsed: 00:00:13.02

--//如果我设置array=3
20           1
30 30 20     2
30 30 10     2
20 10 30     3
20 30 20     2
10           1
--//这样11秒验证是否正确。
SCOTT@book> set array 3
SCOTT@book> select empno, ename, deptno, get_dept(deptno) c20 from emp;
...
14 rows selected.
Elapsed: 00:00:11.02

--//如果我设置array=4
set array 4
20              1
30 30 20 30     2
30 10 20 10     3
30 20 30 20     2
10              1
--//应该是9秒:
SCOTT@book> select empno, ename, deptno, get_dept(deptno) c20 from emp ;
14 rows selected.
Elapsed: 00:00:09.01

--//如果你仔细观察输出时的停顿,可以发现是4条4条输出的,这里非常不好理解!!
--//但是如果改用标量子查询,结果就是3秒。

SCOTT@book> select empno, ename, deptno, (select get_dept(deptno) from dual )c20 from emp;
14 rows selected.
Elapsed: 00:00:03.01

--//还有1个简单的验证方法就是排序输出看看。
SCOTT@book> select empno, ename, deptno, get_dept(deptno) c20 from emp order by deptno;
14 rows selected.
Elapsed: 00:00:03.01

--//这样数据先进入排序区,arraysize大小就变得没有关系,有回到3秒。
--//其中细节可以自己体会。

--//这个测试终于让我明白oracle一些逻辑读细节。

总结
1.oracle 逻辑读不能跨块。
2.oracle 逻辑读第1行作为一个逻辑读,接着读取数量array作为第2个逻辑读。
3.做一个特殊情况:
SCOTT@book> create table empx as select * from emp order by deptno;
Table created.

SCOTT@book> select * from empx ;
     EMPNO ENAME      JOB              MGR HIREDATE                   SAL       COMM     DEPTNO
---------- ---------- --------- ---------- ------------------- ---------- ---------- ----------
      7782 CLARK      MANAGER         7839 1981-06-09 00:00:00       2450                    10
      7839 KING       PRESIDENT            1981-11-17 00:00:00       5000                    10
      7934 MILLER     CLERK           7782 1982-01-23 00:00:00       1300                    10
      7566 JONES      MANAGER         7839 1981-04-02 00:00:00       2975                    20
      7902 FORD       ANALYST         7566 1981-12-03 00:00:00       3000                    20
      7876 ADAMS      CLERK           7788 1987-05-23 00:00:00       1100                    20
      7369 SMITH      CLERK           7902 1980-12-17 00:00:00        800                    20
      7788 SCOTT      ANALYST         7566 1987-04-19 00:00:00       3000                    20
      7521 WARD       SALESMAN        7698 1981-02-22 00:00:00       1250        500         30
      7844 TURNER     SALESMAN        7698 1981-09-08 00:00:00       1500          0         30
      7499 ALLEN      SALESMAN        7698 1981-02-20 00:00:00       1600        300         30
      7900 JAMES      CLERK           7698 1981-12-03 00:00:00        950                    30
      7698 BLAKE      MANAGER         7839 1981-05-01 00:00:00       2850                    30
      7654 MARTIN     SALESMAN        7698 1981-09-28 00:00:00       1250       1400         30
14 rows selected.

SCOTT@book> set array 7
SCOTT@book> select empno, ename, deptno, get_dept(deptno) c20 from empx ;
     EMPNO ENAME          DEPTNO C20
---------- ---------- ---------- --------------------
      7782 CLARK              10 ACCOUNTING
      7839 KING               10 ACCOUNTING
      7934 MILLER             10 ACCOUNTING
      7566 JONES              20 RESEARCH
      7902 FORD               20 RESEARCH
      7876 ADAMS              20 RESEARCH
      7369 SMITH              20 RESEARCH
      7788 SCOTT              20 RESEARCH
      7521 WARD               30 SALES
      7844 TURNER             30 SALES
      7499 ALLEN              30 SALES
      7900 JAMES              30 SALES
      7698 BLAKE              30 SALES
      7654 MARTIN             30 SALES
14 rows selected.
Elapsed: 00:00:04.02

10                    1
10 10 20 20 20 20 20  2
30 30 30 30 30 30     1

--//如果设置6,多2秒。
SCOTT@book> set array 6
SCOTT@book> select empno, ename, deptno, get_dept(deptno) c20 from empx ;
     EMPNO ENAME          DEPTNO C20
---------- ---------- ---------- --------------------
      7782 CLARK              10 ACCOUNTING
      7839 KING               10 ACCOUNTING
      7934 MILLER             10 ACCOUNTING
      7566 JONES              20 RESEARCH
      7902 FORD               20 RESEARCH
      7876 ADAMS              20 RESEARCH
      7369 SMITH              20 RESEARCH
      7788 SCOTT              20 RESEARCH
      7521 WARD               30 SALES
      7844 TURNER             30 SALES
      7499 ALLEN              30 SALES
      7900 JAMES              30 SALES
      7698 BLAKE              30 SALES
      7654 MARTIN             30 SALES
14 rows selected.
Elapsed: 00:00:06.01

10                    1
10 10 20 20 20 20     2
20 30 30 30 30 30     2
30                    1

--//OK正确。

4.不过我自己还是有一点不明白的,oracle的输出是按照array定义的数量输出的,不知道为什么?
  按照我的理解输出应该是1,array数量-1,array数量...,有谁能给出合理解析呢?

目录
相关文章
|
数据库管理
[20180619]fsc表示什么.txt
[20180619]fsc表示什么.txt --//上个星期做sys.bootstrap$恢复时,执行verify时出现类似错误. BBED> verify dba 4,547 DBVERIFY - Verification starting FILE = /mnt/ramdisk/book/users01.
1139 0
|
关系型数据库 Oracle 开发工具
[20180430]ASICC 7f.txt
[20180430]ASICC 7f.txt --//今天从网上copy一个脚本,执行老是报错,提示ORA-00911: invalid character. --//检查才发现里面含有1个ASCII 7F,从文本根本看不出来,浪费了许多时间做一个记录.
1039 0
|
SQL 测试技术 Perl
20180205]为什么是3秒.txt
[20180205]为什么是3秒.txt http://blog.itpub.net/267265/viewspace-2138042/ 1.环境: SCOTT@book> @ &r/ver1 PORT_STRING                   ...
1012 0
|
测试技术 数据库 数据库管理
[20180202]脏块写盘问题.txt
[20180202]脏块写盘问题.txt --//别人问的问题,如果要写脏块的scn号比块小,脏块会写盘吗? --//感觉这种情况不可能出现,脏块的scn应该是最高的,即使rac环境,也不会出现这种情况.
968 0
|
SQL 索引
[20180118]tstats的问题.txt
[20180118]tstats的问题.txt --//关于使用tstats收集处理统计信息,可以看链接http://blog.itpub.net/267265/viewspace-1987839/ TSTATS in a Nutshell P97 The re...
857 0
|
SQL
[20170825]2038.txt
[20170825]2038.txt --//昨天帮别人解决电脑问题联想到的,对方是主机电池没电,导致启动XP黑屏,重新设置正确的时间后ok. --//这样我想到除了2000年外的2038年的问题,大家知道类unix的os系统计时从'1970/1/1'开始的秒数.
1075 0
|
Linux 关系型数据库 Oracle
[20170731]rhgb表示什么.txt
[20170731]rhgb表示什么.txt --//一般我安装好linux服务器,我个性习惯修改grub.conf文件 # ls -l  /boot/grub/grub.
1073 0
|
Oracle 关系型数据库 数据库管理
[20170530]写一致问题.txt
[20170530]写一致问题.txt --//oracle 通过undo等保持读一致性. --//假如一个回话修改1条记录 y字段+1,另外的回话也修改相同记录,y字段+1.
737 0
|
数据库管理
[20161128]关于Little Enddian.txt
[20161128]关于Little Enddian.txt Intel字节顺序称为"Little-Endian",反之Sun,还有网络上采用标准是"Big-Endian"。
840 0