index


索引由 Oracle 服務器自動使用和維護,一旦一個索引被創建,它就不再需要用戶直接管理。rowid是一個十六進制的串,表示包含塊定義的行地址,行的位置在塊中,並且有數據庫文件標識符,訪問任何指定行的最快的方法是引用它的 rowid.

索引里存儲的內容: ROWID 、索引列(鍵值)。

創建索引可以大大提高系統的性能,總體來說,索引的優點如下所示:

  1. 大大加快數據的檢索速度,這也是創建索引的最主要的原因。
  2.  索引可以加速表和表之間的連接。
  3.  索引在實現數據的參照完整性方面特別有意義,例如在外鍵列上創建索引可以有效的避免死鎖的發生,
  4.  也可以防止當更新父表主鍵時,數據庫對子表的全表鎖定。
  5.  索引是減少磁盤 I/O 的許多有效手段之一。
  6.  當使用分組(GROUP BY)和排序(ORDER BY)子句進行數據檢索時,可以顯著減少查詢中分組和排序的時間,大大加快數據的檢索速度。
  7.  創建唯一性索引,可以保證數據庫表中每一行數據的唯一性。
  8.  通過使用索引,可以在查詢的過程中,使用優化隱藏器,提高系統的性能。

索引的缺點如下所示:

  1.  索引必須創建在表上,不能創建在視圖上。
  2.  創建索引和維護索引要耗費時間,這種時間隨着數據量的增加而增加。
  3.  建立索引需要占用物理空間,如果要建立聚簇索引,那么需要的空間會很大。
  4.  當對表中的數據進行增加、刪除和修改的時候,系統必須要有額外的時間來同時對索引進行更新維護,以維持數據和索引的一致性,所以,索引降低了數據的維護速度

索引的使用原則:

  1. 在大表上建立索引才有意義。
  2. 在 WHERE 子句或是連接條件經常引用的列上建立索引。
  3. 索引的層次不要超過 4 層。
  4. 如果某屬性常作為最大值和最小值等聚集函數的參數,那么考慮為該屬性建立索引。
  5. 表的主鍵、外鍵必須有索引
  6. 創建了主鍵和唯一約束后會自動創建唯一索引。
  7. 經常與其它表進行連接的表,在連接字段上應該建立索引。
  8. 經常出現在 WHERE 子句中的字段,特別是大表的字段,應該建立索引。
  9. 要索引的列經常被查詢,並只返回表中的行的總數的一小部分。
  10. 對於那些查詢中很少涉及的列、重復值比較多的列盡量不要建立索引。
  11. 經常出現在關鍵字 ORDER BY、GROUP BY、DISTINCT 后面的字段,最好建立索引。
  12. 索引應該建在選擇性高的字段上。
  13. 索引應該建在小字段上,對於大的文本字段甚至超長字段,不適合建索引。對於定義為 CLOB、TEXT、IMAGE 和 BIT 的數據類型的列不適合建立索引。
  14. 復合索引的建立需要進行仔細分析。正確選擇復合索引中的前導列字段,一般是選擇性較好的字段。
  15. 如果單字段查詢很少甚至沒有,那么可以建立復合索引;否則考慮單字段索引。
  16. 如果復合索引中包含的字段經常單獨出現在 WHERE 子句中,那么分解為多個單字段索引。
  17. 如果復合索引所包含的字段超過 3 個,那么仔細考慮其必要性,考慮減少復合的字段。
  18. 如果既有單字段索引,又有這幾個字段上的復合索引,那么一般可以刪除復合索引。
  19. 頻繁進行 DML 操作的表,不要建立太多的索引。
  20. 刪除無用的索引,避免對執行計划造成負面影響

一個表中定義一個列為主鍵,或者定義一個唯一鍵約束時 Oracle 服務器自動創建該索引,索引的名字習慣上是約束的名字

 另外,需要特別注意的是,索引不存儲空值

為什么不走索引(339頁詳解)

