truncate表,会将统计信息清除么?

本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

原文链接:blog.ouyangsihai.cn >> truncate表,会将统计信息清除么?

看见微信群有位朋友问:

truncate表,会将统计信息清除么?

有些朋友回复,

数据字典信息都没有了,统计信息就清除了,所以是没有统计信息的。
做个实验,跟踪一下truncate,应该比较清楚。
我做了10g的测试,发现那个表的last_analyzed还是有记录的。
truncate完统计信息还是在的,跟你10g还是11g没有关系,关键在你之前有没有收集统计信息,你之前都没有收集统计信息,last analyzed本来就是空的。
之前有记录,last_analyzed是不为空的,truncate表后,这个变成了空。

第二位朋友说的很对,究竟会不会删除统计信息,做一下实验,就可以了解了。

创建测试表,

SQL create table test (id number, name varchar2(1)); Table created.

SQL begin        for i in 1 .. 10000 loop          insert into test values(i, dbms_random.string('a',1));        end loop;        commit;      end;      / PL/SQL procedure successfully completed.

SQL create index idx_test on test(id); Index created.

SQL select count(*) from test;   COUNT(*) ----------      10000

此时检索表的统计信息,记录是空的,检索索引的统计信息,是有记录的,

SQL select num_rows, to_char(last_analyzed,'yyyy-mm-dd hh24:mi:ss') last_analyzed from user_tables where table_name='TEST';   NUM_ROWS LAST_ANALYZED   --------------- -----------------------------------------

SQL select num_rows, sample_size, to_char(last_analyzed,'yyyy-mm-dd hh24:mi:ss') last_analyzed from user_indexes where table_name='TEST';   NUM_ROWS SAMPLE_SIZE LAST_ANALYZED ---------- ----------- -----------------------------      10000          10000 2017-10-08 15:55:42

手工以cascade=false收集统计信息,

SQL exec dbms_stats.gather_table_stats('BISAL','TEST',cascade=false); PL/SQL procedure successfully completed.

可以看出,表的统计信息已近更新了,

SQL select num_rows, to_char(last_analyzed,'yyyy-mm-dd hh24:mi:ss') last_analyzed from user_tables where table_name='TEST';   NUM_ROWS LAST_ANALYZED ---------- --------------------      10000 2017-10-08 16:04:16

但是由于cascade=false,因此不会自动采集索引,

SQL select num_rows, sample_size, to_char(last_analyzed,'yyyy-mm-dd hh24:mi:ss') last_analyzed from user_indexes where table_name='TEST';   NUM_ROWS SAMPLE_SIZE LAST_ANALYZED ---------- ----------- -----------------------------      10000          10000 2017-10-08 15:55:42

以cascade=true采集统计信息,表和索引的统计信息更新了,

SQL exec dbms_stats.gather_table_stats('BISAL','TEST',cascade=true); PL/SQL procedure successfully completed.

SQL select num_rows, to_char(last_analyzed,'yyyy-mm-dd hh24:mi:ss') last_analyzed from user_tables where table_name='TEST';   NUM_ROWS LAST_ANALYZED ---------- --------------------      10000 2017-10-08 16:07:18

SQL select num_rows, sample_size, to_char(last_analyzed,'yyyy-mm-dd hh24:mi:ss') last_analyzed from user_indexes where table_name='TEST';   NUM_ROWS SAMPLE_SIZE LAST_ANALYZED ---------- ----------- ---------------      10000          10000 2017-10-08 16:07:18

此时执行truncate,清空表数据,

SQL truncate table test; Table truncated.

SQL select count(*) from test;   COUNT(*) ----------      0

可以看出表和索引统计信息,没有被删除,

SQL select num_rows, to_char(last_analyzed,'yyyy-mm-dd hh24:mi:ss') last_analyzed from user_tables where table_name='TEST';   NUM_ROWS LAST_ANALYZED ---------- --------------------      10000 2017-10-08 16:07:18

SQL select num_rows, sample_size, to_char(last_analyzed,'yyyy-mm-dd hh24:mi:ss') last_analyzed from user_indexes where table_name='TEST';   NUM_ROWS SAMPLE_SIZE LAST_ANALYZED ---------- ----------- ---------------      10000          10000 2017-10-08 16:07:18

执行一次统计信息采集,此时表和索引的统计信息,已经是最新了,

SQL exec dbms_stats.gather_table_stats('BISAL','TEST',cascade=true); PL/SQL procedure successfully completed.

