Incrementalstatistics For Partitioned Tables In11g
Incrementalstatistics For Partitioned Tables In11g
For partitioned tables, when we collect statistics, even when only one partition changed, such as
add a new partition or load some data to a partition,
we have to scan all partitions to compute global statistics, this is much resource intensive
operation.
In 11G, oracle introduced incremental statistics gather option for partitioned table. When a
partitioned table is set to incremental attribute, it will store
a synopsis on sysaux tablespace for global level statistics(it will only consume very little
space), then, it will only scan one partition but will update
the global statistics, which will save many resource.
2, my test:
2.0: My Test Environments:
Oracle version is: 11.1.0.6,
OS: Solaris
(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),
33
34
35
36
TRUE
My test indicates that: the incremental attribute will make the statistics gathering process much
faster!
exec dbms_stats.gather_table_stats(user, 'test_inc')
exec dbms_stats.gather_table_stats(user, 'test_inc_bak')
18
19
20
21
22
23
24
25
26
27
28
29
30
31
11.22
10.72
11.48
11.01
11.06
10.68
12.58
8.01
12.38
13.09
14.67
13.55
14.27
14.15
The red line represent time elapsed for incremental partitioned table
The yellow line time elapsed for non-incremental partitioned table
93.74
100.85
105.54
112.08
116.53
123.57
126.58
135.41
137.95
144.33
149.75
153.94
160.50
165.50
2.5: let
lets see from another perspective: what last_analyzed column can tell
us?
SQL> exec dbms_stats.gather_table_stats(user, 'test_inc'
'test_inc')
PL/SQL procedure successfully completed.
Elapsed: 00:00:04.37
SQL> select partition_name, blocks, num_rows, last_analyzed from
user_tab_partitions where table_name = 'TEST_INC' and num_rows > 0;
PARTITION_NAME
BLOCKS
NUM_ROWS LAST_ANALYZED
------------------------------ ---------- ---------- ------------------P00
6796
300000 2009-09-09 00:49:51
P16
P17
P18
P19
P20
P21
P22
P23
P24
P25
P26
P27
P28
P29
P30
PMAX
300000
300000
300000
300000
300000
300000
300000
300000
300000
300000
300000
300000
300000
300000
300000
0
6796
6796
6796
6796
6796
6796
6796
6796
6796
6796
6796
6796
6796
6796
6796
0
2009-09-11
2009-09-11
2009-09-11
2009-09-11
2009-09-11
2009-09-11
2009-09-11
2009-09-11
2009-09-11
2009-09-11
2009-09-11
2009-09-11
2009-09-11
2009-09-11
2009-09-11
2009-09-11
01:08:30
01:08:33
01:08:36
01:08:39
01:08:42
01:08:45
01:08:48
01:08:51
01:08:54
01:08:57
01:09:00
01:09:03
01:09:06
01:09:09
01:09:11
01:09:11
While the following is what analyze looks like when I finish the analyze on incremental
table test_inc_bak:
SQL> select partition_name, num_rows, blocks, last_analyzed from
user_tab_partitions where table_name = 'TEST_INC'
'TEST_INC';
PARTITION_NAME
NUM_ROWS
BLOCKS LAST_ANALYZED
------------------------------ ---------- ---------- ------------------P00
300000
6796 2009-09-09 00:49:51
P01
300000
6796 2009-09-09 00:52:27
P02
300000
6796 2009-09-09 00:55:39
P03
300000
6796 2009-09-09 01:00:23
P04
300000
6796 2009-09-09 01:04:59
P05
300000
6796 2009-09-09 01:09:37
P06
300000
6796 2009-09-09 01:14:06
P07
300000
6796 2009-09-09 01:17:33
P08
300000
6796 2009-09-09 01:22:14
P09
300000
6796 2009-09-09 01:28:15
P10
300000
6796 2009-09-09 01:33:29
P11
300000
6796 2009-09-09 01:36:36
P12
300000
6796 2009-09-09 01:42:39
P13
300000
6796 2009-09-09 01:46:54
P14
300000
6796 2009-09-09 01:55:36
P15
300000
6796 2009-09-09 02:04:55
P16
300000
6796 2009-09-09 02:20:34
P17
300000
6796 2009-09-09 03:05:48
P18
300000
6796 2009-09-09 03:38:40
P19
300000
6796 2009-09-09 04:10:07
P20
300000
6796 2009-09-09 04:14:57
P21
300000
6796 2009-09-09 04:46:03
P22
300000
6796 2009-09-09 04:57:09
P23
300000
6796 2009-09-09 05:28:45
P24
300000
6796 2009-09-11 22:03:14
P25
300000
6796 2009-09-11 00:31:14
P26
300000
6796 2009-09-11 00:37:14
P27
300000
6796 2009-09-11 00:44:13
P28
300000
6796 2009-09-11 00:52:49
P29
300000
6796 2009-09-11 01:00:16
P30
300000
6796 2009-09-11 01:06:34
PMAX
0
0 2009-09-11 01:06:34
Per my test, it seems that, incremental statistics is only sensitive for a new partition which is
completely newly loaded data. It can be aware of the following situations:
a. delete/insert some data to a partition that has already been analyzed
b. truncate one/more partitions
Please see my test:
The table currently has 1.8 million records, each partition contain 0.3 million records:
SQL> select partition_name, num_rows, blocks, last_analyzed from
user_tab_partitions where table_name = 'TEST_INC' and num_rows > 0;
PARTITION_NAME
NUM_ROWS
BLOCKS LAST_ANALYZED
------------------------------ ---------- ---------- ------------------P00
300000
6796 2009-09-12 01:41:56
P01
300000
6796 2009-09-12 01:45:07
P02
300000
6796 2009-09-12 01:47:11
P03
300000
6796 2009-09-12 01:50:11
P04
300000
6796 2009-09-12 01:51:41
P05
300000
6796 2009-09-12 01:52:48
P03
P04
P05
300000
300000
300000
6 rows selected.
SQL> select count(*) from test_inc partition(p05);
COUNT(*)
---------200000
SQL> select count(*) from test_inc partition(p06);
COUNT(*)
---------0
SQL> select count(*) from test_inc partition(p01);
COUNT(*)
---------600000
We can see, the statistics does not change at all!
Then, will it triggered by populating data into a newly loaded partition?
It won
wont! Let me insert data to an empty partition p06:
SQL> insert into test_inc select rownum, sysdate+mod(rownum, 30),
'wangweifengwangweifeng'||rownum,
2 rpad('x', 50, 'x')||rownum, rpad('y', 50, 'z')||rownum, 6 from
dual connect by rownum <= 300000;
300000 rows created.
SQL> exec dbms_stats.gather_table_stats(user, 'test_inc');
PL/SQL procedure successfully completed.
Elapsed: 00:00:06.61
SQL> select table_name, num_rows, blocks, last_analyzed from
user_tables where table_name = 'TEST_INC';
TABLE_NAME
NUM_ROWS
BLOCKS LAST_ANALYZED
------------------------------ ---------- ---------- ------------------TEST_INC
2100000
48157 2009-09-12 02:01:36
P06
300000
7 rows selected.
7 rows selected.
SQL> truncate table test_inc;
Table truncated.
Elapsed: 00:00:02.24
SQL> exec dbms_stats.gather_table_stats(user, 'test_inc');
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.61
SQL> select table_name, num_rows, blocks, last_analyzed from
user_tables where table_name = 'TEST_INC';
TABLE_NAME
NUM_ROWS
BLOCKS LAST_ANALYZED
------------------------------ ---------- ---------- ------------------TEST_INC
0
0 2009-09-12 04:09:43
We can see: the statistics for table level is got updated, but, it is not got updated for
partition level!
I think, it should be a bug! Anyway, I will file TAR for Oracle for clarify.
, then analyze again:
How to fix it temporarily? Set it back to no-incremental
no-incremental
SQL> exec
'FALSE'
DBMS_STATS.SET_TABLE_PREFS(user,'test_inc','INCREMENTAL','FALSE'
'FALSE');
PL/SQL procedure successfully completed.
SQL> select DBMS_STATS.get_PREFS('incremental', 'wwf', 'test_inc') from
dual;
DBMS_STATS.GET_PREFS('INCREMENTAL','WWF','TEST_INC')
----------------------------------------------------------------------FALSE
SQL> exec dbms_stats.gather_table_stats(user, 'test_inc');
PL/SQL procedure successfully completed.
SQL> select partition_name, num_rows, blocks, last_analyzed from
user_tab_partitions where table_name = 'TEST_INC' and num_rows > 0;
no rows selected
SQL> select table_name, num_rows, blocks, last_analyzed from
user_tables where table_name = 'TEST_INC';
TABLE_NAME
NUM_ROWS
BLOCKS LAST_ANALYZED
------------------------------ ---------- ---------- ------------------TEST_INC
0
0 2009-09-12 04:18:34
10
11
12
13
14
15
Table created.
Elapsed: 00:00:00.01
SQL> select partition_name, num_rows, blocks, last_analyzed from
user_tab_partitions where table_name = 'COMPOSITE_RNG_LIST' and rownum > 0;
PARTITION_NAME
NUM_ROWS
BLOCKS LAST_ANALYZED
---------------- ---------- ---------- ------------------PER1
100000
496
2009-09-14 18:17:57
Elapsed: 00:00:00.00
SQL> select partition_name, SUBPARTITION_NAME, num_rows, blocks, last_analyzed
from user_tab_subpartitions where table_name = 'COMPOSITE_RNG_LIST' and rownum
> 0;
PARTITION_NAME
SUBPARTITION_NAME NUM_ROWS
---------------- ---------------- ---------PER1
PER1_WEST
100000
BLOCKS LAST_ANALYZED
---------- ------------------496 2009-09-14 18:17:55
Then, insert 100000 more rows and analyze again, we can see that, the
statistics at partition level and table level were not changed at all:
SQL> insert into composite_rng_list select rownum, 'customer'||rownum, 'WA',
to_date('2007-01-01', 'yyyy-mm-dd') from dual connect by rownum <= 100000;
NUM_ROWS
BLOCKS
LAST_ANALYZED
---------- ---------- ------------------200000
1000
2009-09-14 18:24:11
Then, insert 100000 more rows and analyze again, we can see that, the
statistics at partition level and table level were not changed at all:
SQL> insert into composite_rng_list select rownum, 'customer'||rownum,
'NY', to_date('2007-01-01', 'yyyy-mm-dd') from dual connect by rownum <=
100000;
100000 rows created.
SQL> commit;
Commit complete.
SQL> exec dbms_stats.gather_table_stats(user, 'COMPOSITE_RNG_LIST',
granularity=>'ALL')
PL/SQL procedure successfully completed.
SQL> select table_name, num_rows, blocks, last_analyzed from user_tables where
table_name = 'COMPOSITE_RNG_LIST';
TABLE_NAME
NUM_ROWS
BLOCKS LAST_ANALYZED
------------------------------ ---------- ---------- ------------------COMPOSITE_RNG_LIST
100000
1496 2009-09-14 18:26:33
SQL> select partition_name, num_rows, blocks, last_analyzed from
user_tab_partitions where table_name = 'COMPOSITE_RNG_LIST' and num_rows > 0;
PARTITION_NAME
NUM_ROWS
BLOCKS
LAST_ANALYZED
----------------- ---------- ---------- ------------------PER1
100000
496
2009-09-14 18:17:57
LAST_ANALYZED
------------------2009-09-14 18:26:32
2009-09-14 18:26:32
CLUSTERING LAST_ANALYZED
FACTOR
------------- ---------- ------------- ----------------- -------------P00
300000
300000
6763
2009-09-14 19:54:35
P01
300000
300000
6763
2009-09-14 19:54:35
as incremental:
It seems that there is no way to set index ind_test_inc
ind_test_inc
SQL> select dbms_stats.get_prefs('incremental', 'wwf', 'test_inc') from dual;
DBMS_STATS.GET_PREFS('INCREMENTAL','WWF','TEST_INC')
-------------------------------------------TRUE
Elapsed: 00:00:00.01
SQL> select dbms_stats.get_prefs('incremental', 'wwf', 'ind_test_inc'
'ind_test_inc') from
dual;
DBMS_STATS.GET_PREFS('INCREMENTAL','WWF','IND_TEST_INC')
----------------------------------------------FALSE
Elapsed: 00:00:00.01
SQL> exec dbms_stats.set_table_prefs('wwf', 'ind_test_inc'
'ind_test_inc', 'incremental',
'true')
BEGIN dbms_stats.set_table_prefs('wwf', 'ind_test_inc', 'incremental', 'true');
END;
*
ERROR at line 1:
ORA-20000: TABLE "WWF"."IND_TEST_INC" does not exist or insufficient privileges
ORA-06512: at "SYS.DBMS_STATS", line 2091
ORA-06512: at "SYS.DBMS_STATS", line 24110
ORA-06512: at line 1
I will do tests on 11G Release 2 once it is available for download on Solaris version.
But, from the document of 11G Release 2, which has been already available, there is still
no such function in such as set_index_prefs provided.
SM/ADVISOR
Framework
SM/AWR
Repository
SM/OPTSTAT
History
SM/OTHER
Components
SMON_SCN_TIME
mapping
JOB_SCHEDULER
Scheduler
29 rows selected.
The blue line represents the space occupied by the synopsis for global level statistics.
Usually, it will only consume very little space.
Using sql_trace, found that the attribute for incremental for a table is stored in table
SYS.OPTSTAT_USER_PREF$:
SQL> select a.obj#, name, pname, valchar from SYS.OPTSTAT_USER_PREFS$ a, obj$ b
where a.obj# = b.obj#;
OBJ# NAME
PNAME
VALCHAR
---------- ------------------------------ -------------------- ---------------15307 TEST_INC
INCREMENTAL
TRUE
4. My conclusion:
I think, incremental statistics gathering for partitioned tables is a very useful new feature
introduced by ORACLE 11G if all the bugs can be resolved.
It will consume much less resource especially for large partitioned/subpartitioned tables
and shorten our statistics gathering process. I believe it will
not only help us for our normal analyze CR, but also it will help us under situations under
tough situations (such as TCB) caused by inaccurate statistics,
as at such situations, time is so precious for us.
Anyway, I will track this feature.
Thanks!