位圖索引

  1. 適合於決策支持系統(DSS)或 OLAP 系統。位圖索引主要用於數據倉庫,或在以特定方式引用很多列的查詢環境中。位圖索引並不適合許多 OLTP 應用程序,若使用不當則容易產生死鎖。
  2. 被索引的表是只讀的,或 DML 語句不會對其進行頻繁修改的表。
  3. 非常適合 OR 操作符的查詢。
  4. 位圖索引不直接存儲 ROWID,而是存儲字節位到 ROWID 的映射
  5. 減少響應時間。
  6. 節省空間占用。
  7. 在同一列上建立位圖索引后就不能再建立普通索引了,但是可以建立函數索引,位圖索引可以和函數索引同時建立。
  8. 做 UPDATE 代價非常高。
  9. 基於規則的優化器不會考慮位圖索引。
  10. 當執行 ALTER TABLE 語句並修改包含有位圖索引的列時,會使位圖索引失效。
  11. 位圖索引不包含任何列數據,並且不能用於任何類型的完整性檢查。
  12. 位圖索引不能被聲明為唯一索引。
  13. 位圖索引的最大長度為 30。
  14. 位圖索引適合創建在低基數列(即列值重復率很高)上。

函數索引

創建索引的函數里面不能使用 SUM、COUNT 等聚合函數
不能在 LOB 類型的列、NESTED TABLE 列上創建函數索引。
不能使用 SYSDATE、USER 等非確定性函數。
對於任何用戶自定義函數必須顯式的聲明 DETERMINISTIC 關鍵字,否則會報錯:“ora-30553: thefunction is not deterministic”
使用函數索引有幾個先決條件:
(1)必須擁有 CREATE INDEX 和 QUERY REWRITE(本模式下)或 CREATE ANY INDEX 和 GLOBAL QUERY REWRITE(其它模式下)權限。
(2)必須使用基於成本的優化器,基於規則的優化器將被忽略。
(3)參數 QUERY_REWRITE_INTEGRITY 和 QUERY_REWRITE_ENABLED 可以保持默認值

索引組織表(IOT)

索引中存儲的是行的實際數據,而不是 ROWID,它是基於主鍵訪問數據的。在索引組織表中,索引就是數據,數據就是索引

輔助索引(Secondary Indexes)也叫二級索引,是一個建立在索引組織表上的索引。在某種意義上,它是一個索引的索引。輔助索引是一個獨立的模式對象,並與索引組織表分開存儲。索引表上的輔助索引能夠非常有效地訪問索引表,這種索引既不是使用主鍵列也不是使用主鍵的某個前綴。Oracle 構造這種索引使用的是邏輯的行標識符(Logical Rowids),這種 ROWIDS 是基於表的主鍵(而不是基於行的物理地址)。這種邏輯 ROWIDS 包括了一個物理猜想(Physical Guess),它也是一種物理標識符(物理指針),它唯一標識行的塊地址,Oracle 能使用這些猜想直接對索引表的葉塊進行探測,從而避免主鍵搜索。

當創建 IOT 時,必須要設定主鍵,否則報錯。

 分區索引

如果使用了位圖索引,那么就必須是本地索引
本地分區索引可分為以下類別:

  • 本地前綴索引(Local Prefixed Indexes)在這種情況下,分區鍵處於索引定義的前導部分。
  • 本地非前綴索引(Local Nonprefixed Indexes)在這種情況下,分區鍵不是索引列列表的前導部分,甚至根本不必在該列表中。
CREATE INDEX IDX_PART_RANGE_ID ON T_PARTITION_RANGE(ID) LOCAL (
PARTITION I_RANGE_P1 TABLESPACE TS_DATA01,
PARTITION I_RANGE_P2 TABLESPACE TS_DATA02,
PARTITION I_RANGE_P3 TABLESPACE TS_DATA03,
PARTITION I_RANGE_PMAX TABLESPACE TS_DATA04
);

