閱讀導航
提高性能
索引
B-tree 索引
Hash 索引
其他類型
指針
索引百利無一害
索引對于接觸過資料庫的人,都不會很陌生,但是說實話,也不一定很熟悉。先來介紹下索引的優點。
現在有一個資料庫表[Words],有[WordID],[WordPage],[[WordName],[WordPronunciation] ,[WordMeaning],[WordSentence]五個列,假設有上萬條記錄。
現在,使用查詢語句找到“boyce”的詳細資訊,使用語句
1: SELECT * FROM [Words]
2: WHERE [WordName] = 'boyce'
執行這個語句會發生什麼?實際上程式在背景找一個單詞“boyce”。資料庫可能會查找表的每一行,是否存在一個單詞“boyce”。但是,就算找到了表中一個單詞“boyce”的行,資料庫也不會停止檢索,因為剩下的每一行都有可能是一個單詞“boyce”的行,也就是說,知道所有行都被檢索後,資料庫才會停止檢索并傳回查詢結果。其實就是做了一個全表檢索。其實,如果一個表隻有一百行甚至幾千行資料,就算全表檢索我們也不會又什麼明顯的感覺,但是随着資料的膨脹變大,幾萬行資料甚至更多時,整表檢索可能就是一件令人恐懼的事情。如果這樣的事情發生了,除了等待令人恐怖的檢索,我們還可以做什麼呢!使用肉眼去看,這樣可能不是一個明智的做法,正常人幹不出這事。
就像這個小标題一樣,我們可以使用索引提高性能。索引是通過使用指針的指向減少了檢索資料表記錄數量來提高性能的。
索引是一個可以存儲資料表列值的資料結構(通常都是R-tree)。索引建立在表中列上面。一個很重要的内容就是索引包含表中的列值,并且這些值被存儲到了資料結構中。簡單易記的一句話,索引就是資料結構。
那麼可不可以說,索引就是B-tree呢?并不是這樣的,除了有B-tree索引,還有hash索引、R-tree索引、bitmap索引
B-tree 索引
這是最常用的索引。因為,B-tree的索引在查找、删除、插入操作時的時間複雜度是對數時間。另外一個重要的原因是,可以把資料存儲在B-tree中。但是,索引使用什麼樣的資料結構是由RDBMS(關系型資料庫管理系統)決定的。有時候在建立索引的時候也可以指定索引的資料結構類型。
正因為索引是基于資料結構存儲列值值的,是以檢索這些值得時候會更快。B-tree 索引的資料結構也是一個有序的結構。索引提升性能的主要原因是什麼呢?
現在在[WordName] 列上建立B-tree索引,這就意味着,在使用上面的語句
1: SELECT * FROM [Words]
2: WHERE [WordName] = 'boyce'
不會再進行全表的掃描。因為索引是可能是按照[WordName] 的字母進行了排序,這就表明,所有以”b” 開頭單詞的索引是挨着的。更重要的是索引中存儲着指向列值實際資料行的指針。
Hash 索引
這是可能被索引使用的另一個資料結構類型。在進行查找操作時,使用hash 索引。的效率很高。是以,當使用一個語句去比較字元串,然後傳回結果集,這樣的操作使用hash 索引是很快的。就像前面的語句
1: SELECT * FROM [Words]
2: WHERE [WordName] = 'boyce'
在列[WordName] 上建立hash 索引是一個很好的。這時,列值将插入到hash 表中和一個鍵對應,并和實際的資料行有一個映射關系,也就是該鍵是一個指向表中資料行的指針。hash 表實際是基于關聯數組,假如有這樣一個語句“boyce = 0×28936”,0×28936是關聯到存儲在記憶體中的boyce。在hash表索引中查找“boyce”的值并傳回記憶體中的資料,要比檢索整個表的[WordName]列值要快得多。
照這樣的說法,是不是以後建立hash 索引好了?
其實不然
hash 表不是一個被排序的資料結構,很多類型的hash索引查詢根本就沒有性能的提升。比如。檢索300頁以内的所有單詞。因為,hash 表擅長的是檢索鍵值對,也就是說,檢索語句檢查相等性(如,“WHERE [WordName] = “boyce” ”)。在hash 表中的鍵值是沒有排序的,在存儲的時候也沒有任何的排序規則。因為hash 索引不夠靈活。是以,hash 索引不是預設索引的資料結構。
是不是,建立所有的索引使用預設的b-tree資料結構就完事大吉了呢?
下面的情況還是最好考慮使用hash 索引:
表中存在字段過長,這樣的列是不适合建立索引的,建立索引的原則是索引不能太寬。
對于varchar(max)、nvarchar(max) 和 varbinary(max)的大值資料類型也不适合建立索引。
其他類型
使用R-tree 資料結構的索引,這個主要是解決一些特定的問題。比如,找到方圓五百米的美女/帥哥,這是使用R-tree 索引,性能會有一定的提升。
還有bitmap 索引,在列值為Boolean值時,該類索引是相當有效的。一般用在選擇性列上。
有一個問題:在索引中檢索一個值(比如,boyce),是怎麼樣也找到該行其他的列的值呢([WordID]、[WordPage]……)?
可能會說,So easy!因為存在指針。
是這樣的,還是讓我來啰嗦一下。
索引中存儲指向相應行的指針。這個指針是關聯到一塊記憶體,該記憶體中存儲了相應資料在硬碟的位址。也就是說,添加為索引的列值是存儲在索引中,指向相應資料行的指針也是存儲在索引中。這就意味着,[WordName] 在索引中就是像這樣(“boyce”,“0×82937”),那麼,0×82937的位址就是“boyce” 所在行在磁盤中的位址。通過這個例子,可以看出, 單值得指針其實沒有用的,是沒有意義的,因為他不能得到相應資料行的值。
索引建立在表的列上,這個概念大家已經非常清晰了。索引隻是存儲了特定的列,并沒有把表中所有的列全部存儲到索引中。例如,在[WordName] 列上建立索引,這就意味着,[WordID],[WordPage]…… 沒有存儲在索引中。如果建立索引在所有的列上,那就相當于把 整個表複制了一份,這會占據很大的空間并且效率也很低。
現在我們知道,建立索引其實會占據一定空間的,越大的表,建立索引占據的空間越大。還有,在所添加、删除、和更新行的時候,都需要相應的維護索引,這樣資料庫的性能可能會降低。
一般的規則,被頻繁檢索的列,才在該列建立索引。