[2023-04-18]增量收集统计信息

在11g之前,收集global的统计信息时,oracle需要扫描每个分区的统计信息,才能得出 global的统计信息。而在11g以后,Oracle会简单记录分区的概要信息,(synopsis,记录在 WRI$_OPTSTAT_SYNOPSIS_HEAD$ 和 WRI$_OPTSTAT_SYNOPSIS$中),对于global的统计信息,可以不再扫描每个分区的,只需通过计算概要信息,即可得出global 的统计信息。

1、创建分区表

SQL> create table p(id number, age date)
  2  partition by range(id)
  3  (partition p1 values less than(100),
  4  partition p2 values less than(200),
  5  partition p3 values less than(300),
  6  partition p4 values less than(400)
  7  );

Table created.

SQL> insert into p select level lv,sysdate from dual connect by level < 400;

399 rows created.

SQL> commit;

Commit complete.

SQL> exec dbms_stats.gather_table_stats(ownname=>'scott',tabname=>'p');

PL/SQL procedure successfully completed.

SQL>  select table_owner,table_name,partition_name from dba_tab_partitions where table_owner='SCOTT' and table_name='P';

TABLE_OWNER                    TABLE_NAME                     PARTITION_NAME
------------------------------ ------------------------------ ------------------------------
SCOTT                          P                              P1
SCOTT                          P                              P2
SCOTT                          P                              P3
SCOTT                          P                              P4


SQL> alter session set nls_date_format = 'yyyy-mm-dd hh24:mi:ss';

Session altered.

SQL> select table_name,num_rows,last_analyzed from dba_tables where table_name='P';

TABLE_NAME                       NUM_ROWS LAST_ANALYZED
------------------------------ ---------- -------------------
P                                     399 2023-04-18 16:33:47

SQL> 
SQL>   select table_name,partition_name,num_rows,last_analyzed from dba_tab_partitions where table_name='P';

TABLE_NAME                     PARTITION_NAME                   NUM_ROWS LAST_ANALYZED
------------------------------ ------------------------------ ---------- -------------------
P                              P1                                     99 2023-04-18 16:33:46
P                              P2                                    100 2023-04-18 16:33:47
P                              P3                                    100 2023-04-18 16:33:47
P                              P4                                    100 2023-04-18 16:33:47

 2、重新收集统计信息

SQL> exec dbms_stats.gather_table_stats(ownname=>'scott',tabname=>'p');

PL/SQL procedure successfully completed.

SQL> select table_name,num_rows,last_analyzed from dba_tables where table_name='P';

TABLE_NAME                       NUM_ROWS LAST_ANALYZED
------------------------------ ---------- -------------------
P                                     399 2023-04-18 16:35:12

SQL> select table_name,partition_name,num_rows,last_analyzed from dba_tab_partitions where table_name='P';

TABLE_NAME                     PARTITION_NAME                   NUM_ROWS LAST_ANALYZED
------------------------------ ------------------------------ ---------- -------------------
P                              P1                                     99 2023-04-18 16:35:12
P                              P2                                    100 2023-04-18 16:35:12
P                              P3                                    100 2023-04-18 16:35:12
P                              P4                                    100 2023-04-18 16:35:12

SQL> 

对表收集统计信息,虽然分区中的数据没有变化,依然会收集全部统计信息。

3、开启增量统计信息的条件

SQL> set lin 300
SQL> col "publish" for a30
SQL> col "granularity" for a30
SQL> col "incremental" for a30
SQL> select 
  2  dbms_stats.get_prefs('publish','&owner','&tablename') "publish",
  3  dbms_stats.get_prefs('granularity','&&owner','&&tablename') "granularity",
  4  dbms_stats.get_prefs('INCREMENTAL','&&owner','&&tablename') "incremental" 
  5  from dual;
Enter value for owner: scott
Enter value for tablename: p
old   2: dbms_stats.get_prefs('publish','&owner','&tablename') "publish",
new   2: dbms_stats.get_prefs('publish','scott','p') "publish",
Enter value for owner: scott
Enter value for tablename: p
old   3: dbms_stats.get_prefs('granularity','&&owner','&&tablename') "granularity",
new   3: dbms_stats.get_prefs('granularity','scott','p') "granularity",
old   4: dbms_stats.get_prefs('INCREMENTAL','&&owner','&&tablename') "incremental"
new   4: dbms_stats.get_prefs('INCREMENTAL','scott','p') "incremental"