全局分區索引是一個 B-Tree 索引,全局索引(Global Index)既可以分區(全局分區索引),也可以不分區(普通索引),既可以建 RANGE分區,也可以建 HASH 分區,既可創建於分區表上,也可以創建於非分區表上,就是說,全局索引是完全獨立的,因此,它也需要更多的維護操作

  • 全局索引可以依附於分區表,也可以依附於非分區表。
  • 全局分區索引的索引條目可能指向若干個分區,因此,對於全局分區索引,即使只截斷一個分區中的數據,也需要 REBULID 若干個分區甚至是整個索引。
  • 全局索引多應用於 OLTP 系統中。
  • 全局分區索引只按 RANGE 或者 HASH 分區,HASH 分區是 Oracle 10g 以后才支持的。
  • 在 Oracle 9i 以后對分區表做 MOVE 或者 TRUNCATE 的時候可以用 UPDATE GLOBAL INDEXES 語句來同步更新全局分區索引,用消耗一定資源來換取高度的可用性。
  • 若在表中使用 A 列作分區,但在索引中用 B 列作本地索引,若 WHERE 條件中用 B 來查詢,那么 Oracle會掃描所有的表和索引的分區,成本會比分區更高,此時可以考慮用 B 列做全局分區索引和用 A 列做本地索引。
  • 在創建索引時,如果不顯式指定 GLOBAL 或 LOCAL,那么默認是 GLOBAL。
  • 在創建 GLOBAL 索引時,如果不顯式指定分區子句,那么默認不分區。
  • 含有子分區的分區索引有大小,但是在數據字典視圖中的列 SEGMENT_CREATED 的值顯示為 N/A,STATUS 的值也顯示為 N/A。

Truncate 分區操作會導致全局索引失效; truncate 普通表對索引沒有影響;

Truncate 分區操作不會釋放全局索引中的空間,而truncate 普通表會釋放索引所占空間;

rename 表名操作對索引沒有影響,因為rename操作只是更改了數據字典,表中數據行的rowid並沒有發生變化

全文索引

Oracle 全文索引使 Oracle 具備了強大的文本檢索能力和智能化的文本管理能力。Oracle 將全文檢索功能做為內置功能提供給用戶,使得用戶在創建數據庫實例時自動安裝全文檢索。要使用 Oracle 全文索引,必須具有 CTXAPP 角色或者是 CTXSYS 用戶。Oracle 全文索引為系統管理員提供 CTXSYS 用戶,為應用程序開發人員提供 CTXAPP 角色。具有 CTXAPP 角色的用戶可以使用全文索引

 虛擬索引

不可見索引

ALTER INDEX INDEX_NAME INVISIBLE; --修改索引不可見
ALTER INDEX INDEX_NAME VISIBLE; --修改索引可見

不可見索引的特點主要有以下幾點:
(1)當索引變更為不可見的時候,只是對 Oracle 的優化器不可見。
(2)不可見索引在 DML 操作的時候也會被維護。
(3)加 HNIT 對不可見索引無效。
(4)可以通過修改 SYSTEM 級別和 SESSION 級別參數來使用不可見索引。

反向鍵索引(Reverse Key Indexes) 

只有對反向鍵索引列進行“=”操作時,其反向鍵索引才會使用。(在 WHERE 子句中使用“BETWEEN AND”語句或比較運算符“>”、“<”、“>=”、“<=”等),那么反向鍵索引將不會被使用

反向鍵索引應用場合:
1、在索引葉塊成為熱點塊時使用
2、在 RAC 環境中使用
3、反向鍵索引通常建立在值是連續增長的列上,使數據均勻地分布在整個索引上。

創建索引
create index emp_last_name_idx on employees(last_name) online parallel 2;            ---普通單列索引
CREATE INDEX IDX_CI_emp ON employees(OBJECT_ID,OBJECT_TYPE);     ---復合索引(一般情況下,把最常被訪問和選擇性較高的列放在前面)
CREATE INDEX upper_last_name_idx ON employees(UPPER(last_name));          ---函數索引
CREATE BITMAP INDEX IDX_SEX_LHR ON T_USER(SEX);              ---創建位圖索引
CREATE TABLE IND_ORG_TAB_LHR(VENCODE NUMBER(4) PRIMARY KEY,VENNAME VARCHAR2(20)) ORGANIZATION INDEX;        ---索引組織表
CREATE INDEX DOC_INDEX_LHR ON XT_DOCS_LHR(TEXT) INDEXTYPE IS CTXSYS.CONTEXT;           ---創建全文索引
CREATE INDEX REV_INDEX_LHR ON XT_REVI_LHR(OBJECT_ID) REVERSE;                  ---創建反向鍵索引

DROP INDEX IDX_NAME_LHR FORCE;                ---刪除索引

查看索引信息

