我们的一位dbas表示,在更改Oracle中的系统日期后(我们需要这样做才能测试我们的软件),我们需要收集表格的所有统计数据 - 这是真的吗?如果是,那为什么呢?我无法解决Oracle文档中的任何问题。我想到的一件事是,自动收集统计数据的工作可能会等待下一个被跳下的运行日期。
还有其他想法吗?
答案 0 :(得分:2)
更改系统日期可能不需要重新收集统计信息。表统计信息不包含实际的SYSDATE。即使执行计划对SYSDATE非常敏感,Oracle似乎也能很好地处理日期更改。
然而,如果在更改日期时出现一些奇怪的错误,我不会感到太惊讶。但您应该向DBA询问具体细节,包括Oracle Support错误号。
以下是优化程序完美处理操作系统日期更改的示例。
1:删除所有当前缓存的SQL,以防万一。
alter system flush shared_pool;
2:创建一个带有倾斜列的表格。今天有许多价值,但明天只有少数。
drop table test1;
create table test1(a date, b varchar2(100));
create index test1_idx on test1(a);
insert into test1 select trunc(sysdate), 'common value' from dual
connect by level <= 100000;
insert into test1 select trunc(sysdate)+1, 'rare value' from dual
connect by level <= 10;
--Workload to generate histograms.
select max(b) from test1 where a = trunc(sysdate);
begin
dbms_stats.gather_table_stats(user, 'TEST1');
end;
/
3:从今天起选择公共数据,正确使用全表扫描。
select to_char(sysdate, 'YYYY-MM-DD') current_date from dual;
CURRENT_DATE
------------
2014-01-05
explain plan for select b from test1 where a = trunc(sysdate);
select * from table(dbms_xplan.display(format => '-cost -bytes -predicate'));
Plan hash value: 4122059633
------------------------------------------------------
| Id | Operation | Name | Rows | Time |
------------------------------------------------------
| 0 | SELECT STATEMENT | | 100K| 00:00:01 |
| 1 | TABLE ACCESS FULL| TEST1 | 100K| 00:00:01 |
------------------------------------------------------
4:从明天起选择稀有数据,正确使用索引范围扫描。
explain plan for select b from test1 where a = trunc(sysdate)+1;
select * from table(dbms_xplan.display(format => '-cost -bytes -predicate'));
Plan hash value: 1226949
----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 10 | 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID BATCHED| TEST1 | 10 | 00:00:01 |
| 2 | INDEX RANGE SCAN | TEST1_IDX | 10 | 00:00:01 |
----------------------------------------------------------------------------
5:将操作系统时钟更改为明天。 SYSDATE立即更新。
select to_char(sysdate, 'YYYY-MM-DD') current_date from dual;
CURRENT_DATE
------------
2014-01-06
6:重新执行第3步。此查询先前返回了大量数据,现在只返回少量数据。该计划应该并且确实从全表扫描变为索引范围扫描。
explain plan for select b from test1 where a = trunc(sysdate);
select * from table(dbms_xplan.display(format => '-cost -bytes -predicate'));
Plan hash value: 1226949
----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 10 | 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID BATCHED| TEST1 | 10 | 00:00:01 |
| 2 | INDEX RANGE SCAN | TEST1_IDX | 10 | 00:00:01 |
----------------------------------------------------------------------------