zoukankan      html  css  js  c++  java
  • oracle慎用基于on commit刷新物化视图的方式(二)

     

    oracle慎用基于on commit刷新物化视图的方式(二)

    环境模拟

    首先,需要有示例用户SCOTT,以emp表为例子。

    首先是串行下无物化视图的emp表,做update操作的情况,

    16:56:14 SYS@zkm(27)> begin
    16:56:21   2    for i in 1..10000 loop
    16:56:21   3            update scott.emp set sal=9999 where empno=7934;
    16:56:21   4            commit;
    16:56:21   5    end loop;
    16:56:21   6  end ;
    16:56:21   7  /
    
    PL/SQL procedure successfully completed.
    
    Elapsed: 00:00:00.48
    16:56:23 SYS@zkm(27)> begin
    16:56:26   2    for i in 1..10000 loop
    16:56:26   3            update scott.emp set sal=9999 where empno=7934;
    16:56:26   4            commit;
    16:56:26   5    end loop;
    16:56:26   6  end ;
    16:56:26   7  /
    
    PL/SQL procedure successfully completed.
    
    Elapsed: 00:00:00.65
    16:56:27 SYS@zkm(27)> begin
    16:56:28   2    for i in 1..10000 loop
    16:56:28   3            update scott.emp set sal=9999 where empno=7934;
    16:56:28   4            commit;
    16:56:28   5    end loop;
    16:56:28   6  end ;
    16:56:28   7  /
    
    PL/SQL procedure successfully completed.
    
    Elapsed: 00:00:00.65

    然后是串行下有物化视图的emp表,做update操作的情况,

    17:15:23 SYS@zkm(27)> conn scott/oracle
    Connected.
    17:15:32 SCOTT@zkm(27)> create materialized view scott.mv_emp
    17:15:33   2  REFRESH force on commit
    17:15:33   3  as
    17:15:33   4  select * from scott.emp;
    
    Materialized view created.
    
    Elapsed: 00:00:00.55
    17:15:34 SCOTT@zkm(27)> begin
    17:16:06   2    for i in 1..10000 loop
    17:16:06   3            update scott.emp set sal=9999 where empno=7934;
    17:16:06   4            commit;
    17:16:06   5    end loop;
    17:16:06   6  end ;
    17:16:06   7  /
    
    PL/SQL procedure successfully completed.
    
    Elapsed: 00:00:21.73
    17:16:29 SCOTT@zkm(27)> /
    
    PL/SQL procedure successfully completed.
    
    Elapsed: 00:00:21.64
    17:16:53 SCOTT@zkm(27)> /
    
    PL/SQL procedure successfully completed.
    
    Elapsed: 00:00:20.70

    可以看到,有物化视图的情况下,性能下降40多倍。

    更不要说在并行情况下产生行级锁的情况了,几乎会导致业务都瘫痪掉。

    并行下也进行一次模拟看看,开启两个session,sid分别为27和31。

    删除上边的物化视图,

    17:33:58 SCOTT@zkm(27)> drop materialized view scott.mv_emp;
    
    Materialized view dropped.
    
    Elapsed: 00:00:00.50

    为了保证同时运行匿名块,使用crt的command windows功能,将匿名块同时发送到活动的会话里边,

    可以发现,运行时间情况为

    17:34:07 SCOTT@zkm(27)> begin
    17:34:32   2    for i in 1..10000 loop
    17:34:32   3            update scott.emp set sal=9999 where empno=7934;
    17:34:32   4            commit;
    17:34:32   5    end loop;
    17:34:32   6  end ;
    17:34:32   7  /
    
    PL/SQL procedure successfully completed.
    
    Elapsed: 00:00:01.06
    17:34:33 SCOTT@zkm(27)> /
    
    PL/SQL procedure successfully completed.
    
    Elapsed: 00:00:01.12
    17:34:39 SCOTT@zkm(27)> /
    
    PL/SQL procedure successfully completed.
    
    Elapsed: 00:00:01.17
    17:34:43 SCOTT@zkm(27)> 
    
    
    ----------------------------同时sid=31的运行----------------------------- 17:34:16 SCOTT@zkm(31)> begin 17:34:32 2 for i in 1..10000 loop 17:34:32 3 update scott.emp set sal=9999 where empno=7934; 17:34:32 4 commit; 17:34:32 5 end loop; 17:34:32 6 end ; 17:34:32 7 / PL/SQL procedure successfully completed. Elapsed: 00:00:01.13 17:34:33 SCOTT@zkm(31)> / PL/SQL procedure successfully completed. Elapsed: 00:00:01.18 17:34:39 SCOTT@zkm(31)> / PL/SQL procedure successfully completed. Elapsed: 00:00:01.24 17:34:43 SCOTT@zkm(31)>

    相对于串行下,性能稍微下降。

    再试试有物化视图下,并发的执行情况,

    17:40:44 SCOTT@zkm(27)> create materialized view scott.mv_emp
    17:40:44   2  REFRESH force on commit
    17:40:44   3  as
    17:40:44   4  select * from scott.emp;
    
    Materialized view created.
    
    Elapsed: 00:00:00.03
    17:40:47 SCOTT@zkm(27)> begin
    17:41:01   2    for i in 1..10000 loop
    17:41:01   3            update scott.emp set sal=9999 where empno=7934;
    17:41:01   4            commit;
    17:41:01   5    end loop;
    17:41:01   6  end ;
    17:41:01   7  /
    
    PL/SQL procedure successfully completed.
    
    Elapsed: 00:00:44.82
    17:41:46 SCOTT@zkm(27)> /
    
    PL/SQL procedure successfully completed.
    
    Elapsed: 00:00:49.45
    ----------------------------同时sid=31的运行-----------------------------
    17:34:43 SCOTT@zkm(31)> begin 17:41:01 2 for i in 1..10000 loop 17:41:01 3 update scott.emp set sal=9999 where empno=7934; 17:41:01 4 commit; 17:41:01 5 end loop; 17:41:01 6 end ; 17:41:01 7 / PL/SQL procedure successfully completed. Elapsed: 00:00:44.78 17:41:46 SCOTT@zkm(31)> / PL/SQL procedure successfully completed. Elapsed: 00:00:49.32

    性能相对串行下降了将近一倍。

    如果并发的会话是3个或者更多,那么预计性能下降会更大,这里不做测试。

    这里对有物化视图的情况下做个10046,

    08:36:10 SYS@zkm(27)> select value from v$diag_info where name like 'De%';
    
    VALUE
    --------------------------------------------------------------------------------
    /u01/app/oracle/diag/rdbms/zkm/zkm/trace/zkm_ora_6102.trc
    
    Elapsed: 00:00:00.10
    08:37:05 SYS@zkm(27)> alter session set events '10046 trace name context forever,level 12';
    
    Session altered.
    
    Elapsed: 00:00:00.01
    08:37:26 SYS@zkm(27)> update scott.emp set sal=9999 where empno=7934;
    
    1 row updated.
    
    Elapsed: 00:00:00.09
    08:37:59 SYS@zkm(27)> commit;
    
    Commit complete.
    
    Elapsed: 00:00:00.43

    使用tkprof格式化,

    [oracle@oracle ~]$ tkprof /u01/app/oracle/diag/rdbms/zkm/zkm/trace/zkm_ora_6102.trc 10046.trc

    去掉其余无用的递归SQL,剩余信息如下:

    update scott.emp set sal=9999 
    where
     empno=7934
    
    
    call     count       cpu    elapsed       disk      query    current        rows
    ------- ------  -------- ---------- ---------- ---------- ----------  ----------
    Parse        1      0.00       0.00          0          0          0           0
    Execute      1      0.00       0.00          0          1          3           1
    Fetch        0      0.00       0.00          0          0          0           0
    ------- ------  -------- ---------- ---------- ---------- ----------  ----------
    total        2      0.00       0.00          0          1          3           1
    
    Misses in library cache during parse: 1
    Optimizer mode: ALL_ROWS
    Parsing user id: SYS
    Number of plan statistics captured: 1
    
    Rows (1st) Rows (avg) Rows (max)  Row Source Operation
    ---------- ---------- ----------  ---------------------------------------------------
             0          0          0  UPDATE  EMP (cr=1 pr=0 pw=0 time=116 us)
             1          1          1   INDEX UNIQUE SCAN PK_EMP (cr=1 pr=0 pw=0 time=25 us cost=0 size=8 card=1)(object id 87109)
    
    
    Elapsed times include waiting on following events:
      Event waited on                             Times   Max. Wait  Total Waited
      ----------------------------------------   Waited  ----------  ------------
      SQL*Net message to client                       1        0.00          0.00
      SQL*Net message from client                     1       66.12         66.12
    ********************************************************************************
    
    SQL ID: 23wm3kz7rps5y Plan Hash: 0
    
    commit
    
    
    call     count       cpu    elapsed       disk      query    current        rows
    ------- ------  -------- ---------- ---------- ---------- ----------  ----------
    Parse        1      0.00       0.00          0          0          0           0
    Execute      1      0.01       0.03          0          0          2           0
    Fetch        0      0.00       0.00          0          0          0           0
    ------- ------  -------- ---------- ---------- ---------- ----------  ----------
    total        2      0.01       0.03          0          0          2           0
    
    Misses in library cache during parse: 0
    Parsing user id: SYS
    
    Elapsed times include waiting on following events:
      Event waited on                             Times   Max. Wait  Total Waited
      ----------------------------------------   Waited  ----------  ------------
      log file sync                                   1        0.00          0.00
      SQL*Net message to client                       1        0.00          0.00
    ********************************************************************************
    
    
    delete from "SCOTT"."MV_EMP"
    
    
    call     count       cpu    elapsed       disk      query    current        rows
    ------- ------  -------- ---------- ---------- ---------- ----------  ----------
    Parse        1      0.00       0.00          0          0          2           0
    Execute      1      0.00       0.00          0          1         43          14
    Fetch        0      0.00       0.00          0          0          0           0
    ------- ------  -------- ---------- ---------- ---------- ----------  ----------
    total        2      0.00       0.00          0          1         45          14
    
    Misses in library cache during parse: 1
    Optimizer mode: ALL_ROWS
    Parsing user id: 83     (recursive depth: 1)
    Number of plan statistics captured: 1
    
    Rows (1st) Rows (avg) Rows (max)  Row Source Operation
    ---------- ---------- ----------  ---------------------------------------------------
             0          0          0  DELETE  MV_EMP (cr=1 pr=0 pw=0 time=490 us)
            14         14         14   INDEX FULL SCAN PK_EMP1 (cr=1 pr=0 pw=0 time=7 us cost=1 size=56 card=14)(object id 96640)
    
    ********************************************************************************
    
    
    INSERT /*+  */ INTO "SCOTT"."MV_EMP"("EMPNO","ENAME","JOB","MGR","HIREDATE",
      "SAL","COMM","DEPTNO") SELECT "EMP"."EMPNO","EMP"."ENAME","EMP"."JOB",
      "EMP"."MGR","EMP"."HIREDATE","EMP"."SAL","EMP"."COMM","EMP"."DEPTNO" FROM 
      "SCOTT"."EMP" "EMP"
    
    
    call     count       cpu    elapsed       disk      query    current        rows
    ------- ------  -------- ---------- ---------- ---------- ----------  ----------
    Parse        1      0.00       0.00          0          0          2           0
    Execute      1      0.00       0.00          0          7         31          14
    Fetch        0      0.00       0.00          0          0          0           0
    ------- ------  -------- ---------- ---------- ---------- ----------  ----------
    total        2      0.00       0.00          0          7         33          14
    
    Misses in library cache during parse: 1
    Optimizer mode: ALL_ROWS
    Parsing user id: 83     (recursive depth: 1)
    Number of plan statistics captured: 1
    
    Rows (1st) Rows (avg) Rows (max)  Row Source Operation
    ---------- ---------- ----------  ---------------------------------------------------
             0          0          0  LOAD TABLE CONVENTIONAL  (cr=7 pr=0 pw=0 time=211 us)
            14         14         14   TABLE ACCESS FULL EMP (cr=6 pr=0 pw=0 time=69 us cost=3 size=546 card=14)
    
    ********************************************************************************

    这里可以总结以下几点,在无物化视图日志的情况下,on commit方式同步刷新的物化视图在dml并commit的情况下:

    1. 基表(emp)的所有dml操作,只要不提交并不会触发去更新对应的物化视图(mv_emp)。
    2. 提交之后,会先直接删除整张物化视图(trc中有“delete from "SCOTT"."MV_EMP")
    3. 删除整张物化视图的数据后,进行insert操作。

    注意一点,上述的全部步骤均会对应产生TX锁,并且第2步的影响最大因为是直接delete掉全部的行。

    另外,insert部分有个明显的“hint”标志/*+ */,我在这次的生产事故中的awr也有同样看到。

      

    也难怪,一次基表的dml会这么多锁,并发差也正常。

    类似这类方式创建的物化视图,适用于dml相对少并且不是特别重要的表上。

    至于存在物化视图可以快速刷新的情况,这个就不在做实验了。

    日志激增问题

    在第一篇中,问题出现时候明显还有一个问题,那就是归档目录爆了。

    查询日志切换频率也可以看到日志从个位数变为三位数。

    这里也探究一下,删除物化视图,

    09:08:17 SYS@zkm(27)> drop materialized view scott.mv_emp;
    
    Materialized view dropped.
    
    Elapsed: 00:00:00.56

    创建视图v_redo_size作为查询会话产生的日志量,

    14:10:47 SYS@zkm(28)> create or replace view v_redo_size as
    14:11:04   2  select a.name,b.value
    14:11:04   3  from v$statname a,v$mystat b
    14:11:04   4  where a.statistic#=b.statistic#
    14:11:04   5  and a.name='redo size';
    
    View created.
    
    Elapsed: 00:00:00.10

    运行update之前先查询该视图,接着运行update,在查询视图,两次的值相减就是会话产生的redo量。

    14:11:13 SYS@zkm(28)> col name for a15
    14:11:19 SYS@zkm(28)> select * from v_redo_size;
    
    NAME                 VALUE
    --------------- ----------
    redo size            10940
    
    14:20:29 SYS@zkm(28)> begin
    14:20:34   2    for i in 1..10000 loop
    14:20:34   3            update scott.emp set sal=9999 where empno=7934;
    14:20:34   4            commit;
    14:20:34   5    end loop;
    14:20:34   6  end ;
    14:20:34   7  /
    
    PL/SQL procedure successfully completed.
    
    Elapsed: 00:00:01.15
    
    14:20:36 SYS@zkm(28)> select * from v_redo_size;
    
    NAME                 VALUE
    --------------- ----------
    redo size          5406192
    
    Elapsed: 00:00:00.00
    14:20:41 SYS@zkm(28)> select (5406192-10940)/1024 kb from dual;
    
            KB
    ----------
    5268.80078
    
    Elapsed: 00:00:00.02

    可以看到日志量差不多为5M,创建物化视图,

    14:22:47 SCOTT@zkm(27)> create materialized view scott.mv_emp
    14:22:48   2  REFRESH force on commit
    14:22:48   3  as
    14:22:48   4  select * from scott.emp;
    
    Materialized view created.
    
    Elapsed: 00:00:00.42

    再试运行匿名块,

    14:22:30 SYS@zkm(28)> select * from v_redo_size;
    
    NAME                 VALUE
    --------------- ----------
    redo size         10757024
    
    Elapsed: 00:00:00.00
    14:22:58 SYS@zkm(28)> begin
    14:23:07   2    for i in 1..10000 loop
    14:23:07   3            update scott.emp set sal=9999 where empno=7934;
    14:23:07   4            commit;
    14:23:07   5    end loop;
    14:23:07   6  end ;
    14:23:07   7  /
    
    PL/SQL procedure successfully completed.
    
    Elapsed: 00:00:22.28
    14:23:31 SYS@zkm(28)> select * from v_redo_size;
    
    NAME                 VALUE
    --------------- ----------
    redo size        177995832
    
    Elapsed: 00:00:00.00
    14:23:33 SYS@zkm(28)> select (177995832-10757024)/1024 kb from dual;
    
            KB
    ----------
    163319.148
    
    Elapsed: 00:00:00.00

    产生日志量差不多是163M,多这么多也难怪归档会爆掉。

    这估计还受基表字段数量的影响,字段要是再多一点,估计redo量还更大。

    至此,完毕!!

  • 相关阅读:
    Django数据库查询优化-事务-图书管理系统的搭建
    模型层字段-多表查询-神奇的双下划线查询-F,Q查询
    Django的View(视图)-settings源码的解析-模板层-模板语法
    Django路由层与视图层
    Django框架的前奏(安装及介绍)
    面向对象的三大特性
    一,类的初识
    一,对象初识
    装饰器
    闭包
  • 原文地址:https://www.cnblogs.com/PiscesCanon/p/13518549.html
Copyright © 2011-2022 走看看