SELECT IC.INDEX_NAME,IC.COLUMN_NAME,IC.COLUMN_POSITION COL_POS,IX.UNIQUENESS FROM USER_INDEXES IX, USER_IND_COLUMNS IC WHERE IC.INDEX_NAME = IX.INDEX_NAME
AND IC.TABLE_NAME = 'EMPLOYEES';                      ---查詢某個表上的索引

SELECT D.INDEX_NAME,D.TABLE_NAME,D.COLUMN_NAME FROM DBA_IND_COLUMNS D WHERE D.INDEX_NAME='IDX_CI_20170628_LHR';  ---查詢復合索引列

SELECT * FROM DBA_INDEXES D WHERE D.INDEX_TYPE LIKE 'FUNCTION-BASED%';  ---查詢所有的函數索引

SELECT * FROM DBA_INDEXES D WHERE D.INDEX_TYPE='BITMAP';           ---查詢所有的位圖索引
SELECT * FROM DBA_INDEXES D WHERE D.JOIN_INDEX='YES';              ---查詢所有的位圖連接索引

SELECT * FROM DBA_TABLES D WHERE D.IOT_TYPE='IOT';               ---查詢所有的IOT表

SELECT * FROM DBA_INDEXES D WHERE D.INDEX_TYPE LIKE '%/REV'; ---查詢反向鍵索引

 獲取索引定義

select dbms_metadata.get_ddl('INDEX','INDEX_NAME','INDEX_OWNER') from dual;

索引選擇性

 

SELECT INDEX_NAME,DISTINCT_KEYS/NUM_ROWS SELECTIVITY FROM DBA_INDEXES;
毋庸置疑,主鍵的選擇性為 1。選擇性越接近 1,那么該索引就越好。

 

查詢索引大小

select owner,segment_name,(sum(bytes)/1024/1024)||'MB',tablespace_name from dba_segments where segment_name = 'IDX_T'  group by owner,segment_name,tablespace_name;

---查詢大索引
col owner for a10
col segment_name for a32
select * from (select owner,segment_name,bytes/1024/1024 SIZE_MB from dba_segments where owner in ('TEST') and segment_type like '%INDEX%' order by 3 desc) where rownum < 11;

Oracle 11gR2 中使用 EXPLAIN PLAN FOR CREATE INDEX 時,Oracle會提示評估的索引大小(ESTIMATED INDEX SIZE)

EXPLAIN PLAN FOR CREATE INDEX IDX_T ON SYS.TEST_INDEX_SIZE(OBJECT_ID);
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY());

查詢索引碎片比例

analyze index ID_IND validate structure;  ---下面語句不要在其他會話查詢
select name,del_lf_rows,lf_rows, round(del_lf_rows/decode(lf_rows,0,1,lf_rows)*100,0)||'%' frag_pct from index_stats where round(del_lf_rows/decode(lf_rows,0,1,lf_rows)*100,0)>30;
注意:x$kdxstoracle的一個內存表,然后analyze index indexname validate structure這條語句會往x$kdxst寫一些統計信息,當執行select * from x$kdxst的時候,oracle這里實際上是把你執行analyze index indexname validate structure時的那個indexname給當作綁定變量給傳進來了,所以你只能看到你執行analyze index indexname validate structure的那個index的統計信息。也就是只有在執行過analyze index indexname validate structure后且在同一個session下才能從index_stats中看到數據

索引失效情況:

當某些操作導致數據行的 ROWID 改變,索引就會完全失效。可以分普通表和分區表來討論哪些操作將導致索引失效。

(1)普通表索引失效的情形如下所示:

1、手動置索引無效:ALTER INDEX IND_OBJECT_ID UNUSABLE;。

2、如果對表進行 MOVE 操作(包含移動表空間和壓縮操作)或在線重定義表后,那么該表上所有的索引狀態會變為 UNUSABLE。MOVE 操作的 SQL 語句為:ALTER TABLE TT MOVE;。

3、SQL*Loader加載數據。在SQL*Loader加載過程中會維護索引,由於數據量比較大,在SQL*Loader加載過程中出現異常情況,也會導致Oracle來不及維護索引,導致索引處於失效狀態,影響查詢和加載。異常情況主要有:在加載過程中殺掉 SQL*Loader 進程、重啟或表空間不足等。

(2)分區表索引失效的情形如下所示:

1、對分區表的某個含有數據的分區執行了 TRUNCATE、DROP 操作可以導致該分區表的全局索引失效,而分區索引依然有效,如果操作的分區沒有數據,那么不會影響索引的狀態。需要注意的是,對分區表的 ADD 

操作對分區索引和全局索引沒有影響。

2 執行 EXCHANGE 操作后,全局索引和分區索引都無條件地會被置為 UNUSABLE(無論分區是否含有數據)。但是,若包含 INCLUDING INDEXES 子句(缺省情況下為 EXCLUDING 

INDEXES),則全局索引會失效,而分區索引依然有效。

3 如果執行 SPLIT 的目標分區含有數據,那么在執行 SPLIT 操作后,全局索引和分區索引都會被被置為UNUSABLE。如果執行 SPLIT 的目標分區沒有數據,那么不會影響索引的狀態。

4 對分區表執行 MOVE 操作后,全局索引和分區索引都會被置於無效狀態。

5 手動置其無效:ALTER INDEX IND_OBJECT_ID UNUSABLE;。對於分區表而言,除了 ADD 操作之外,TRUNCATE、DROP、EXCHANGE 和 SPLIT 操作均會導致全局索引失

效,但是可以加上 UPDATE GLOBAL INDEXES 子句讓全局索引不失效。重建分區索引的命令為:ALTER INDEX IDX_RANG_LHR REBUILD PARTITION P1;。

列出失效索引或索引分區

select owner, index_name, status From dba_indexes where status='UNUSABLE' and owner in ('FENG') order by 1,2;
select index_owner,index_name,partition_name,subpartition_name from dba_ind_subpartitions where status='unusable' and index_owner in('FENG');

重建索引

 

alter index indexname rebuild online tablespace t1;
alter index indexname rebuild partition paritionname tablespace tablespacename; alter index indexname rebuild subpartition partitioname tablespace tablespacename;
alter index index_name coalesce
1、rebuild以index fast full scan(or table full scan) 方式讀取原索引中的數據來構建一個新的索引,有排序的操作; rebuild online 執行表掃描獲取數據,有排序的操作; 2、rebuild 會阻塞 dml 操作 ,rebuild online 不會阻塞 dml 操作; 3、rebuild online 時系統會產生一個 SYS_JOURNAL_xxx 的 IOT 類型的系統臨時日志表,所有 rebuild online 時索引的變化都記錄在這個表中,當新的索引創建完成后,把這個表的記錄維護到新的索引中去,然后 drop 掉舊的索引 4、Rebuild操作會產生大量redo log;
5、使用帶有coalesce參數時重建期間不需要額外空間,它只是在重建索引時將處於同一個索引分支內的葉塊拼合起來,這最大限度的減少了與查詢過程中相關的潛在的加鎖問題,但是,coalesce選項不能用來將一個索引轉移到其他表空間。

 

 

監控索引使用情況

監控索引一般有兩種方式:

1)直接監控索引的使用情況

1)設置所要監控的索引:ALTER INDEX IDX_T_XX MONITORING USAGE;

2)查看該索引有沒有被使用:SELECT * FROM V$OBJECT_USAGE;

3)關閉監控:ALTER INDEX IDX_T_XX NOMONITORING USAGE;

2schema級別索引監控

如果想在系統中監控所有的索引,可以通過下面腳本實現監控數據庫所有的索引。注意我們要排除一些系統表的索引、以及LOB indexes。可以直接執行腳本來開啟索引監控,當然監控索引時長非常重要,太短的話有可能導致查詢出來的數據有問題,一般建議監控一周后即可,OLAP系統則需要適當延長監控的時間。

--1、開啟索引監控
SELECT 'ALTER INDEX ' || owner || '.' || index_name || ' MONITORING USAGE;' enable_monitor,
       'ALTER INDEX ' || owner || '.' || index_name ||
       ' NOMONITORING USAGE;' disable_monitor
  FROM dba_indexes
 WHERE INDEX_TYPE != 'LOB'
   and owner IN
       (SELECT username FROM dba_users WHERE account_status = 'OPEN')
   AND owner NOT IN ('SYS', 'SYSTEM', 'PERFSTAT', 'MGMT_VIEW', 'MONITOR',
        'SYSMAN', 'DBSNMP')
   AND owner not like '%SYS%';
