如你們所知道的,Mysql目前主要有如下幾種索引類型:FULLTEXT,HASH,BTREE,RTREE。java
那麼,這幾種索引有什麼功能和性能上的不一樣呢?node
FULLTEXTmysql
即爲全文索引,目前只有MyISAM引擎支持。其能夠在CREATE TABLE ,ALTER TABLE ,CREATE INDEX 使用,不過目前只有 CHAR、VARCHAR ,TEXT 列上能夠建立全文索引。值得一提的是,在數據量較大時候,現將數據放入一個沒有全局索引的表中,而後再用CREATE INDEX建立FULLTEXT索引,要比先爲一張表創建FULLTEXT而後再將數據寫入的速度快不少。redis
全文索引並非和MyISAM一塊兒誕生的,它的出現是爲了解決WHERE name LIKE 「%word%"這類針對文本的模糊查詢效率較低的問題。在沒有全文索引以前,這樣一個查詢語句是要進行遍歷數據表操做的,可見,在數據量較大時是極其的耗時的,若是沒有異步IO處理,進程將被挾持,很浪費時間,固然這裏不對異步IO做進一步講解,想了解的童鞋,自行谷哥。算法
全文索引的使用方法並不複雜:sql
建立ALTER TABLE table ADD INDEX `FULLINDEX` USING FULLTEXT(`cname1`[,cname2…]);數據庫
使用SELECT * FROM table WHERE MATCH(cname1[,cname2…]) AGAINST ('word' MODE );緩存
其中, MODE爲搜尋方式(IN BOOLEAN MODE ,IN NATURAL LANGUAGE MODE ,IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION / WITH QUERY EXPANSION)。數據結構
關於這三種搜尋方式,愚安在這裏也很少作交代,簡單地說,就是,布爾模式,容許word裏含一些特殊字符用於標記一些具體的要求,如+表示必定要有,-表示必定沒有,*表示通用匹配符,是否是想起了正則,相似吧;天然語言模式,就是簡單的單詞匹配;含表達式的天然語言模式,就是先用天然語言模式處理,對返回的結果,再進行表達式匹配。
對搜索引擎稍微有點了解的同窗,確定知道分詞這個概念,FULLTEXT索引也是按照分詞原理創建索引的。西文中,大部分爲字母文字,分詞能夠很方便的按照空格進行分割。但很明顯,中文不能按照這種方式進行分詞。那又怎麼辦呢?這個向你們介紹一個Mysql的中文分詞插件Mysqlcft,有了它,就能夠對中文進行分詞,想了解的同窗請移步Mysqlcft,固然還有其餘的分詞插件可使用。
HASH
Hash這個詞,能夠說,自打咱們開始碼的那一天起,就開始不停地見到和使用到了。其實,hash就是一種(key=>value)形式的鍵值對,如數學中的函數映射,容許多個key對應相同的value,但不容許一個key對應多個value。正是因爲這個特性,hash很適合作索引,爲某一列或幾列創建hash索引,就會利用這一列或幾列的值經過必定的算法計算出一個hash值,對應一行或幾行數據(這裏在概念上和函數映射有區別,不要混淆)。在java語言中,每一個類都有本身的hashcode()方法,沒有顯示定義的都繼承自object類,該方法使得每個對象都是惟一的,在進行對象間equal比較,和序列化傳輸中起到了很重要的做用。hash的生成方法有不少種,足能夠保證hash碼的惟一性,例如在MongoDB中,每個document都有系統爲其生成的惟一的objectID(包含時間戳,主機散列值,進程PID,和自增ID)也是一種hash的表現。額,我好像扯遠了-_-!
因爲hash索引能夠一次定位,不須要像樹形索引那樣逐層查找,所以具備極高的效率。那爲何還須要其餘的樹形索引呢?
在這裏愚安就不本身總結了。引用下園子裏其餘大神的文章:來自 14的路 的MySQL的btree索引和hash索引的區別
(1)Hash 索引僅僅能知足"=","IN"和"<=>"查詢,不能使用範圍查詢。
因爲 Hash 索引比較的是進行 Hash 運算以後的 Hash 值,因此它只能用於等值的過濾,不能用於基於範圍的過濾,由於通過相應的 Hash 算法處理以後的 Hash 值的大小關係,並不能保證和Hash運算前徹底同樣。
(2)Hash 索引沒法被用來避免數據的排序操做。
因爲 Hash 索引中存放的是通過 Hash 計算以後的 Hash 值,並且Hash值的大小關係並不必定和 Hash 運算前的鍵值徹底同樣,因此數據庫沒法利用索引的數據來避免任何排序運算;
(3)Hash 索引不能利用部分索引鍵查詢。
對於組合索引,Hash 索引在計算 Hash 值的時候是組合索引鍵合併後再一塊兒計算 Hash 值,而不是單獨計算 Hash 值,因此經過組合索引的前面一個或幾個索引鍵進行查詢的時候,Hash 索引也沒法被利用。
(4)Hash 索引在任什麼時候候都不能避免表掃描。
前面已經知道,Hash 索引是將索引鍵經過 Hash 運算以後,將 Hash運算結果的 Hash 值和所對應的行指針信息存放於一個 Hash 表中,因爲不一樣索引鍵存在相同 Hash 值,因此即便取知足某個 Hash 鍵值的數據的記錄條數,也沒法從 Hash 索引中直接完成查詢,仍是要經過訪問表中的實際數據進行相應的比較,並獲得相應的結果。
(5)Hash 索引遇到大量Hash值相等的狀況後性能並不必定就會比B-Tree索引高。
對於選擇性比較低的索引鍵,若是建立 Hash 索引,那麼將會存在大量記錄指針信息存於同一個 Hash 值相關聯。這樣要定位某一條記錄時就會很是麻煩,會浪費屢次表數據的訪問,而形成總體性能低下。
愚安我稍做補充,講一下HASH索引的過程,順便解釋下上面的第4,5條:
當咱們爲某一列或某幾列創建hash索引時(目前就只有MEMORY引擎顯式地支持這種索引),會在硬盤上生成相似以下的文件:
hash值 | 存儲地址 |
1db54bc745a1 | 77#45b5 |
4bca452157d4 | 76#4556,77#45cc… |
…
hash值即爲經過特定算法由指定列數據計算出來,磁盤地址即爲所在數據行存儲在硬盤上的地址(也有多是其餘存儲地址,其實MEMORY會將hash表導入內存)。
這樣,當咱們進行WHERE age = 18 時,會將18經過相同的算法計算出一個hash值==>在hash表中找到對應的儲存地址==>根據存儲地址取得數據。
因此,每次查詢時都要遍歷hash表,直到找到對應的hash值,如(4),數據量大了以後,hash表也會變得龐大起來,性能降低,遍歷耗時增長,如(5)。
BTREE
BTREE索引就是一種將索引值按必定的算法,存入一個樹形的數據結構中,相信學過數據結構的童鞋都對當初學習二叉樹這種數據結構的經歷記憶猶新,反正愚安我當時爲了軟考但是被這玩意兒好好地折騰了一番,不過那次考試好像沒怎麼考這個。如二叉樹同樣,每次查詢都是從樹的入口root開始,依次遍歷node,獲取leaf。
BTREE在MyISAM裏的形式和Innodb稍有不一樣
在 Innodb裏,有兩種形態:一是primary key形態,其leaf node裏存放的是數據,並且不只存放了索引鍵的數據,還存放了其餘字段的數據。二是secondary index,其leaf node和普通的BTREE差很少,只是還存放了指向主鍵的信息.
而在MyISAM裏,主鍵和其餘的並無太大區別。不過和Innodb不太同樣的地方是在MyISAM裏,leaf node裏存放的不是主鍵的信息,而是指向數據文件裏的對應數據行的信息.
RTREE
RTREE在mysql不多使用,僅支持geometry數據類型,支持該類型的存儲引擎只有MyISAM、BDb、InnoDb、NDb、Archive幾種。
相對於BTREE,RTREE的優點在於範圍查找.
各類索引的使用狀況
(1)對於BTREE這種Mysql默認的索引類型,具備廣泛的適用性
(2)因爲FULLTEXT對中文支持不是很好,在沒有插件的狀況下,最好不要使用。其實,一些小的博客應用,只須要在數據採集時,爲其創建關鍵字列表,經過關鍵字索引,也是一個不錯的方法,至少愚安我是常常這麼作的。
(3)對於一些搜索引擎級別的應用來講,FULLTEXT一樣不是一個好的處理方法,Mysql的全文索引創建的文件仍是比較大的,並且效率不是很高,即使是使用了中文分詞插件,對中文分詞支持也只是通常。真要碰到這種問題,Apache的Lucene或許是你的選擇。
(4)正是由於hash表在處理較小數據量時具備無可比擬的素的優點,因此hash索引很適合作緩存(內存數據庫)。如mysql數據庫的內存版本Memsql,使用量很普遍的緩存工具Mencached,NoSql數據庫redis等,都使用了hash索引這種形式。固然,不想學習這些東西的話Mysql的MEMORY引擎也是能夠知足這種需求的。
(5)至於RTREE,愚安我至今尚未使用過,它具體怎麼樣,我就不知道了。有RTREE使用經歷的同窗,到時能夠交流下!