什麼是索引
索引是建立在表的一列或多個列上的輔助對象, 目的是加快訪問表中的數據。
oracle存儲索引的數據結構是B樹,位圖索引(Bitmap索引)也是如此,只不過是葉子節點不同B樹索引。
Bitmap索引:索引由根節點,分支節點和葉子節點組成,上級索引塊包含下級索引快的索引數據,葉節點包含索引數據和確定行實際位置的rowid.
oracle中最常用的索引就倆種:B樹索引和位圖索引。
B樹索引在oracle中是一個通用的索引,在創建索引時他就是默認的類型,最多可以包含32列。
一般情況下,大多數用戶都只創建TYPE爲NORMAL的B樹索引,所以對於較低基數的列我們都是不創建索引的,
因爲B-樹索引對查詢速度提升不一定會有改善,甚至會增加INSERT,UPDATE,DELETE 命令所消耗的時間。
位圖索引爲oracle每一個鍵創建一個位圖,然後把與鍵值所關聯的ROWID保存爲位圖,最多可以包含30列。
位圖索引在加載表(插入操作)時,通常要比B樹索引做得好。通常,位圖索引要比一個低基數(很少不同值)上的B樹索引要快3~4倍。
但如果新增的值佔插入行的70%以上時,B樹索引通常會更快一些。當每條記錄都增加一個新值時,B樹索引要比位圖索引快3倍。
建議
建議不要在一些聯機事務處理(OLTP)應用程序中使用位圖索引。B樹索引的索引值包含ROWID,這樣oracle就可以在行級別上鎖定索引。
位圖索引被存儲爲壓縮的索引值,其中包含了一個範圍的ROWID,因此ROWID必須對一個給定值鎖定所有範圍內的ROWID。
這種鎖定可能會使某些DML語句中造成死鎖。SELECT語句不會受到這種鎖定問題的影響。
位圖索引有很多限制
1 基於規則的優化器不會考慮位圖索引
2 當執行ALTER TABLE語句,並修改包含有位圖索引的列時,會使位圖索引失效
3 位圖索引在索引塊中存儲了索引鍵的值,然而,他們並不能完成用戶任何類型的檢查
使用索引的目的
加快查詢速度,減少I/O操作
I/O操作:設備與cpu連接的接口電路的操作。
索引的種類
非唯一索引,唯一索引,位圖索引,局部有前綴分區索引,局部無前綴分區索引,
全局有前綴分區索引,散列分區索引,基於函數的索引
管理索引的準則
在表中插入數據後創建準則
在用SQL*LOADER(工具)或import工具插入或裝載數據後,建立索引比較有效
索引正確的表和列
列中的值相對比較唯一
取值範圍(大:B樹索引,小:位圖索引)
Date型列一般適合基於函數的索引
列中有許多空值,不適合建立索引
爲性能而安排索引列
經常一起使用多個字段檢索記錄,組合索引比單索引更有效。
把最常用的列放在最前面,例:dx_groupid_serv_id(groupid,serv_id),在where條件中使用groupid或serv_id,
查詢將使用索引,若僅用到serv_id字段,則索引無效。
合併/拆分不必要的索引
限制每個表索引的數量
一個表可以有幾百個索引,但是對於頻繁的插入和更新表,索引越多系統CPU,I/O負擔就越重。
建議每張表不超過5個索引。
刪除不再需要的索引。
索引無效,集中表現在該使用基於函數的索引或位圖索引,而使用了B樹索引。
應用中的查詢不使用索引。
重建索引之前必須先刪除索引,若用alter index ...rebuild 重建索引,則不必刪除索引。
索引數據塊空間使用
創建索引時指定表空間,特別是在建立主鍵時,應明確指定表空間。
合理設定pctfress,注意:不能給索引指定pctused。
pctfress:爲一個塊保留的空間百分比,表示數據塊在什麼情況下可以被insert,默認是10,
表示當數據塊的可用空間低於10%後,就不可以被insert了,只能被用於update。
即當使用一個bolck時,在達到pctfree之前,該block是一直可以被插入的,這個時候處在上升期。
pctused:是指當塊裏的數據低於多少百分比時,又可以重新被insert,一般默認是40,即40%,
即當數據低於40%時,又可以寫入新的數據,這個時候處在下降期。
考慮並行創建索引
對大表可以採取並行創建索引,在並行創建索引時,存儲參數被每個查詢服務器進程分別使用,
例如:initial爲1M,並行度爲8,則創建索引期間至少要消耗8M空間。
考慮用nologging創建索引
對大表創建索引時可以用弄logging來減少重做日誌。
節省重做日誌文的空間。
縮短創建索引的時間。
改善了並行創建大索引時的性能。
怎樣建立最佳索引
明確的創建索引
create index index_name on table_name (field_name)
tablespace tablespace_name
pctfree 5
initrans 2
maxtrans 255
storge
(
minextents 1
maxextents 16382
pctincrease 0
)
initrans:每個塊都有一個塊首部。事務表中會建立一些條目來描述哪些事務將塊上的哪些行/元素鎖定。
這個事務表的初始大小由對象initrans設定指定。 對於表,這個值默認爲1,索引的initrans默認爲2。
創建基於函數的索引
常用語UPPER,LOWER,TO_CHAR(date)等函數分類上, 例
create index idx_func on emp(UPPER(ename)) tablespace tablespace_name
創建位圖索引
對於基數較小,且基數相對穩定的列建立索引時,首先應該考慮位圖索引,例
create bitmap index idx_bitm on class(classno) tablespace tablespace_name
明確地創建唯一索引
唯一索引:一種索引,不允許具有索引值相同的,從而禁止重複的索引或鍵值。
系統在創建該索引時檢查是否有重複的鍵值,並在每次使用insert和update語句添加數據時進行檢查。
可以用create unique index 語句來創建唯一索引,例
create unique index dept_unique_idx on dept(dept_no) tablespace idx_1;
創建與約束相關的索引
可以用using index字句,爲與unique和primary key約束相關的索引,例如:
alter table table_name
add constraint PK_primary_keyname primary key (field_name)
using index tablespace tablespace_name;
建立索引的代價
基礎表維護時,系統要同時維護索引,不合理的索引將嚴重影響系統資源,主要表現在CPU和I/0上
插入,更新,刪除數據產生大量db file sequential read鎖等待
db file sequential read:??db file sequential read等待事件有3個參數,file#,first block#,和block#數量。
在10g中,這等待事件受到用戶I/O等級別的影響。當處理db file sequential read等待事件的時候,牢記以下關鍵想法。
oracle進程需要一個當前不在SGA中的塊,等待數據塊從磁盤讀入到SGA中。
要看的倆個重要的數字是單獨會話和TIME_WAITED和AVERAGE_WAIT
重要db file sequential read等待時間最可能是一個應用問題。
下面是一些常見的索引限制問題
使用不等於操作符(<>,!=)
即使在列dept_id有一個索引,查詢語句扔然執行一次全表掃描
select * from dept where staff_num <> 1000;
但是開發中的確需要這樣的查詢,難道沒有解決問題的辦法了嗎?
有的!
通過把用or語法替代不等號進行查詢,就可以使用索引,以避免全表掃描,
上面的語句改成下面這樣的,就可以使用索引了。
select * from dept where staff_num < 1000 or dept_id > 1000;
使用函數
如果沒有使用基於函數的索引,那麼where子句中對存在索引的列使用函數時,會使優化器忽略掉這些索引,
下面的查詢就不會使用索引
select * from staff where trunc(birthdate) = '01-MAY-82'
但是把函數應用在條件上,索引是可以生效的, 把上面的語句改成下面的語句,就可以通過索引進行查找。
select * from staff where birthdate < (to_date('01-MAY-82') + 0.9999)
下面的例子中,dept_id是一個varchar2型的字段, 在這個字段上有索引,但是下面的語句會執行全盤掃描。
select * from dept where dept_id = 900198
這是因爲oracle 會自動把where 子句換成to_number(DEPT_ID) = 900198 , 就是限制了索引的使用。
把語句改成select * from dept where dept_id = '900198' 語句就會使用索引。
使用like子句查詢時,數據需要把所有的記錄都遍歷來進行判斷,索引不能發揮作用,這種情況也要儘量避免。
如果能不用到排序,則儘量避免排序。
用到排序的情況有集合操作。
union,minus,intersect,注意:union all是不排序的。
order by , group by, distinct , in 有的時候會用到排序
確實要排序的時候也儘量要排序小數據量 ,儘量讓排序在內存中執行。