1. 程式人生 > >oracle的統計資訊的檢視與收集

oracle的統計資訊的檢視與收集

檢視某個表的統計資訊

SQL> alter session set NLS_DATE_FORMAT='YYYY-MM-DD HH24:MI:SS';

Session altered.

SQL> select t.TABLE_NAME,t.NUM_ROWS,t.BLOCKS,t.LAST_ANALYZED from user_tables t where table_name in ('T1','T2');

TABLE_NAME                       NUM_ROWS     BLOCKS LAST_ANALYZED
------------------------------ ---------- ---------- -------------------
T1                                   2000         30 2017-07-16 14:02:23
T2                                   2000         30 2017-07-16 14:02:23

檢視某個表上索引的統計資訊
SQL> select table_name,index_name,t.blevel,t.num_rows,t.leaf_blocks,t.last_analyzed from user_indexes t where table_name in ('T1','T2');

TABLE_NAME     INDEX_NAME                 BLEVEL   NUM_ROWS LEAF_BLOCKS LAST_ANALYZED
-------------- ---------------------- ---------- ---------- ----------- -------------------
T1             IDX_T1_OBJ_ID                   1       2000           5 2017-07-16 12:06:33
T2             IDX_T2_OBJ_ID                   1       2000           5 2017-07-16 14:02:23
T2             IDX_T2_OBJ_TYPE                 1       2000           5 2017-07-16 14:02:23
T2             IDX_T2_OBJ_NAME                 1       2000           8 2017-07-16 14:02:23
T2             IDX_T2_DATA_OBJ_ID              1       1198           3 2017-07-16 14:02:23
T2             IDX_T2_STATUS                   1       2000           5 2017-07-16 14:02:23
T2             IDX_T2_CREATED                  1       2000           6 2017-07-16 14:02:23
T2             IDX_T2_LAST_DDL_TIME            1       2000           6 2017-07-16 14:02:23

8 rows selected.

oracle會在一個固定的時間將資料庫裡的表和索引的相關統計資訊進行收集,預設選擇週一到週五晚上10點,持續收集4小時,和週六週日早上6點,持續收集20小時。 oracle可以專門對錶的記錄變化量進行管理,當某表一天記錄變化量沒有超過指定的閥值時,oracle就不會對該表進行統計資訊收集。

修改統計資訊自動收集時間

SQL> set linesize 200
SQL> col REPEAT_INTERVAL for a60
SQL> col DURATION for a30
SQL> select t1.window_name,t1.repeat_interval,t1.duration from dba_scheduler_windows t1,dba_scheduler_wingroup_members t2
  2  where t1.window_name=t2.window_name and t2.window_group_name in ('MAINTENANCE_WINDOW_GROUP','BSLN_MAINTAIN_STATS_SCHED');

WINDOW_NAME        REPEAT_INTERVAL                                              DURATION
------------------ ------------------------------------------------------------ ---------------
MONDAY_WINDOW      freq=daily;byday=MON;byhour=22;byminute=0; bysecond=0        +000 04:00:00
TUESDAY_WINDOW     freq=daily;byday=TUE;byhour=22;byminute=0; bysecond=0        +000 04:00:00
WEDNESDAY_WINDOW   freq=daily;byday=WED;byhour=22;byminute=0; bysecond=0        +000 04:00:00
THURSDAY_WINDOW    freq=daily;byday=THU;byhour=22;byminute=0; bysecond=0        +000 04:00:00
FRIDAY_WINDOW      freq=daily;byday=FRI;byhour=22;byminute=0; bysecond=0        +000 04:00:00
SATURDAY_WINDOW    freq=daily;byday=SAT;byhour=6;byminute=0; bysecond=0         +000 20:00:00
SUNDAY_WINDOW      freq=daily;byday=SUN;byhour=6;byminute=0; bysecond=0         +000 20:00:00

7 rows selected.


關閉自動統計資訊收集
BEGIN
  DBMS_SCHEDULER.DISABLE(
  name => '"SYS"."SATURDAY_WINDOW"',
  force => TRUE);
END;
/


修改自動統計資訊持續時間
BEGIN
  DBMS_SCHEDULER.SET_ATTRIBUTE(
  name => '"SYS"."SATURDAY_WINDOW"',
  attribute => 'DURATION',
  value => numtodsinterval(240,'minute'));
END;  
/

修改自動統計資訊開始時間
BEGIN
  DBMS_SCHEDULER.SET_ATTRIBUTE(
  name => '"SYS"."SATURDAY_WINDOW"',
  attribute => 'REPEAT_INTERVAL',
  value => 'freq=daily;byday=SAT;byhour=22;byminute=0; bysecond=0 ');
END;
/

開啟自動統計資訊收集
BEGIN
  DBMS_SCHEDULER.ENABLE(
  name => '"SYS"."SATURDAY_WINDOW"');
END;
/


SQL> set linesize 200
SQL> col REPEAT_INTERVAL for a60
SQL> col DURATION for a30
SQL> select t1.window_name,t1.repeat_interval,t1.duration from dba_scheduler_windows t1,dba_scheduler_wingroup_members t2
  2  where t1.window_name=t2.window_name and t2.window_group_name in ('MAINTENANCE_WINDOW_GROUP','BSLN_MAINTAIN_STATS_SCHED');

