SYSDATE更改是否会影响Oracle中的表统计信息?

时间:2014-01-03 17:05:24

标签: database oracle oracle11g database-administration

我们的一位dbas表示,在更改Oracle中的系统日期后(我们需要这样做才能测试我们的软件),我们需要收集表格的所有统计数据 - 这是真的吗?如果是,那为什么呢?我无法解决Oracle文档中的任何问题。我想到的一件事是,自动收集统计数据的工作可能会等待下一个被跳下的运行日期。

还有其他想法吗?

1 个答案:

答案 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 |
----------------------------------------------------------------------------