合 在Oracle中,对表执行TRUNCATE操作会将表的统计信息也清除掉吗
不会。对表执行TRUNCATE操作,表及其索引的统计信息都不会被清除掉,除非使用系统包DBMS_STATS中的相关DELETE存储过程才能将表或索引的统计信息清除掉。命令如下所示:
1 2 | DBMS_STATS.DELETE_TABLE_STATS(USER,'TB_NAME');--表 DBMS_STATS.DELETE_INDEX_STATS(USER,'INDX_NAME');--索引 |
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | SYS@DCLHR> create table lhr_test_tjxx (id number, name varchar2(1)); Table created. SYS@DCLHR> begin 2 for i in 1 .. 10000 loop 3 insert into lhr_test_tjxx values(i, dbms_random.string('a',1)); 4 end loop; 5 commit; 6 end; 7 / PL/SQL procedure successfully completed. SYS@DCLHR> create index idx_test on lhr_test_tjxx(id); Index created. SYS@DCLHR> select count(*) from lhr_test_tjxx; COUNT(*) ---------- 10000 此时查询表的统计信息,记录是空的,查询索引的统计信息,是有记录的,说明创建索引时会自动收集索引的统计信息,自动收集索引的统计信息由隐含参数“_OPTIMIZER_COMPUTE_INDEX_STATS”控制: SYS@DCLHR> select num_rows, to_char(last_analyzed,'yyyy-mm-dd hh24:mi:ss') last_analyzed from user_tables where table_name='LHR_TEST_TJXX'; NUM_ROWS LAST_ANALYZED ---------- -------------------------------------- SYS@DCLHR> select num_rows, sample_size, to_char(last_analyzed,'yyyy-mm-dd hh24:mi:ss') last_analyzed from user_indexes where table_name='LHR_TEST_TJXX'; NUM_ROWS SAMPLE_SIZE LAST_ANALYZED ---------- ----------- -------------------------------------- 10000 10000 2020-04-02 15:14:22 手工以cascade=false收集表的统计信息: SQL> exec dbms_stats.gather_table_stats('SYS','LHR_TEST_TJXX',cascade=>false); PL/SQL procedure successfully completed. SYS@DCLHR> select num_rows, to_char(last_analyzed,'yyyy-mm-dd hh24:mi:ss') last_analyzed from user_tables where table_name='LHR_TEST_TJXX'; NUM_ROWS LAST_ANALYZED ---------- -------------------------------------- 10000 2020-04-02 15:18:13 SYS@DCLHR> SELECT TABLE_OWNER,TABLE_NAME,INSERTS,TRUNCATED FROM DBA_TAB_MODIFICATIONS WHERE TABLE_NAME='LHR_TEST_TJXX'; TABLE_OWNE TABLE_NAME INSERTS TRUNCA ---------- ---------------- ---------- ------ SYS LHR_TEST_TJXX 10000 NO 可以看出,表的统计信息已经更新了,而且DBA_TAB_MODIFICATIONS视图(基表为SYS.MON_MODS_ALL$)插入了一条记录(如果没有可以执行exec dbms_stats.flush_database_monitoring_info();),此时执行truncate,清空表数据:可以看出表和索引统计信息,没有被删除,而且TRUNCATED列由NO变为了YES: SYS@DCLHR> truncate table LHR_TEST_TJXX; Table truncated. SYS@DCLHR> SELECT TABLE_OWNER,TABLE_NAME,INSERTS,TRUNCATED FROM DBA_TAB_MODIFICATIONS WHERE TABLE_NAME='LHR_TEST_TJXX'; TABLE_OWNE TABLE_NAME INSERTS TRUNCA ---------- ---------------- ---------- ------ SYS LHR_TEST_TJXX 10000 YES SYS@DCLHR> select num_rows, sample_size, to_char(last_analyzed,'yyyy-mm-dd hh24:mi:ss') last_analyzed from user_indexes where table_name='LHR_TEST_TJXX'; NUM_ROWS SAMPLE_SIZE LAST_ANALYZED ---------- ----------- -------------------------------------- 10000 10000 2020-04-02 15:14:22 SYS@DCLHR> select num_rows, to_char(last_analyzed,'yyyy-mm-dd hh24:mi:ss') last_analyzed from user_tables where table_name='LHR_TEST_TJXX'; NUM_ROWS LAST_ANALYZED ---------- -------------------------------------- 10000 2020-04-02 15:18:13 此时再执行一次统计信息采集,此时表和索引的统计信息,已经是最新的了: SYS@DCLHR> exec dbms_stats.gather_table_stats('SYS','LHR_TEST_TJXX',cascade=>true); PL/SQL procedure successfully completed. SYS@DCLHR> SELECT TABLE_OWNER,TABLE_NAME,INSERTS,TRUNCATED FROM DBA_TAB_MODIFICATIONS WHERE TABLE_NAME='LHR_TEST_TJXX'; no rows selected SYS@DCLHR> select num_rows, sample_size, to_char(last_analyzed,'yyyy-mm-dd hh24:mi:ss') last_analyzed from user_indexes where table_name='LHR_TEST_TJXX'; NUM_ROWS SAMPLE_SIZE LAST_ANALYZED ---------- ----------- -------------------------------------- 0 0 2020-04-02 15:20:52 SYS@DCLHR> select num_rows, to_char(last_analyzed,'yyyy-mm-dd hh24:mi:ss') last_analyzed from user_tables where table_name='LHR_TEST_TJXX'; NUM_ROWS LAST_ANALYZED ---------- -------------------------------------- 0 2020-04-02 15:20:52 |