Oracle 字段監控 ( column monitor)


Oracle 字段監控 ( column monitor)

從oracle9i開始,oracle為了監控column的使用情況,引入了col_usage$ 基表,該表會記錄 數據庫運行期間column作為謂詞被使用的情況,這些記錄信息會指導oracle如何生成column的 直方圖。

這是Oracle 本身原本的意圖,從另外一個角度上來講,我們可以以此為依據,判斷哪個字段上 應該建立索引。

1 開啟與關閉

Oracle通過隱藏參數"_column_tracking_level"控制此功能的開關:

0
禁用column tracking
1
啟用column tracking

此參數可以在session 或者system級別動態調整,不需要重新啟動數據庫。

2 字段說明

表字段可以通過desc col_usage$來查看。如:

sql> desc col_usage$
Table 1: col_usage$ 字段說明
字段 含義
OBJ# DBA_OBJECTS.OBJECT_ID
INTCOL#  
EQUALITY_PREDS 等值查詢
EQUIJOIN_PREDS 等值連接
NONEQUIJOIN_PREDS 不等值連接
RANGE_PREDS 范圍查詢
LIKE_PREDS 使用LIKE關鍵字查詢
NULL_PREDS 空值查詢
TIMESTAMP 時間戳

3 數據來源與清除

  • 插入
    • 自動 SMON里程每15分鍾將SGA中的內容刷新到col_usage$表中
    • 手動 調用DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO
  • 清除 在數據庫實例關閉的時候,smon會清除無效的行,比如某張表被刪除,與此表相關的信息 即為無效。

4 對直方圖的影響

從Oracle 10G 開始,收集表統計信息時,若采用 ”FOR ALL COLUMNS SIZE AUTO" 的方式。如果某張表的字段存在於COL_USAGE$中,數據庫就會認為有必要收集直方圖信息。

5 對建立索引的影響

開啟此功能后,我們可以對字段被用於查詢條件的情況進行區分統計。哪個字段被使用到, 被使用的頻率有多高,是用於連接還是范圍查詢等等。這些信息,對於我們創建索引,創 建什么類型的索引,是一個重要的依據。

6 Col_Usage$

6.0.1 表結構

我們先來看看這張表的結構。

create table col_usage$
(
  obj#              number,                                 /* object number */
  intcol#           number,                        /* internal column number */
  equality_preds    number,                           /* equality predicates */
  equijoin_preds    number,                           /* equijoin predicates */
  nonequijoin_preds number,                        /* nonequijoin predicates */
  range_preds       number,                              /* range predicates */
  like_preds        number,                         /* (not) like predicates */
  null_preds        number,                         /* (not) null predicates */
  timestamp         date      /* timestamp of last time this row was changed */
)
  storage (initial 200K next 100k maxextents unlimited pctincrease 0)
