根据文档,“使用常量 DBMS_STATS.AUTO_CASCADE 让 Oracle 确定是否要收集索引统计信息。”
但看起来 AUTO_CASCADE 总是会收集索引统计信息,即使它显然不需要。
这个测试用例演示了这个问题:
SQL> --Create table
SQL> create table statistics_test(a number, b number, c number, d number, e number);
Table created.
SQL> --Add 10 million rows (about 320 MB)
SQL> begin
2 for i in 1 .. 100 loop
3 insert into statistics_test
4 select level, level, level, level, level from dual
5 connect by level <= 100000;
6 end loop;
7 commit;
8 end;
9 /
PL/SQL procedure successfully completed.
SQL> --Create large index (AFTER the data load)
SQL> create index statistics_test_index on statistics_test(a,b,c,d,e);
Index created.
SQL> --Statistics are automatically gathered on index creation or rebuild.
SQL> select to_char(last_analyzed, 'HH24:MI:SS') last_analyzed
2 from user_indexes
3 where index_name = 'STATISTICS_TEST_INDEX';
LAST_ANA
--------
16:11:43
SQL> --Gather stats, use AUTO_CASCADE.
SQL> exec dbms_stats.gather_table_stats(user, 'STATISTICS_TEST', cascade => DBMS_STATS.AUTO_CASCADE);
PL/SQL procedure successfully completed.
SQL> --FAIL: Time changed - index was re-analyzed even though no data changed.
SQL> select to_char(last_analyzed, 'HH24:MI:SS') last_analyzed
2 from user_indexes
3 where index_name = 'STATISTICS_TEST_INDEX';
LAST_ANA
--------
16:12:12
SQL> --Let's assume that LAST_ANALYZED is lying.
SQL> --What I'm really worried about is the extra time spent analyzing indexes.
SQL> --Compare performance of AUTO_CASCADE, TRUE, and FALSE.
SQL> --FAIL: AUTO_CASCADE is as slow as TRUE. It should be as fast as FALSE.
SQL> set timing on
SQL> exec dbms_stats.gather_table_stats(user, 'STATISTICS_TEST', cascade => DBMS_STATS.AUTO_CASCADE);
PL/SQL procedure successfully completed.
Elapsed: 00:00:20.80
SQL> exec dbms_stats.gather_table_stats(user, 'STATISTICS_TEST', cascade => true);
PL/SQL procedure successfully completed.
Elapsed: 00:00:19.58
SQL> exec dbms_stats.gather_table_stats(user, 'STATISTICS_TEST', cascade => false);
PL/SQL procedure successfully completed.
Elapsed: 00:00:08.27
Run Code Online (Sandbox Code Playgroud)
我认为这并不重要,但我的系统使用默认值 ESTIMATE_PERCENT、METHOD_OPT、DEGREE、GRANULARITY、CASCADE 和 NO_INVALIDATE。我可以在 10.2.0.4、11.2.0.1、11.2.0.3 和 12.2.0.1 上重现这个问题。
这看起来像是一个错误,但我在 My Oracle Support 上找不到任何内容。奇怪的是,具有重大性能影响的默认设置会被完全破坏这么长时间。
我在这里错过了什么吗?
| 归档时间: |
|
| 查看次数: |
4009 次 |
| 最近记录: |