WINDOW_NAME       REPEAT_INTERVAL                                              DURATION
----------------- ------------------------------------------------------------ --------------
MONDAY_WINDOW     freq=daily;byday=MON;byhour=22;byminute=0; bysecond=0        +000 04:00:00
TUESDAY_WINDOW    freq=daily;byday=TUE;byhour=22;byminute=0; bysecond=0        +000 04:00:00
WEDNESDAY_WINDOW  freq=daily;byday=WED;byhour=22;byminute=0; bysecond=0        +000 04:00:00
THURSDAY_WINDOW   freq=daily;byday=THU;byhour=22;byminute=0; bysecond=0        +000 04:00:00
FRIDAY_WINDOW     freq=daily;byday=FRI;byhour=22;byminute=0; bysecond=0        +000 04:00:00
SATURDAY_WINDOW   freq=daily;byday=SAT;byhour=22;byminute=0; bysecond=0        +000 04:00:00
SUNDAY_WINDOW     freq=daily;byday=SUN;byhour=6;byminute=0; bysecond=0         +000 20:00:00

7 rows selected.

手動收集統計資訊

收集表統計資訊

exec dbms_stats.gather_table_stats(ownname => 'USER',tabname => 'TEST',estimate_percent => 10,method_opt=> 'for all indexed columns');

exec dbms_stats.gather_table_stats(ownname => 'USER',tabname => 'TAB_NAME',CASCADE=>TURE);
收集分割槽表的某個分割槽統計資訊
exec dbms_stats.gather_table_stats(ownname => 'USER',tabname => 'RANGE_PART_TAB',partname => 'p_201312',estimate_percent => 10,method_opt=> 'for all indexed columns',cascade=>TRUE);
收集索引統計資訊
exec dbms_stats.gather_index_stats(ownname => 'USER',indname => 'IDX_OBJECT_ID',estimate_percent => '10',degree => '4');
收集表和索引統計資訊 
exec dbms_stats.gather_table_stats(ownname => 'USER',tabname => 'TEST',estimate_percent => 10,method_opt=> 'for all indexed columns',cascade=>TRUE);
收集某個使用者的統計資訊
exec dbms_stats.gather_schema_stats(ownname=>'CS',estimate_percent=>10,degree=>8,cascade=>true,granularity=>'ALL');
收集整個資料庫的統計資訊
exec dbms_stats.gather_database_stats(estimate_percent=>10,degree=>8,cascade=>true,granularity=>'ALL');
關於dbms_stats中引數的解釋,具體參考官方文件:

http://docs.oracle.com/cd/E11882_01/appdev.112/e40758/d_stats.htm#ARPLS68582

ownname: USER_NAME
tabname: TABLE_NAME
partname: 分割槽表的某個分割槽名
estimate_percent: 取樣百分比,有效範圍為[0.000001,100]
block_sample:使用隨機塊取樣代替隨機行取樣
method_opt:
cascade:是否收集此表索引的統計資訊
degree:並行處理的cpu數量
granularity: 統計資料的收集,'ALL' - 收集所有(子分割槽,分割槽和全域性)統計資訊
動態採集統計資訊

對於新建立的表,當訪問此表時,oracle會動態的收集這個表的相關資訊,等到晚上10點,再將其收集到資料字典中。

SQL> set autotrace off
SQL> set linesize 1000
SQL> drop table t_sample purge;
drop table t_sample purge
           *
ERROR at line 1:
ORA-00942: table or view does not exist


SQL> create table t_sample as select * from dba_objects;

Table created.

SQL> create index idx_t_sample_objid on t_sample(object_id);

Index created.
新建的表,查不到統計資訊
SQL> select num_rows, blocks, last_analyzed from user_tables where table_name = 'T_SAMPLE';

  NUM_ROWS     BLOCKS LAST_ANAL
---------- ---------- ---------

SQL> set autotrace traceonly
SQL> set linesize 1000
SQL> select  * from t_sample where object_id=20;


Execution Plan
----------------------------------------------------------
Plan hash value: 1453182238

--------------------------------------------------------------------------------------------------
| Id  | Operation                   | Name               | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |                    |     1 |   207 |     2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T_SAMPLE           |     1 |   207 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | IDX_T_SAMPLE_OBJID |     1 |       |     1   (0)| 00:00:01 |
--------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("OBJECT_ID"=20)

Note
-----
   - dynamic sampling used for this statement (level=2)


Statistics
----------------------------------------------------------
         24  recursive calls
          0  db block gets
         93  consistent gets
          1  physical reads
          0  redo size
       1608  bytes sent via SQL*Net to client
        523  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

- dynamic sampling used for this statement (level=2) 表示動態取樣,但是不記錄資料字典,除非手動收集表的統計資訊。
SQL> select num_rows, blocks, last_analyzed from user_tables where table_name = 'T_SAMPLE';

  NUM_ROWS     BLOCKS LAST_ANAL
---------- ---------- ---------


SQL>