--2、查詢數據庫中所有被監控索引的使用情況
SELECT U.NAME OWNER,
       IO.NAME INDEX_NAME,
       T.NAME TABLE_NAME,
       DECODE(BITAND(I.FLAGS, 65536), 0, 'NO', 'YES') MONITORING,
       DECODE(BITAND(OU.FLAGS, 1), 0, 'NO', 'YES') USED,
       OU.START_MONITORING START_MONITORING,
       OU.END_MONITORING END_MONITORING
  FROM SYS.USER$        U,
       SYS.OBJ$         IO,
       SYS.OBJ$         T,
       SYS.IND$         I,
       SYS.OBJECT_USAGE OU
 WHERE I.OBJ# = OU.OBJ#
   AND IO.OBJ# = OU.OBJ#
   AND T.OBJ# = I.BO#
   AND U.USER# = IO.OWNER#;
--3、歷史執行計划分析索引使用情況
WITH TMP1 AS
(SELECT I.OWNER INDEX_OWNER,
I.TABLE_OWNER,
TABLE_NAME,
INDEX_NAME,
INDEX_TYPE,
(SELECT NB.CREATED
FROM DBA_OBJECTS NB
WHERE NB.OWNER = I.OWNER
AND NB.OBJECT_NAME = I.INDEX_NAME
AND NB.SUBOBJECT_NAME IS NULL
AND NB.OBJECT_TYPE = 'INDEX') CREATED,
(SUM(S.BYTES) / 1024 / 1024) INDEX_MB,
(SELECT COUNT(1)
FROM DBA_IND_COLUMNS DIC
WHERE DIC.INDEX_NAME = I.INDEX_NAME
AND DIC.TABLE_NAME = I.TABLE_NAME
AND DIC.INDEX_OWNER = I.OWNER) COUNT_INDEX_COLS
FROM DBA_SEGMENTS S, DBA_INDEXES I
WHERE I.INDEX_NAME = S.SEGMENT_NAME
AND I.OWNER = S.OWNER
AND S.OWNER NOT LIKE '%SYS%'
GROUP BY I.OWNER, I.TABLE_OWNER, TABLE_NAME, INDEX_NAME, INDEX_TYPE
HAVING SUM(S.BYTES) > 1024 * 1024),
TMP2 AS
(SELECT INDEX_OWNER,
INDEX_NAME,
PLAN_OPERATION,
(SELECT MIN(TO_CHAR(NB.BEGIN_INTERVAL_TIME, 'YYYY-MM-DD HH24:MI:SS'))
FROM DBA_HIST_SNAPSHOT NB
WHERE NB.SNAP_ID = V.MIN_SNAP_ID) MIN_DATE,
(SELECT MAX(TO_CHAR(NB.END_INTERVAL_TIME, 'YYYY-MM-DD HH24:MI:SS'))
FROM DBA_HIST_SNAPSHOT NB
WHERE NB.SNAP_ID = V.MAX_SNAP_ID) MAX_DATE,
COUNTS
FROM (SELECT D.OBJECT_OWNER INDEX_OWNER,
D.OBJECT_NAME INDEX_NAME,
D.OPERATION || ' ' || D.OPTIONS PLAN_OPERATION,
MIN(H.SNAP_ID) MIN_SNAP_ID,
MAX(H.SNAP_ID) MAX_SNAP_ID,
COUNT(1) COUNTS
FROM DBA_HIST_SQL_PLAN D, DBA_HIST_SQLSTAT H
WHERE D.OPERATION LIKE '%INDEX%'
AND D.SQL_ID = H.SQL_ID
GROUP BY D.OBJECT_OWNER, D.OBJECT_NAME, D.OPERATION, D.OPTIONS) V)
SELECT A.TABLE_OWNER,
A.TABLE_NAME,
A.INDEX_OWNER,
A.INDEX_NAME,
A.CREATED,
A.INDEX_TYPE,
A.INDEX_MB,
A.COUNT_INDEX_COLS,
B.PLAN_OPERATION,
CASE
WHEN MIN_DATE IS NULL THEN
(SELECT MIN(TO_CHAR(NB.BEGIN_INTERVAL_TIME, 'YYYY-MM-DD HH24:MI:SS'))
FROM DBA_HIST_SNAPSHOT NB)
ELSE
MIN_DATE
END AS MIN_DATE,
CASE
WHEN MAX_DATE IS NULL THEN
(SELECT MAX(TO_CHAR(NB.BEGIN_INTERVAL_TIME, 'YYYY-MM-DD HH24:MI:SS'))
FROM DBA_HIST_SNAPSHOT NB)
ELSE
MAX_DATE
END AS MAX_DATE,
COUNTS
FROM TMP1 A
LEFT OUTER JOIN TMP2 B
ON (A.INDEX_OWNER = B.INDEX_OWNER AND A.INDEX_NAME = B.INDEX_NAME);

 查看某個表索引使用情況

