码迷,mamicode.com
首页 > 其他好文 > 详细

表的设计

时间:2015-04-11 16:02:22      阅读:139      评论:0      收藏:0      [点我收藏+]

标签:

普通表

  1. 优点:
    1. 语法简单
    2. 适合大部分情况
  2. 缺点:
    1. 表更新日志开销大--》可以适当选择全局表
      grant all on dba_objects to swat;
      grant all on v_$statname to swat;
      grant all on v_$mystat to swat;
      grant create any view to swat;
      conn swat/swat
      SELECT a.name, b.value from v$statname a, v$mystat b where a.statistic#=b.statistic# and a.name=redo size;
      create or replace view v_redo as SELECT a.name, b.value from v$statname a, v$mystat b where a.statistic#=b.statistic# and a.name=redo size;
      create table t as select * from dba_objects;
      NAME                                      VALUE
      ---------------------------------------------------------------- ----------
      redo size                                  12204
      
      SQL> delete from t;
      
      72493 rows deleted.
      
      SQL> select * from v_redo;
      
      NAME                                      VALUE
      ---------------------------------------------------------------- ----------
      redo size                               28869556
      SQL> select (28869556-12204)/1024/1024||M redo from dual;
      
      REDO
      ---------------------
      27.52051544189453125M
      SQL> insert into t select * from dba_objects;
      
      72494 rows created.
      
      SQL> select * from v_redo;
      
      NAME                                      VALUE
      ---------------------------------------------------------------- ----------
      redo size                               37166892
      SQL> select (37166892-28869556)/1024/1024||M redo from dual;
      
      REDO
      --------------------
      7.91295623779296875M
      SQL> update t set object_id=rownum;
      
      72494 rows updated.
      
      SQL> select * from v_redo;
      
      NAME                                      VALUE
      ---------------------------------------------------------------- ----------
      redo size                               57257080
      SQL> select (57257080-37166892)/1024/1024||M redo from dual;
      
      REDO
      ----------------------
      19.159496307373046875M
      
      对72494条记录删除产生27.5M > 更新产生19.2M > 插入产生7.9M。 对于全局临时表来说这个数字分别是:22.8m 12.8M 0.43M
    2. delete无法释放空间--》可以考虑全局临时表和分区表,Truncate和Delete的区别。 Truncate 是DDL不能加where字句,可以用分区表间接利用Truncate好处。
      在sys用户下运行:
      @$ORACLE_HOME/sqlplus/admin/plustrce.sql
      grant plustrace to swat;
      conn swat/swat
      set autotrace on
      select count(*) from t;

      Statistics
      ----------------------------------------------------------
             1037  consistent gets

      delete from t;
      select count(*) from t;

      Statistics
      ----------------------------------------------------------
             1037  consistent gets

      truncate table t;

      select count(*) from t;

      | Id  | Operation       | Name | Rows  | Cost (%CPU)| Time      |
      -------------------------------------------------------------------
      |   0 | SELECT STATEMENT   |      |    1 |    2   (0)| 00:00:01 |   ---上两次选择cost均为288.时间为4秒
      |   1 |  SORT AGGREGATE    |      |    1 |           |      |
      |   2 |   TABLE ACCESS FULL| T      |    1 |    2   (0)| 00:00:01 |

      Statistics
      ----------------------------------------------------------
           20  recursive calls
            1  db block gets --上面两次select语句以上项是0,所以没有拷贝过来
           10  consistent gets

    3. 表太大检索较慢--》可以选择分区表或者建立索引,索引本身是双刃剑,既可以提高性能,也会给数据库带来负担。
    4. 索引回表读开销大--》可以选择索引组织表
      select * from t where object_id<=10;
      4  consistent gets
      -----------------------------------------------------------------------------------------
      | Id  | Operation                                       | Name          | Rows| Bytes | Cost (%CPU)| Time    |
      -----------------------------------------------------------------------------------------
      |   0 | SELECT STATEMENT                                   |              |     9 |  1863 |     2   (0)| 00:00:01 |
      |   1 |  TABLE ACCESS BY INDEX ROWID            |T           |     9 |  1863 |     2   (0)| 00:00:01 |
      |*  2 |   INDEX RANGE SCAN                                   | IDX_T_OID   |     9 |               |     1   (0)| 00:00:01 |
      -----------------------------------------------------------------------------------------
      select object_id from t where object_id<=10;
      2  consistent gets
      | Id  | Operation     | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
      ------------------------------------------------------------------------------
      |   0 | SELECT STATEMENT |         |       9 |     117 |       1   (0)| 00:00:01 |
      |*  1 |  INDEX RANGE SCAN| IDX_T_OID |       9 |     117 |       1   (0)| 00:00:01 |
    5. 即使有序插入,也难有序读出--》可以选择聚簇表: 一般读取是无序的,需要使用order by来排序,这样就增加了一块sort内存,增加了开销。为了避开orderby有两种方法
      1. 用order by的排序列建索引。
      2. 将普通表改造为聚簇表。

