Oracle索引之Btree索引


索引介紹

日常開發中,對於數據的查詢如果需要優化,常聽說要加個索引。但是為什么加了索引,數據的查詢就快了呢?那是不是加了索引就一定會是有效或者有利的呢?

Oracle中常見有BTREE索引,位圖索引和函數索引。

我們今天就先介紹一下這個BTREE索引吧。既然叫BTREE索引,那就從它的樹結構說起:

建BTREE索引其實是先拿出所有數據排序,將有序的索引列的值和rowid存進Oracle的各個數據塊中,形成索引塊,存在內存中。這些數據塊以樹結構的形式組織起來,父節點只記錄子節點的鍵值位置信息,不存具體數據,所以,只有葉子塊存具體數據(索引列數據和rowid)。其他非葉子節點只記錄位置信息,占用空間非常小,所以索引塊即使存了很多數據,這顆樹的高度其實並不高。如下圖:

 

 

索引查詢

查詢的時候,根據樹的結構去查詢,產生的邏輯讀的次數也就是樹的高度,走索引的邏輯讀不會很多,產生的IO少,所以肯定比全表掃描要效率高。

注意:如果索引列包含空值,是不會走索引的。所以,在一些查詢中,要想走索引,需要加上條件“索引列 is not null”或者修改表字段屬性為非空。

例如:沒建索引之前,對於統計函數肯定是全表掃描:

建索引之后,如果我們不對空值進行篩選,是不走索引的:

對於空值進行排除后,可以看到走索引了:

 

在最大最小值的查詢中,索引也是優化的一個手段。沒建索引之前:

建了索引之后,因為索引的有序特性,直接去索引樹的最右或最左葉子節點找一遍就可以了:

 

再看select具體字段和select *的區別。

比較下面兩個查詢:

 

上面我們說過,索引儲存了索引列和rowid的數據,如果我們只取索引列的數據,則,訪問到索引塊即取到我們需要的數據了,如果還需要取其他字段的數據,在索引中找不到,則會存在一個去表中取數據的操作,即“TABLE ACCESS BY INDEX ROWID ”,多產生的讀取操作必然會增加消耗,所以如果有些字段必須展現,又數據量很小,可以考慮建聯合索引。

 

既然索引是有序的,那我們的order by操作是不是也可以用索引來優化呢?答案是肯定的:

建完索引之后:

 

可見走索引的排序要比全表掃描的排序消耗小很多。

 

上面我們見到了執行計划中各種走索引的方式,那他們有什么區別呢?感興趣的童鞋可以討論討論呀~

 

聯合索引

上面說到,為了避免回表,我們可以建聯合索引,但組合列最好不要超過3列,返回的組合列越少越高效;

問題也隨之而來,組合列中哪個列在前哪個列在后呢?

一般,在等值查詢情況下,誰在前誰在后沒關系;如果一列是范圍查詢,一列是等值查詢,等值查詢列在前效率高;聯合索引中,如果針對其中一列的查詢單列比較多的時候,單列查詢在前。比如在某表中,想對其code和pcode字段建聯合索引,但是業務中有大量的查詢pcode的單列查詢操作,則聯合索引應該將pcode放在前面比較合適。

 

 

索引的危害

上面說了這么多索引的優點,那是不是建索引一定是有利的呢?

因為索引的有序特性,索引索引越多,為了維持索引有序,更新數據受到影響就會越大:

insert:每插入一條數據,就要維持索引有序,因此,索引對於插入操作有弊無利;

delete:刪除數據,如果數據量很大,對於定位要刪除的少量數據,條件列是索引列是有利的。如果刪除大量記錄或者索引列過多,對於刪除操作是有弊端的;

update:如果更新非索引列,則無影響;如果更新索引列,定位和更新索引列則和delete操作類似。

因為是將數據拿出來排序並且保存到數據塊中,建索引時會鎖表,以免建索引過程中數據更新造成影響,所以,建索引尤其是大數據表,不要在使用高峰期建。

 

以上便是BTREE索引的一些簡單介紹啦,還請多多指正啊~

 

我是一個呆頭呆腦的程序員,一直想做一只有趣的代碼狗,關注公眾號codinggogo,了解更有趣的愛恨情仇啊~

 

 

 

 

 

 


免責聲明!

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



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