某個用戶的某個表的索引信息
--get the index column information by specified table set linesize 180 col cl_nam format a20 col table_name format a25 col cl_pos format 9 col idx_typ format a15 SELECT b.table_name, a.index_name, a.column_name cl_nam, a.column_position cl_pos, b.status, b.index_type idx_typ, a.descend dscd FROM dba_ind_columns a, dba_indexes b WHERE a.index_name = b.index_name AND owner = upper('&owner') AND a.table_name LIKE upper('%&table_name%') ORDER BY 2, 4;

--
查看某個表索引使用情況 SELECT p.object_name, p.operation, p.options, COUNT(1) FROM v$sql_plan p, v$sql s WHERE p.object_owner <> 'SYS' AND p.OBJECT_NAME in (select index_name from dba_indexes where table_name = 'S_SHIP_UNIT_LINE') AND p.sql_id = s.sql_id GROUP BY p.object_name, p.operation, p.options ORDER BY 1, 2, 3; --查看歷史索引使用情況 SELECT p.object_name, p.operation, p.options, COUNT(1) FROM dba_hist_sql_plan p, dba_hist_sqlstat s WHERE p.object_owner <> 'SYS' AND p.object_name in (select index_name from dba_indexes where table_name = 'S_SHIP_UNIT_LINE') AND p.sql_id = s.sql_id GROUP BY p.object_name, p.operation, p.options ORDER BY 1, 2, 3;

 

 

 

附錄:

1、獲得索引使用頻率腳本(idx_usage_detail.sql

set linesize 140
set pagesize 160
 
clear breaks
clear computes
 
break on TABLE_NAME skip 2 ON INDEX_NAME ON INDEX_TYPE ON MB
compute sum of NR_EXEC on TABLE_NAME SKIP 2
compute sum of MB on TABLE_NAME SKIP 2
 
 
SET TIMI OFF
set linesize 140
set pagesize 10000
set verify off
col OWNER noprint
col TABLE_NAME for a30 heading 'Table name'
col INDEX_NAME for a30 heading 'Index name'
col INDEX_TYPE for a15 heading 'Index type'
col INDEX_OPERATION for a21 Heading 'Index operation'
col NR_EXEC for 9G999G990 heading 'Executions'
col MB for 999G990D90 Heading 'Index|Size MB' justify  right
 
        WITH Q AS (
                SELECT
                       S.OWNER                  A_OWNER,
                       TABLE_NAME               A_TABLE_NAME,
                       INDEX_NAME               A_INDEX_NAME,
                       INDEX_TYPE               A_INDEX_TYPE,
                       SUM(S.bytes) / 1048576   A_MB
                  FROM DBA_SEGMENTS S,
                       DBA_INDEXES  I
                 WHERE S.OWNER =  '&&1'
                   AND I.OWNER =  '&&1'
                   AND INDEX_NAME = SEGMENT_NAME
                 GROUP BY S.OWNER, TABLE_NAME, INDEX_NAME, INDEX_TYPE
                HAVING SUM(S.BYTES) > 1048576 * &&2
        )
        SELECT /*+ NO_QUERY_TRANSFORMATION(S) */
               A_OWNER                                    OWNER,
               A_TABLE_NAME                               TABLE_NAME,
               A_INDEX_NAME                               INDEX_NAME,
               A_INDEX_TYPE                               INDEX_TYPE,
               A_MB                                       MB,
               DECODE (OPTIONS, null, '       -',OPTIONS) INDEX_OPERATION,
               COUNT(OPERATION)                           NR_EXEC
         FROM  Q,
               DBA_HIST_SQL_PLAN d
         WHERE
               D.OBJECT_OWNER(+)= q.A_OWNER AND
               D.OBJECT_NAME(+) = q.A_INDEX_NAME
        GROUP BY
               A_OWNER,
               A_TABLE_NAME,
               A_INDEX_NAME,
               A_INDEX_TYPE,
               A_MB,
               DECODE (OPTIONS, null, '       -',OPTIONS)
        ORDER BY
               A_OWNER,
               A_TABLE_NAME,
               A_INDEX_NAME,
               A_INDEX_TYPE,
               A_MB DESC,
               NR_EXEC DESC
;
 
PROMPT "Showed only indexes in &&1 schema whose size > &&2 MB in period:"
 
SET HEAD OFF;
select to_char (min(BEGIN_INTERVAL_TIME), 'DD.MM.YYYY')
       || '-' ||
       to_char (max(END_INTERVAL_TIME), 'DD.MM.YYYY')
from dba_hist_snapshot;
 
SET HEAD ON
SET TIMI ON

2、索引質量分析腳本

--1、script name: idx_quality.sql     
--Author : Leshami  
--index quality retrieval
SET LINESIZE 145
SET PAGESIZE 1000
SET VERIFY OFF
 
CLEAR COMPUTES
CLEAR BREAKS
 
BREAK ON table_name ON num_rows ON blocks
 
COLUMN owner FORMAT a14 HEADING 'Index owner'
COLUMN table_name FORMAT a25 HEADING 'Table'
COLUMN index_name FORMAT a25 HEADING 'Index'
COLUMN num_rows FORMAT 999G999G990 HEADING 'Table|Rows'
COLUMN MB FORMAT 9G990 HEADING 'Index|Size MB'
COLUMN blocks HEADING 'Table|Blocks'
COLUMN num_blocks FORMAT 9G990 HEADING 'Data|Blocks'
COLUMN avg_data_blocks_per_key FORMAT 999G990 HEADING 'Data Blks|per Key'
COLUMN avg_leaf_blocks_per_key FORMAT 999G990 HEADING 'Leaf Blks|per Key'
COLUMN clustering_factor FORMAT 999G999G990 HEADING 'Clust|Factor'
COLUMN Index_Quality FORMAT A13 HEADING 'Index|Quality'
 
--SPOOL index_quality
SELECT i.table_name,
         t.num_rows,
         t.blocks,
         i.index_name,
         o.bytes / 1048576 mb,
         i.avg_data_blocks_per_key,
         i.avg_leaf_blocks_per_key,
         i.clustering_factor,
         CASE
            WHEN NVL (i.clustering_factor, 0) = 0 THEN '0-No Stats'
            WHEN NVL (t.num_rows, 0) = 0 THEN '0-No Stats'
            WHEN (ROUND (i.clustering_factor / t.num_rows * 100)) < 6 THEN '5-Excellent'
            WHEN (ROUND (i.clustering_factor / t.num_rows * 100)) BETWEEN 7 AND 11 THEN '4-Very Good'
            WHEN (ROUND (i.clustering_factor / t.num_rows * 100)) BETWEEN 12 AND 15 THEN '2-Good'
            WHEN (ROUND (i.clustering_factor / t.num_rows * 100)) BETWEEN 16 AND 25 THEN '2-Fair'
            ELSE '1-Poor'
         END
            index_quality
    FROM dba_indexes i, dba_segments o, dba_tables t
   WHERE 
     --    i.index_name LIKE UPPER ('%&&1%') AND
         i.owner = t.owner
         AND i.table_name = t.table_name
         AND i.owner = o.owner
         AND i.index_name = o.segment_name
         AND t.owner = UPPER('&input_owner')
         AND t.table_name LIKE UPPER('%&input_tbname%')
ORDER BY table_name,
         num_rows,
         blocks,
         index_quality DESC;
 
--SPOOL OFF;
==============================================================

--2、獲取指定schema或表上的索引質量信息報告
SQL> @idx_quality.sql
Enter value for input_owner: RFUSER
Enter value for input_tbname: TAB_GOODSLABEL --省略具體的表名則會輸出整個schema的索引質量報告

 

 


免責聲明!

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



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