全局临时表:应用场景:为了数据安全和数据保护的目的,对表的日志是不可避免;然而,实际情况中有些应用对于某些操作是不要求恢复的,如:运算中的临时中间结果集。

  1. 优点:
    1. 高效删除
    2. 产生日志少
    3. 不同session独立,不产生锁
  2. 缺点:
    1. 语法特别
    2. 数据无法得到有效保护
  3. 类型:
    1. 基于session:退出删除数据也不产生reod信息
    2. 基于事务:Commit是删除数据,但是不会对这个删除动作产生redo信息。
      会话级别的全局临时表
      create global temporary table t on COMMIT PRESERVE ROWS as select * from dba_objects where 1=2;
      select table_name,temporary,duration from user_tables where table_name=T;
      select * from v_redo;
       insert into t select * from dba_objects;
      select * from v_redo;
      产生redo 0.43M;
      update t set object_id=rownum;
      产生redo 12.8M;
      delete from t;
      产生redo 22.8M;
      提交,退出sql,然后重新进入:可以看到全部数据被删除。
      SQL> conn swat/swat
      Connected.
      SQL> select count(*) from t;
      
        COUNT(*)
      ----------
           0
      事务级别的全局临时表
      create global temporary table tt on COMMIT DELETE ROWS as select * from dba_objects where 1=2;
      select table_name,temporary,duration from user_tables where table_name=TT;
      insert into tt select * from dba_objects;
      产生0.43M redo
      update tt set object_id=rownum;
      产生redo 12.8M;
      delete from tt;
      产生redo 22.8M;
      提交以后清零
      SQL> select count(*) from tt;
      
        COUNT(*)
      ----------
           72495
      
      SQL> commit;
      
      Commit complete.
      
      SQL> select count(*) from tt;
      
        COUNT(*)
      ----------
           0
  4. DML操作日志产生情况:
    1. 插入
    2. 更新
    3. 删除
  5. 重要实用特性:
    1. 高效删除记录:基于会话的情况是主流少数应用非常复杂,执行中间要求对表清零,这个时候可以使用基于事务的,也就是说用commit代替delete以避免产生redo。
      1. 基于session:退出session时删除表数据。
      2. 基于事务:commit或突出session删除表数据。
    2. 不同会话独立,这里只说明基于会话的情况:在用不同会话连进去去操作同一个临时表,会发现它神奇的独立于其它的会话。这个特性结合上一个高效删除的特性,会给我们的应用带来极大的方便。

