大分区表数据切换的解决方案

1、问题描述

大表mv_auc上有hash分区,3个索引多用户不定时查询;如何使新旧数据快速交换,并且不影响查询性能

 

2、问题分析

可以将每天的数据导入到一个唯一命名的表,比如T20090708,然后通过建立一个视图来屏蔽底层表的变化(通过存储过程的动态sql来实现视图定义的动态变化),当每天凌晨我们把数据导入表中之后,即执行vw_shift存储过程来改变vw_test视图的定义,这样就会使得查询业务平稳切换,完全不会影响到业务,并且查询性能也不会受到影响。

 

3、方案验证

实验方案的设计:创建两张表,一张为大表t20090708,共3670016行;一张为小表t20090709,共896行。之所以将第一张表设计得如此之大,目的就是为了使查询操作的时间尽量长,这样可以保证在这个查询操作执行的过程中我们有充裕的时间进行视图定义的切换,同时这样的设计也可以验证该方案完全不会影响业务操作。

实验旨在验证所提出的大分区表数据切换的可操作性,通过set timing on为命令提示符前加上时间线索,所显示的时间与命令的执行时间基本一致,三个会话交错执行,从时间上可以一目了然地看出它们的执行轨迹。

 

会话1

22:46:43 SQL> select count(*) from t20090708;

 

  COUNT(*)

----------

   3670016

 

22:47:27 SQL> select count(*) from t20090709;

 

  COUNT(*)

----------

       896

 

22:47:42 SQL> create or replace view vw_test as select * from t20090708;

 

视图已创建。

 

22:48:00 SQL> create or replace procedure vw_shift as

22:48:10   2  curr_date varchar2(10);

22:48:10   3  vw_str varchar2(100);

22:48:10   4  begin

22:48:10   5    select to_char(sysdate,'yyyymmdd') into curr_date from dual;

22:48:10   6    vw_str := ' create or replace view vw_test as select * from t'||

curr_date;

22:48:10   7    execute immediate vw_str;

22:48:10   8  end;

22:48:13   9  /

 

过程已创建。

 

22:51:12 SQL> exec vw_shift

 

PL/SQL 过程已成功完成。

 

会话2

22:50:04 SQL> set autot on

22:50:09 SQL> alter system flush shared_pool;

 

系统已更改。

 

22:50:34 SQL> select count(*) from vw_test;

 

  COUNT(*)

----------

   3670016

 

执行计划

----------------------------------------------------------

Plan hash value: 1428396537

------------------------------------------------------------------------

| Id  | Operation          | Name      | Rows  | Cost (%CPU)| Time     |

------------------------------------------------------------------------

|   0 | SELECT STATEMENT   |           |     1 |     5   (0)| 00:00:01 |

|   1 |  SORT AGGREGATE    |           |     1 |            |          |

|   2 |   TABLE ACCESS FULL| T20090709 |   896 |     5   (0)| 00:00:01 |

------------------------------------------------------------------------

 

Note

-----

   - dynamic sampling used for this statement

 

这里要注意的是,会话2在查询vw_test视图的时候视图定义还没有修改,所以上面查询的是基表t20090708,结果为3670016。不过,执行计划中所显示的基表为t20090709,这是由于Oracle在开始执行查询操作的时候会首先将视图名称转化为视图的定义,然后才执行查询操作,实际上这时候的查询已经与视图毫无关系了,在查询操作执行期间,我们可以改变视图的定义,从而使得视图指向另一个基表t20090709。而执行计划的生成是在查询操作结束之后进行的,此时视图的定义已经发生变化,因此就出现了真正查询的表与执行计划中显示的表名不相同的情况

 

会话3

22:52:07 SQL> set autot on

22:52:39 SQL> select count(*) from vw_test;

 

  COUNT(*)

----------

       896

 

执行计划

----------------------------------------------------------

Plan hash value: 1428396537

------------------------------------------------------------------------

| Id  | Operation          | Name      | Rows  | Cost (%CPU)| Time     |

------------------------------------------------------------------------

|   0 | SELECT STATEMENT   |           |     1 |     5   (0)| 00:00:01 |

|   1 |  SORT AGGREGATE    |           |     1 |            |          |

|   2 |   TABLE ACCESS FULL| T20090709 |   896 |     5   (0)| 00:00:01 |

------------------------------------------------------------------------

 

Note

-----

   - dynamic sampling used for this statement

 

上面的查询操作是在视图定义改变之后开始执行的,因此,所查询的基表是t20090709,结果为896。同样,执行计划中显示的基表仍然为t20090709

 

接下来验证一下分区表的执行计划是否会受到影响:

SQL> create table t2009(

  2  id number,

  3  EMPNO NUMBER(4),

  4  ENAME                                              VARCHAR2(10),

  5  JOB                                                VARCHAR2(9),

  6  MGR                                                NUMBER(4),

  7  HIREDATE                                           DATE,

  8  SAL                                                NUMBER(7,2),

  9  COMM                                               NUMBER(7,2),

 10  DEPTNO                                             NUMBER(2)

 11  )

 12  PARTITION BY HASH(id)

 13  (PARTITION p1 ,

 14   PARTITION p2,

 15   PARTITION p3,

 16   PARTITION p4);

 

表已创建。

 

SQL> insert into t2009 select * from t20090709;

 

已创建896行。

 

SQL> commit;

 

提交完成。

 

SQL> create or replace view vw_test as select * from t2009;

 

视图已创建。

 

SQL> create index idx_empno on t2009(empno);

 

索引已创建。

 

SQL> select * from vw_test where empno=8888;

 

 

执行计划

----------------------------------------------------------

Plan hash value: 1069650138

 

--------------------------------------------------------------------------------

 

--------------------------------

 

| Id  | Operation                          | Name      | Rows  | Bytes | Cost (%

 

CPU)| Time     | Pstart| Pstop |

 

--------------------------------------------------------------------------------

 

--------------------------------

 

|   0 | SELECT STATEMENT                   |           |     1 |    43 |     2

 (0)| 00:00:01 |       |       |

 

|   1 |  TABLE ACCESS BY GLOBAL INDEX ROWID| T2009     |     1 |    43 |     2

 (0)| 00:00:01 | ROWID | ROWID |

 

|*  2 |   INDEX RANGE SCAN                 | IDX_EMPNO |     1 |       |     1

 (0)| 00:00:01 |       |       |

 

--------------------------------------------------------------------------------

 

--------------------------------

 

 

Predicate Information (identified by operation id):

---------------------------------------------------

 

   2 - access("EMPNO"=8888)

 

 

统计信息

----------------------------------------------------------

        223  recursive calls

          0  db block gets

         42  consistent gets

          0  physical reads

          0  redo size

        854  bytes sent via SQL*Net to client

        385  bytes received via SQL*Net from client

          2  SQL*Net roundtrips to/from client

          2  sorts (memory)

          0  sorts (disk)

          1  rows processed

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/15203236/viewspace-610709/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/15203236/viewspace-610709/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值