SQL select num_rows, to_char(last_analyzed,'yyyy-mm-dd hh24:mi:ss') last_analyzed from user_tables where table_name='TEST'; NUM_ROWS  LAST_ANALYZED --------- --------------------        0  2017-10-08 16:25:06

SQL select num_rows, sample_size, to_char(last_analyzed,'yyyy-mm-dd hh24:mi:ss') last_analyzed from user_indexes where table_name='TEST';   NUM_ROWS SAMPLE_SIZE LAST_ANALYZED ---------- ----------- --------------------            0              0 2017-10-08 16:25:06

说明执行truncate,表的统计信息不会被删除,除非执行了统计信息采集,truncate table和表和索引的统计信息,没有任何关联。

另一方面,truncate会影响表是否可以被自动采集统计信息的任务触发,mon_mods_all$会记录自上次自动统计信息收集作业完成之后,对所有目标表的insert、delete和update操作所影响的记录数,即DML操作次数,以及目标表是否执行过truncate操作,主要用于每日统计信息采集作业判断是否需要采集此张表,对于这张视图mon_mods_all$的介绍,可以参考eygle的文章,

http://www.eygle.com/archives/2009/09/mon_mods_is_use.html

truncate表,会将统计信息清除么?

比如如下表,记录数为10000,mon_mods_all$记录了一条信息,其中插入insert是10000,其他的字段,为空,

SQL select count(*) from test;   COUNT(*) ----------      10000

SQL exec dbms_stats.flush_database_monitoring_info(); PL/SQL procedure successfully completed.

SQL select obj#, inserts, updates, deletes, flags from sys.mon_mods_all$ where obj#=18021;   OBJ#   INSERTS      UPDATES   DELETES   FLAGS ------ --------- --------- ---------- -------  18021      10000            0          0       0

此时执行truncate,mon_mods_all$记录未变,

SQL truncate table test; Table truncated.

SQL select obj#, inserts, updates, deletes, flags from sys.mon_mods_all$ where obj#=18021;    OBJ#   INSERTS        UPDATES   DELETES    FLAGS ------- ---------- ---------- --------- --------   18021        10000           0            0        0

此时执行一次dbms_stats.flush_database_monitoring_info(),显示FLAGS是1,表示执行过了truncate table,

SQL exec dbms_stats.flush_database_monitoring_info(); PL/SQL procedure successfully completed.

SQL select obj#, inserts, updates, deletes, flags from sys.mon_mods_all$ where obj#=18021;    OBJ#   INSERTS        UPDATES   DELETES    FLAGS ------- ---------- ---------- --------- --------   18021        10000           0         10000        1

再次执行统计信息采集,此时mon_mods_all$的记录就会被清空,

SQL exec dbms_stats.gather_table_stats('BISAL','TEST',cascade=true); PL/SQL procedure successfully completed.

SQL select obj#, inserts, updates, deletes, flags from sys.mon_mods_all$ where obj#=18021; no rows selected

总结:

  1. 执行truncate,表的统计信息不会被删除,除非执行了统计信息采集,truncate table和表和索引的统计信息,没有任何关联,对象是否有统计信息记录,取决于是否采集过统计信息,包括手工和自动两种方法。

  2. 执行truncate,会将mon_mods_all$视图的FLAGS字段置位,变为1,自动采集统计信息作业,可以据此判断,是否需要采集这张表,当重新采集统计信息,就会删除mon_mods_all$保存的记录。

如果您觉得此篇文章对您有帮助,欢迎关注微信公众号:bisal的个人杂货铺,您的支持是对我最大的鼓励!共同学习,共同进步:)

truncate表,会将统计信息清除么? truncate表,会将统计信息清除么?
本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

原文链接:blog.ouyangsihai.cn >> truncate表,会将统计信息清除么?


 上一篇
一个关于Definer和Invoker的权限问题 一个关于Definer和Invoker的权限问题
前两天有位朋友,微信公众号提了一个问题,原文描述如下, 我的需求是在tag库中执行一个处理,使得tag中所有用户seq的nextval与src库中一致。 我在tag库的user1中创建了一个存储过程,代码逻辑为通过dblink(指向s
下一篇 
经典的运维脚本三步曲 经典的运维脚本三步曲
无论是应用运维,还是数据库运维,均可以分为“人肉”-“自动化”-“智能化”阶段,其中自动化阶段,主要是将一些人做的操作,尤其是一些重复性操作,封装为程序,一方面避免重复性操作,另一方面提高执行效率。自动化实现的过程中,经常使用的,可能就