分区表

  1. 分区表的原理:
    1. 原理:不同的分区在不同的segment上
    2. 类型:
      1. range分区:最常用的就是时间分区。
        create table range_pt(id number,month date,code number,contents varchar2(4000)) PARTITION BY RANGE(month)(partition p1 values less than (TO_DATE(2012-02-01,YYYY-MM-DD)),  --partition by range是关键字
        partition p2 values less than (TO_DATE(2012-03-01,YYYY-MM-DD)),
        partition p3 values less than (TO_DATE(2012-04-01,YYYY-MM-DD)),
        partition p4 values less than (TO_DATE(2012-05-01,YYYY-MM-DD)),
        partition p5 values less than (TO_DATE(2012-06-01,YYYY-MM-DD)),
        partition p6 values less than (TO_DATE(2012-07-01,YYYY-MM-DD)),
        partition p7 values less than (TO_DATE(2012-08-01,YYYY-MM-DD)),
        partition p8 values less than (TO_DATE(2012-09-01,YYYY-MM-DD)),
        partition p9 values less than (TO_DATE(2012-10-01,YYYY-MM-DD)),
        partition p10 values less than (TO_DATE(2012-11-01,YYYY-MM-DD)),
        partition p11 values less than (TO_DATE(2012-12-01,YYYY-MM-DD)),
        partition p12 values less than (TO_DATE(2013-01-01,YYYY-MM-DD)),
        partition p_max VALUES LESS THAN (MAXVALUE) --所有不属于上面12个区的全部落这个区,避免出错。
        )
        ;
        
        insert into range_pt (id,month,code,contents)
            select rownum,
                to_date(to_char(sysdate-365,J)+TRUNC(DBMS_RANDOM.VALUE(0,365)),J),
                ceil(dbms_random.value(590,599)),
                rpad(*,400,*)
            from dual
        connect by rownum <=100000;
        
        commit;
      2. list分区
        create table list_pt (id number,month date,code number,contents varchar2(4000))
            PARTITION BY LIST (CODE)   --这里指明这是一个list分区表以列值分区
            (
                PARTITION P_591 VALUES (591),  --这里并不是说取值只能写一个,也可以写多个如:(591,592,593)
                PARTITION P_592 VALUES (592),  --分区可以落在不同的表空间,如果不写就是默认表空间。
                PARTITION P_593 VALUES (593),
                PARTITION P_594 VALUES (594),
                PARTITION P_595 VALUES (595),
                PARTITION P_596 VALUES (596),
                PARTITION P_597 VALUES (597),
                PARTITION P_598 VALUES (598),
                PARTITION P_599 VALUES (599),
                PARTITION P_other VALUES (DEFAULT) --表示剩下的数据全部落入这个分区。
            )
        ;
        
        insert into list_pt(id,month,code,contents)
                select rownum,
                        to_date(to_char(sysdate-365,J)+TRUNC(dbms_random.value(0,365)),J), 
                        ceil(dbms_random.value(590,599)),
                        rpad(*,400,*)
                from dual
        connect by rownum<=100000;
        commit;
      3. hash分区
        create table hash_pt (id number,month date,code number,contents varchar2(4000))
                partition by hash(month)
                partitions 12; --没有指定表分区名,只指定了个数。这个个数尽量是偶数。可以指定表空间:store in (ts1,ts2…ts12)
        
        insert into hash_pt(id,month,code,contents)
        select rownum,
                to_date(to_char(sysdate-365,J)+trunc(dbms_random.value(0,365)),J),
                ceil(dbms_random.value(590,599)),
                rpad(*,400,*)
        from dual
        connect by rownum<=100000;
        commit;
      4. 组合分区
  2. 优点/重要特性:
    1. 有效的分区消除:将一年分为12个月,那么你只需访问特定的月。就不用去访问另外的11个月。
    2. 高效的记录清理:如果想删除某区数据,可以用truncate来清空,避免了delete删除慢,高水位不释放的问题。
    3. 高效的记录转移:
  3. 分区索引:
    1. 全局索引:
    2. 局部索引:
  4. 分区表相关易错点:
    1. 有分区用不到:
    2. 分区索引失效:
    3. 分区索引效率低下:
  5. 缺点
    1. 语法复杂
    2. 分区过多对系统有一定影响

索引组织表

  1. 优点:
    1. 表就是索引,避免回表
  2. 缺点:
    1. 语法复杂
    2. 更新开销大

簇表

  1. 优点:
    1. 可以减少或避免排序
  2. 缺点:
    1. 语法复杂
    2. 表更新开销大

表的设计

标签:

原文地址:http://www.cnblogs.com/alexweng/p/4417695.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!