zoukankan      html  css  js  c++  java
  • 【转】浅谈truncate的使用

    delete 操作不会改变表的高水标记,因此如果我们对一个表插入1000万条数据,然后再回滚(对insert操作做回滚相当于相应地做delete操作),会使表的高水标记增长得很高,这时虽然我们操作的表依然是一个空表,但是查询它却会读惊人数量的内存块,实验如下:
    ETL@RACTEST> create table test_table (a number);

    Table created.

    Elapsed: 00:00:00.01
    ETL@RACTEST> set autotrace traceonly statistics;
    ETL@RACTEST> select * from test_table;

    no rows selected

    Elapsed: 00:00:00.00

    Statistics
    ----------------------------------------------------------
     

           24  recursive calls
              0  db block gets
              7  consistent gets
              0  physical reads
              0  redo size
            318  bytes sent via SQL*Net to client
            453  bytes received via SQL*Net from client
              1  SQL*Net roundtrips to/from client
              0  sorts (memory)
              0  sorts (disk)
              0  rows processed
    可以看到查询这个空表读了7个内存块。然后我们向表中插入1000万条数据后再回滚:
    insert into test_table select level from dual connect by level<=10000000;

    10000000 rows created.

    Elapsed: 00:00:58.38
    ETL@RACTEST> rollback;

    Rollback complete.

    Elapsed: 00:00:01.15

    ETL@RACTEST> set autotrace traceonly statistics;
    ETL@RACTEST> select * from test_table;

    no rows selected

    Elapsed: 00:00:00.14

    Statistics
    ----------------------------------------------------------
            283  recursive calls
              1  db block gets
          15463  consistent gets
              0  physical reads
            176  redo size
            318  bytes sent via SQL*Net to client
            453  bytes received via SQL*Net from client
              1  SQL*Net roundtrips to/from client
              4  sorts (memory)
              0  sorts (disk)
              0  rows processed
    可以看到,同样是读一个空表,但是却做了15463(consistent gets)+1(db block gets)个逻辑读,可见delete操作不会修改表的高水标记。并且delete操作也很耗费时间,因此我们通常在想清空一个表的数据时用truncate来替代delete。truncate会以一种快速的方式清空表,只产生很少的日志信息,并且会将高水标记清零。例如:
    ETL@RACTEST> insert into test_table select level from dual connect by level<=10000000;

    10000000 rows created.

    Elapsed: 00:00:32.45
    ETL@RACTEST> commit;

    Commit complete.

    Elapsed: 00:00:00.02
    ETL@RACTEST> truncate table test_table;

    Table truncated.

    Elapsed: 00:00:29.52
    ETL@RACTEST> set autotrace traceonly statistics;
    ETL@RACTEST> select * from test_table;

    no rows selected

    Elapsed: 00:00:00.00

    Statistics
    ----------------------------------------------------------
              1  recursive calls
              1  db block gets
              6  consistent gets
              0  physical reads
             96  redo size
            318  bytes sent via SQL*Net to client
            453  bytes received via SQL*Net from client
              1  SQL*Net roundtrips to/from client
              0  sorts (memory)
              0  sorts (disk)
              0  rows processed
    truncate后再查询只做了7个逻辑读,也就是读了7个内存块。
    但是truncate操作有一个限制,例如B表有一个外键参照A表的一个字段,那么truncate A表Oracle就会报错,实验如下:
    create table ttt1 (a number,primary key(a));

    Table created.

    Elapsed: 00:00:00.02
    ETL@RACTEST> insert into ttt1 select level from dual connect by level<=10;

    10 rows created.

    Elapsed: 00:00:00.02
    ETL@RACTEST> commit;

    Commit complete.

    Elapsed: 00:00:00.00
    ETL@RACTEST> select * from ttt1;

             A
    ----------
             1
             2
             3
             4
             5
             6
             7
             8
             9
            10

    10 rows selected.

    Elapsed: 00:00:00.00
    ETL@RACTEST> create table ttt2 (a number,constraint fk_ttt2_a foreign key(a) references ttt1(a));

    Table created.
    这时ttt2表的a字段参照了ttt1表的a字段,我如果用delete操作清空ttt1表的值是可以的,因为ttt2表没有数据,删除ttt1的数据不会违背外键参照完整性。
    ETL@RACTEST> delete from ttt1;

    10 rows deleted.
    但是如果我们使用truncate,oracle则要报错:
    ETL@RACTEST> truncate table ttt1;
    truncate table ttt1
                   *
    ERROR at line 1:
    ORA-02266: unique/primary keys in table referenced by enabled foreign keys

    因为truncate实现的是一种快速删除,因此它无法检验参照完整性,即使删除的数据不违反参照完整性,Oracle也不允许做truncate操作,也就是我们说的宁可错杀一千,不可放过一个,呵呵。
    我在培训的时候有人说外键如果设置了级联删除就可以truncate,但实际上是不行的,实验如下:
    ETL@RACTEST> drop table ttt2 purge;

    Table dropped.

    Elapsed: 00:00:00.03
    ETL@RACTEST> create table ttt2 (a number,constraint fk_ttt2_a foreign key(a) references ttt1(a) on delete cascade);

    Table created.

    Elapsed: 00:00:00.01
    ETL@RACTEST> truncate table ttt1;
    truncate table ttt1
                   *
    ERROR at line 1:
    ORA-02266: unique/primary keys in table referenced by enabled foreign keys

    Elapsed: 00:00:00.00
    这是一种方式的级联删除,trucate仍然报错,下面是另一种级联:
    ETL@RACTEST> drop table ttt2 purge;

    Table dropped.

    Elapsed: 00:00:00.01
    ETL@RACTEST> create table ttt2 (a number,constraint fk_ttt2_a foreign key(a) references ttt1(a) on delete set null);

    Table created.

    Elapsed: 00:00:00.01
    ETL@RACTEST> truncate table ttt1;
    truncate table ttt1
                   *
    ERROR at line 1:
    ORA-02266: unique/primary keys in table referenced by enabled foreign keys
    同样不行,因此得出结论,只要有外键参照A表的字段,那么就不能对A表使用truncate操作!
     
    转自:http://blog.sina.com.cn/s/blog_6ff05a2c0100mira.html
  • 相关阅读:
    java 在线网络考试系统源码 springboot mybaits vue.js 前后分离跨域
    springboot 整合flowable 项目源码 mybiats vue.js 前后分离 跨域
    flowable Springboot vue.js 前后分离 跨域 有代码生成器 工作流
    Flowable 工作流 Springboot vue.js 前后分离 跨域 有代码生成器
    java 企业 网站源码 后台 springmvc SSM 前台 静态化 代码生成器
    java 进销存 商户管理 系统 管理 库存管理 销售报表springmvc SSM项目
    基于FPGA的电子计算器设计(中)
    基于FPGA的电子计算器设计(上)
    FPGA零基础学习:SPI 协议驱动设计
    Signal tap 逻辑分析仪使用教程
  • 原文地址:https://www.cnblogs.com/autumnlj/p/5814693.html
Copyright © 2011-2022 走看看