publish                        granularity                    incremental
------------------------------ ------------------------------ ------------------------------
TRUE                           AUTO                           FALSE

SQL> 
SQL> exec dbms_stats.set_table_prefs('SCOTT', 'P', 'INCREMENTAL', 'TRUE');

PL/SQL procedure successfully completed.

SQL> col "publish" for a30
SQL> col "granularity" for a30
SQL> col "incremental" for a30
SQL> select 
  2  dbms_stats.get_prefs('publish','&owner','&tablename') "publish",
  3  dbms_stats.get_prefs('granularity','&&owner','&&tablename') "granularity",
  4  dbms_stats.get_prefs('INCREMENTAL','&&owner','&&tablename') "incremental" 
  5  from dual;
old   2: dbms_stats.get_prefs('publish','&owner','&tablename') "publish",
new   2: dbms_stats.get_prefs('publish','scott','p') "publish",
old   3: dbms_stats.get_prefs('granularity','&&owner','&&tablename') "granularity",
new   3: dbms_stats.get_prefs('granularity','scott','p') "granularity",
old   4: dbms_stats.get_prefs('INCREMENTAL','&&owner','&&tablename') "incremental"
new   4: dbms_stats.get_prefs('INCREMENTAL','scott','p') "incremental"

publish                        granularity                    incremental
------------------------------ ------------------------------ ------------------------------
TRUE                           AUTO                           TRUE

SQL> 

4、开启增量后第一次收集统计信息

SQL> exec dbms_stats.gather_table_stats(ownname=>'scott',tabname=>'p');

PL/SQL procedure successfully completed.

SQL> select table_name,num_rows,last_analyzed from dba_tables where table_name='P';

TABLE_NAME                       NUM_ROWS LAST_ANALYZED
------------------------------ ---------- -------------------
P                                     399 2023-04-18 16:39:26

SQL> select table_name,partition_name,num_rows,last_analyzed from dba_tab_partitions where table_name='P';

TABLE_NAME                     PARTITION_NAME                   NUM_ROWS LAST_ANALYZED
------------------------------ ------------------------------ ---------- -------------------
P                              P1                                     99 2023-04-18 16:39:26
P                              P2                                    100 2023-04-18 16:39:26
P                              P3                                    100 2023-04-18 16:39:26
P                              P4                                    100 2023-04-18 16:39:26

SQL> 

设置增量收集后,第一次收集统计信息会将全部历史分区重新收集,以生成历史分区的大纲信息,分区数越多,耗时越长

5、开启增量后第二次收集统计信息

SQL> exec dbms_stats.gather_table_stats(ownname=>'scott',tabname=>'p');

PL/SQL procedure successfully completed.

SQL> select table_name,num_rows,last_analyzed from dba_tables where table_name='P';

TABLE_NAME                       NUM_ROWS LAST_ANALYZED
------------------------------ ---------- -------------------
P                                     399 2023-04-18 16:41:03

SQL> select table_name,partition_name,num_rows,last_analyzed from dba_tab_partitions where table_name='P';

TABLE_NAME                     PARTITION_NAME                   NUM_ROWS LAST_ANALYZED
------------------------------ ------------------------------ ---------- -------------------
P                              P1                                     99 2023-04-18 16:39:26
P                              P2                                    100 2023-04-18 16:39:26
P                              P3                                    100 2023-04-18 16:39:26
P                              P4                                    100 2023-04-18 16:39:26

SQL> 

全局统计信息时间更新了,但是分区统计信息还是旧的。

6、对某个分区收集统计信息,全局统计信息也会更新

SQL> exec dbms_stats.gather_table_stats(ownname=>'scott',tabname=>'p',PARTNAME=>'p1');

PL/SQL procedure successfully completed.

SQL> select table_name,num_rows,last_analyzed from dba_tables where table_name='P';

TABLE_NAME                       NUM_ROWS LAST_ANALYZED
------------------------------ ---------- -------------------
P                                     399 2023-04-18 16:42:26

SQL> select table_name,partition_name,num_rows,last_analyzed from dba_tab_partitions where table_name='P';

TABLE_NAME                     PARTITION_NAME                   NUM_ROWS LAST_ANALYZED
------------------------------ ------------------------------ ---------- -------------------
P                              P1                                     99 2023-04-18 16:42:26
P                              P2                                    100 2023-04-18 16:39:26
P                              P3                                    100 2023-04-18 16:39:26
P                              P4                                    100 2023-04-18 16:39:26

SQL> 


 

你可能感兴趣的:(oracle,数据库,sql)