/
create unique index i_col_usage$ on col_usage$(obj#,intcol#)
  storage (maxextents unlimited)
/

6.0.2 COL_USAGE$字段說明

columen related to
obj# obj$.obj#
intcol# col$.col#
obj# 與基表obj$.obj# 相關聯
intcol# 與基表col$.col# 相關聯
preds 指的是predicate,也就是where條件語句中的條件。
equlity_preds 賦值條件
equijoin_preds 等值連接
nonequijoin_preds 非等值連接
range_preds 范圍查詢
like_preds 模糊查詢
null_preds 空值匹配查詢
timestamp COL_USAGE$ 表中該行數據更新時間

6.0.3 refresh COL_USAGE$(刷新基表)

  1. refresh automatically(自動刷新)

    字段訪問記錄被保存在SGA中,SMON 會每隔15分鍾將這些信息從內存中刷新至基表COL_USAGE$中。SMON進程會對該表進行插入、更新、刪除操作。當一個字段被首次訪問后,SMON在刷新內存信息時,會在表中插入一行新的數據,如果字段或者表被刪除,與其相關的字段信息會被SMON從COL_USAGE$中刪除。

  2. refresh manually(手動刷新)

    REFRESH THE TABLE(刷新COL_USAGE$)

    上面已經提及,SMON 進程會每隔15分鍾將SGA 中的字段訪問數據更新到COL_USAGE$表中。那么如果我們想得到最新的字段訪問數據,該怎么辦呢? Oracle 提供了一個包:DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO.

    exec dbms_stats.flush_database_monitoring_info;
    

6.0.4 利用COL_USAGE$表

在收集表的統計信息時,依據此表決定是否對某個字段收集直方圖。我們是否可以利用它呢? 不知道你是否遇到過這種場景:

你負責對優化數據庫,其中一個很重要的工作就是創建索引,但是你對業務邏輯和數據庫都不 太了解,這時你會怎么做? 如何決定哪個字段應該創建索引?

這種時候,這張表可以給我們提供相應的信息,因為它里面存儲了所有字段的訪問記錄。

col table_owner heading "Tab Owner" for a9
col table_name  heading "Table Name" for a30
col column_name heading "Col Name" for a20
col col_acc_num for 9999999
col indexed for a8

select u.name as table_owner,
       o.name as table_name,
       c.name as column_name,
       cu.equality_preds + cu.equijoin_preds + cu.nonequijoin_preds +
       cu.range_preds + cu.like_preds + cu.null_preds as col_acc_num,
       lpad(decode(ic.obj#, null, 'no', 'yes'),5,' ') as indexed,
       to_char(round(ratio_to_report(cu.equality_preds + cu.equijoin_preds +
                             cu.nonequijoin_preds + cu.range_preds +
                             cu.like_preds + cu.null_preds) over() * 100,
             2),'fm990.00') pct
  from sys.col_usage$ cu,
       sys.obj$ o,
       (select distinct obj#, intcol#, name, property from sys.col$) c,
       sys.user$ u,
       sys.icol$ ic
 where cu.obj# = o.obj#
   and cu.intcol# = c.intcol#
   and o.obj# = c.obj#
   and o.owner# = u.user#
   and c.intcol# = ic.intcol#(+)
   and c.obj# = ic.bo#(+)
   and u.name not in(
   'NONYMOUS','CTXSYS','DIP','DBSNMP','DMSYS','EXFSYS','MDDATA','MDSYS',
   'MGMT_VIEW','OLAPSYS','ORDPLUGINS','ORDSYS','OUTLN','SCOTT','SI_INFORMTN',
   '_SCHEMA','SYS','SYSMAN','SYSTEM','WK_TEST','WKPROXY','WKSYS','WMSYS'
   ,'XDB','TSMSYS','ORACLE_OCM')
   and o.name not like 'BIN$%'
order by 6
/

6.0.5 TEST(測試示例)

create table scott.t_halberd_colmon as select * from dba_objects;

 SELECT OBJECT_ID,OBJECT_NAME FROM DBA_OBJECTS WHERE OWNER='SCOTT' and object_type='TABLE';

 EXEC DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO;

 select * from col_usage$ where obj#=98581;

 exec dbms_stats.gather_table_stats(ownname=>'SCOTT',TABNAME=>'T_HALBERD_COLMON',METHOD_OPT=>'FOR ALL COLUMNS SIZE AUTO');

 SELECT table_name, column_name,histogram,num_distinct,num_buckets,sample_size,last_analyzed FROM DBA_TAB_COL_STATISTICS WHERE OWNER='SCOTT';

 SELECT COUNT(*) FROM SCOTT.T_HALBERD_COLMON WHERE OBJECT_ID < 200;

 EXEC DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO;

 select * from col_usage$ where obj#=98581;

 SELECT table_name, column_name,histogram,num_distinct,num_buckets,sample_size,last_analyzed FROM DBA_TAB_COL_STATISTICS WHERE OWNER='SCOTT';

 UPDATE SCOTT.T_HALBERD_COLMON SET OBJECT_ID = MOD(OBJECT_ID,25);

 EXEC DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO;

 select * from col_usage$ where obj#=98581;

 exec dbms_stats.gather_table_stats(ownname=>'SCOTT',TABNAME=>'T_HALBERD_COLMON',METHOD_OPT=>'FOR ALL COLUMNS SIZE AUTO');

 SELECT table_name, column_name,histogram,num_distinct,num_buckets,sample_size,last_analyzed FROM DBA_TAB_COL_STATISTICS WHERE OWNER='SCOTT';

 update scott.t1 set object_name=object_id;

 select count(*) from scott.t1 where object_name like '%4%';

 EXEC DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO;

 select * from col_usage$ where obj#=98581;

 exec dbms_stats.gather_table_stats(ownname=>'SCOTT',TABNAME=>'T_HALBERD_COLMON',METHOD_OPT=>'FOR ALL COLUMNS SIZE AUTO');

 SELECT table_name, column_name,histogram,num_distinct,num_buckets,sample_size,last_analyzed FROM DBA_TAB_COL_STATISTICS WHERE OWNER='SCOTT';

 exec dbms_stats.delete_table_stats(ownname=>'SCOTT',TABNAME=>'T_HALBERD_COLMON');

 SELECT table_name, column_name,histogram,num_distinct,num_buckets,sample_size,last_analyzed FROM DBA_TAB_COL_STATISTICS WHERE OWNER='SCOTT';

 select * from col_usage$ where obj#=98581;

 delete from col_usage$ where obj#=98581 and intcol#=1;

 exec dbms_stats.gather_table_stats(ownname=>'SCOTT',TABNAME=>'T_HALBERD_COLMON',METHOD_OPT=>'FOR ALL COLUMNS SIZE AUTO');

 SELECT table_name, column_name,histogram,num_distinct,num_buckets,sample_size,last_analyzed FROM DBA_TAB_COL_STATISTICS WHERE OWNER='SCOTT';

–如果在col_usgae$不存在對應記錄,在size auto模式下是不會生成直方圖的

Author: halberd

Created: 2019-06-22 Sat 13:58

Validate


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM