在關係數據庫中,索引是一種與表有關的數據庫結構,它可使對應於表的SQL語句執行得更快。索引的做用至關於圖書的目錄,能夠根據目錄中的頁碼快速找到所需的內容。 數據庫
對於數據庫來講,索引是一個必選項,但對於如今的各類大型數據庫來講,索引能夠大大提升數據庫的性能,以致於它變成了數據庫不可缺乏的一部分。oracle
索引分類:函數
邏輯分類性能
single column or concatenated 對一列或多列建所引ui
unique or nonunique 惟一的和非惟一的所引,也就是對某一列或幾列的鍵值(key)是不是惟一的。spa
Function-based 基於某些函數索引,當執行某些函數時須要對其進行計算,能夠將某些函數的計算結果事先保存並加以索引,提升效率。 翻譯
Doman 索引數據庫之外的數據,使用相對較少指針
物理分類code
B-Tree :normal or reverse key B-Tree索引也是咱們傳統上常見所理解的索引,它又能夠分爲正常所引和倒序索引。orm
Bitmap : 位圖所引,後面會細講
B-Tree 索引
B-Tree index 也是咱們傳統上常見所理解的索引。B-tree (balance tree)即平衡樹,左右兩個分支相對平衡。
B-Tree index
Root爲根節點,branch 爲分支節點,leaf 到最下面一層稱爲葉子節點。每一個節點表示一層,當查找某一數據時先讀根節點,再讀支節點,最後找到葉子節點。葉子節點會存放index entry (索引入口),每一個索引入口對應一條記錄。
Index entry 的組成部分:
Indexentry entry header 存放一些控制信息。
Key column length 某一key的長度
Key column value 某一個key 的值
ROWID 指針,具體指向於某一個數據
建立索引:
conn as1 dex (id ,sex (),name ( i .. dex (i,, SQL dex_idx1 ,object_type DEX
索引分離於表,做爲一個單獨的個體存在,除了能夠根據單個字段建立索引,也能夠根據多列建立索引。Oracle要求建立索引最多不可超過32列。
SQL> create index dex_index2 on dex(sex,name);Index created. SQL> select object_name,object_type from user_objects;OBJECT_NAME OBJECT_TYPE--------------------------------------------------------------------------------DEX TABLEDEX_IDX1 INDEXDEX_INDEX2 INDEX
這裏須要理解:
編寫一本書,只有章節頁面定好以後再設置目錄;數據庫索引也是同樣,只有先插入好數據,再創建索引。那麼咱們後續對數據庫的內容進行插入、刪除,索引也須要隨之變化。但索引的修改是由oracle自動完成的。
上面這張圖能更加清晰的描述索引的結構。
跟節點記錄0至50條數據的位置,分支節點進行拆分記錄0至10.......42至50,葉子節點記錄每第數據的長度和值,並由指針指向具體的數據。
最後一層的葉子節是雙向連接,它們是被有序的連接起來,這樣才能快速鎖定一個數據範圍。
如:
SQL> select * from dex where id>23 and id<32; ID SE NAME---------- -- -------------------- 24 M chongshi 25 M chongshi 26 M chongshi 27 M chongshi 28 M chongshi 29 M chongshi 30 M chongshi 31 M chongshi8 rows selected.
如上面查找的列子,經過索引的方式先找到第23條數據,再找到第32條數據,這樣就能快速的鎖定一個查找的範圍,若是每條數據都要從根節點開始查找的話,那麼效率就會很是低下。
位圖索引
位圖索引主要針對大量相同值的列而建立。拿全國居民登陸一第表來講,假設有四個字段:姓名、性別、年齡、和身份證號,年齡和性別兩個字段會產生許多相同的值,性別只有男女兩種值,年齡,1到120(假設最大年齡120歲)個值。那麼無論一張表有幾億條記錄,但根據性別字段來區分的話,只有兩種取值(男、女)。那麼位圖索引就是根據字段的這個特性所創建的一種索引。
Bitmap Index
從上圖,咱們能夠看出,一個葉子節點(用不一樣顏色標識)表明一個key , start rowid 和 end rowid規定這種類型的檢索範圍,一個葉子節點標記一個惟一的bitmap值。由於一個數值類型對應一個節點,當時行查詢時,位圖索引經過不一樣位圖取值直接的位運算(與或),來獲取到結果集合向量(計算出的結果)。
舉例講解:
假設存在數據表T,有兩個數據列A和B,取值以下,咱們看到A和B列中存在相同的數據。
對兩個數據列A、B分別創建位圖索引:idx_t_bita和idx_t_bitb。兩個索引對應的存儲邏輯結構以下:
Idx_t_bita索引結構,對應的是葉子節點:
Idx_t_bitb索引結構,對應的是葉子節點:
對查詢「select * from t where b=1 and (a=’L’ or a=’M’)」
分析:位圖索引使用方面,和B*索引有很大的不一樣。B*索引的使用,一般是從根節點開始,通過不斷的分支節點比較到最近的符合條件葉子節點。經過葉子節點上的不斷Scan操做,「掃描」出結果集合rowid。
而位圖索引的工做方式大相徑庭。經過不一樣位圖取值直接的位運算(與或),來獲取到結果集合向量(計算出的結果)。
針對實例SQL,能夠拆分紅以下的操做:
一、a=’L’ or a=’M’
a=L:向量:1010
a=M:向量:0001
or操做的結果,就是兩個向量的或操做:結果爲1011。
二、結合b=1的向量
中間結果向量:1011
B=1:向量:1001
and操做的結果,1001。翻譯過來就是第一和第四行是查詢結果。
三、獲取到結果rowid
目前知道了起始rowid和終止rowid,以及第一行和第四行爲操做結果。能夠經過試算的方法獲取到結果集合rowid。
位圖索引的特色:
1.Bitmap索引的存儲空間節省
2.Bitmap索引建立的速度快
3.Bitmap索引容許鍵值爲空
4.Bitmap索引對錶記錄的高效訪問
建立位圖索引:
查看錶記錄 SQL> select * from dex; ................... ID SEX NAME---------- -- -------------------- 991 M chongshi 992 M chongshi 993 G chongshi 994 G chongshi 995 G chongshi 996 M chongshi 997 G chongshi 998 G chongshi 999 G chongshi 1000 M chongshi1000 rows selected. 對於上面表來講sex(性別)只有兩種值,最適合用來建立位圖所引 建立索引: SQL> create bitmap index my_bit_idx on dex(sex);Index created. 查看建立的所引 SQL> select object_name,object_type from user_objects;OBJECT_NAME OBJECT_TYPE--------------------------------------------------------------------------------MY_BIT_IDX INDEX
建立索引的一些規則
1、權衡索引個數與DML之間關係,DML也就是插入、刪除數據操做。
這裏須要權衡一個問題,創建索引的目的是爲了提升查詢效率的,但創建的索引過多,會影響插入、刪除數據的速度,由於咱們修改的表數據,索引也要跟着修改。這裏須要權衡咱們的操做是查詢多仍是修改多。
二、把索引與對應的表放在不一樣的表空間。
當讀取一個表時表與索引是同時進行的。若是表與索引和在一個表空間裏就會產生資源競爭,放在兩個表這空就可並行執行。
三、最好使用同樣大小是塊。
Oracle默認五塊,讀一次I/O,若是你定義6個塊或10個塊都須要讀取兩次I/O。最好是5的整數倍更能提升效率。
四、若是一個表很大,創建索引的時間很長,由於創建索引也會產生大量的redo信息,因此在建立索引時能夠設置不產生或少產生redo信息。只要表數據存在,索引失敗了大不了再建,因此能夠不須要產生redo信息。
五、建索引的時候應該根據具體的業務SQL來建立,特別是where條件,還有where條件的順序,儘可能將過濾大範圍的放在後面,由於SQL執行是從後往前的。(小李飛菜刀)
索引常見操做
改變索引:
SQL> alter index employees_last _name_idx storage(next 400K maxextents 100);
索引建立後,感受不合理,也能夠對其參數進行修改。詳情查看相關文檔
調整索引的空間:
新增長空間 SQL> alter index orders_region_id_idx allocate extent (size 200K datafile '/disk6/index01.dbf'); 釋放空間 SQL> alter index oraers_id_idx deallocate unused;
索引在使用的過程當中可能會出現空間不足或空間浪費的狀況,這個時候須要新增或釋放空間。上面兩條命令完成新增與釋放操做。關於空間的新增oracle能夠自動幫助,若是瞭解數據庫的狀況下手動增長能夠提升性能。
從新建立索引:
所引是由oracle自 動完成,當咱們對數據庫頻繁的操做時,索引也會跟着進行修改,當咱們在數據庫中刪除一條記錄時,對應的索引中並無把相應的索引只是作一個刪除標記,但它 依然佔據着空間。除非一個塊中全部的標記全被刪除的時,整個塊的空間纔會被釋放。這樣時間久了,索引的性能就會降低。這個時候能夠從新創建一個乾淨的索引 來提升效率。
SQL> alter index orders_region_id_idx rebuild tablespace index02;
經過上面的命令就能夠重現創建一個索引,oracle重創建索引的過程:
一、鎖表,鎖表以後其餘人就不能對錶作任何操做。
二、建立新的(乾淨的)臨時索引。
三、把老的索引刪除掉
四、把新的索引從新命名爲老索引的名字
五、對錶進行解鎖。
移動所引:
其實,咱們移動索引到其它表空間也一樣使用上面的命令,在指定表空間時指定不一樣的表空間。新的索引建立在別位置,把老的幹掉,就至關於移動了。
SQL> alter index orders_region_id_idx rebuild tablespace index03;
在線從新建立索引:
上面介紹,在建立索引的時候,表是被鎖定,不能被使用。對於一個大表,從新建立索引所須要的時間較長,爲了知足用戶對錶操做的需求,就產生的這種在線從新建立索引。
SQL> alter index orders_id_idx rebuild online;
建立過程:
一、鎖住表
二、建立立臨時的和空的索引和IOT表用來存在on-going DML。普通表存放的鍵值,IOT所引表直接存放的表中數據;on-gong DML也就是用戶所作的一些增刪改的操做。
三、對錶進行解鎖
四、從老的索引建立一個新的索引。
五、IOT表裏存放的是on-going DML信息,IOT表的內容與新建立的索引合併。
六、鎖住表
七、再次將IOT表的內容更新到新索引中,把老的索引幹掉。
八、把新的索引從新命名爲老索引的名字
九、對錶進行解鎖
整合索引碎片:
如上圖,在不少索引中有剩餘的空間,能夠經過一個命令把剩餘空間整合到一塊兒。
SQL> alter index orders_id_idx coalesce;
刪除索引:
SQL> drop index hr.departments_name_idx;
分析索引
檢查所引的有效果,前面介紹,索引用的時間久了會產生大量的碎片、垃圾信息與浪費的剩餘空間了。能夠經過從新建立索引來提升所引的性能。
能夠經過一條命令來完成分析索引,分析的結果會存放在在index_stats表中。
查看存放分析數據的表: SQL> select count(*) from index_stats; COUNT(*)---------- 0執行分析索引命令: SQL> analyze index my_bit_idx validate structure;Index analyzed. 再次查看 index_stats 已經有了一條數據 SQL> select count(*) from index_stats; COUNT(*)---------- 1把數據查詢出來: SQL> select height,name,lf_rows,lf_blks,del_lf_rows from index_stats; HEIGHT NAME LF_ROWS LF_BLKS DEL_LF_ROWS---------- ---------------------------------------------------------------------- ---------- ----------- 2 MY_BIT_IDX 1000 3 100
分析數據分析:
(HEIGHT)這個所引高度是2 ,(NAME)索引名爲MY_BIT_IDX ,(LF_ROWS)所引表有1000行數據,(LF_BLKS)佔用3個塊,(DEL_LF_ROWS)刪除100條記錄。
這裏也驗證了前面所說的一個問題,刪除的100條數據只是標記爲刪除,由於總的數據條數依然爲1000條,佔用3個塊,那麼每一個塊大於333條記錄,只有刪除的數據大於333條記錄,這時一個塊被清空,總的數據條數纔會減小。