mysql數據庫索引

索引是對數據庫表中一列或多列的值進行排序的一種結構,使用索引可快速訪問數據庫表中的特定信息。html

根據數據庫的功能,能夠在數據庫設計器中建立三種索引:惟一索引、主鍵索引和彙集索引。node

惟一索引:惟一索引是不容許其中任何兩行具備相同索引值的索引。
當現有數據中存在重複的鍵值時,大多數數據庫不容許將新建立的惟一索引與表一塊兒保存。數據庫還可能防止添加將在表中建立重複鍵值的新數據。
主鍵索引:
數據庫表常常有一列或多列組合,其值惟一標識表中的每一行。該列稱爲表的主鍵。
在數據庫關係圖中爲表定義主鍵將自動建立主鍵索引,主鍵索引是惟一索引的特定類型。該索引要求主鍵中的每一個值都惟一。當在查詢中使用主鍵索引時,它還容許對數據的快速訪問。
彙集索引:
在彙集索引中,表中行的物理順序與鍵值的邏輯(索引)順序相同。一個表只能包含一個彙集索引。
在彙集索引中,索引的排序的有序性是指,索引的順序對應着數據庫中對應索引關鍵字的順序,而和數據在磁盤中的物理順序無關。 ( http://www.cnblogs.com/lwzz/archive/2012/08/05/2620824.html
 
彙集索引與非彙集索引:( http://www.2cto.com/database/201609/544681.html
     B+樹索引能夠分爲彙集索引和輔助索引,他們不一樣點是,彙集索引的行數據和主鍵B+樹存儲在一塊兒,輔助索引只存儲輔助鍵和主鍵。
 
這裏主要講mysql使用到的B+樹。
B+樹

        性質:B+樹是B-樹的變體,也是一種多路搜索樹:mysql

           1.其定義基本與B-樹同,除了:算法

           2.非葉子結點的子樹指針與關鍵字個數相同;sql

            3.非葉子結點的子樹指針P[i],指向關鍵字值屬於[K[i], K[i+1])的子樹(B-樹是開區間);數據庫

           4.爲全部葉子結點增長一個鏈指針;數據庫設計

           5.全部關鍵字都在葉子結點出現;函數

        B+的搜索與B-樹也基本相同,區別是B+樹只有達到葉子結點才命中(B-樹能夠在oop

非葉子結點命中),其性能也等價於在關鍵字全集作一次二分查找;源碼分析

        B+的特性:

            1.全部關鍵字都出如今葉子結點的鏈表中(稠密索引),且鏈表中的關鍵字剛好是有序的;

           2.不可能在非葉子結點命中;

            3.非葉子結點至關因而葉子結點的索引(稀疏索引),葉子結點至關因而存儲(關鍵字)數據的數據層;

           4.更適合文件索引系統;

B+樹插入刪除變化圖及源碼分析( http://blog.csdn.net/cdnight/article/details/11772621
 
 

B-/+Tree索引的性能分析

通常使用磁盤I/O次數評價索引結構的優劣。先從B-Tree分析,根據B-Tree的定義,可知檢索一次最多須要訪問h個節點。數據庫系統的設計者巧妙利用了磁盤預讀原理,將一個節點的大小設爲等於一個頁,這樣每一個節點只須要一次I/O就能夠徹底載入。爲了達到這個目的,在實際實現B-Tree還須要使用以下技巧:

每次新建節點時,直接申請一個頁的空間,這樣就保證一個節點物理上也存儲在一個頁裏,加之計算機存儲分配都是按頁對齊的,就實現了一個node只需一次I/O。

B-Tree中一次檢索最多須要h-1次I/O(根節點常駐內存),漸進複雜度爲O(h)=O(logdN)。通常實際應用中,出度d是很是大的數字,一般超過100( B+ trees have very high fanout (number of pointers to child nodes in a node, typically on the order of 100 or more)),所以h很是小(一般不超過3)。

綜上所述,用B-Tree做爲索引結構效率是很是高的。

而紅黑樹這種結構,h明顯要深的多。因爲邏輯上很近的節點(父子)物理上可能很遠,沒法利用局部性,因此紅黑樹的I/O漸進複雜度也爲O(h),效率明顯比B-Tree差不少。

上文還說過,B+Tree更適合外存索引,緣由和內節點出度d(>節點的度:一個節點含有的子樹的個數稱爲該節點的度;>樹的度:一棵樹中,最大的節點的度稱爲樹的度)有關。從上面分析能夠看到,d越大索引的性能越好,而出度的上限取決於節點內key和data的大小:

dmax = floor(pagesize / (keysize + datasize + pointsize))

floor表示向下取整。因爲B+Tree內節點去掉了data域,所以能夠擁有更大的出度,擁有更好的性能。

 

下圖是一個簡單的B+Tree示意。 

 

MySQL索引實現

在MySQL中,索引屬於存儲引擎級別的概念,不一樣存儲引擎對索引的實現方式是不一樣的,本文主要討論MyISAM和InnoDB兩個存儲引擎的索引實現方式。

走進搜索引擎的做者梁斌老師針對B樹、B+樹給出了他的意見(爲了真實性,特引用其原話,未做任何改動): 「B+樹還有一個最大的好處,方便掃庫,B樹必須用中序遍歷的方法按序掃庫,而B+樹直接從葉子結點挨個掃一遍就完了,B+樹支持range-query很是方便,而B樹不支持。這是數據庫選用B+樹的最主要緣由。

    好比要查 5-10之間的,B+樹一把到5這個標記,再一把到10,而後串起來就好了,B樹就很是麻煩。B樹的好處,就是成功查詢特別有利,由於樹的高度整體要比B+樹矮。不成功的狀況下,B樹也比B+樹稍稍佔一點點便宜。

    B樹好比你的例子中查,17的話,一把就獲得結果了,
有不少基於頻率的搜索是選用B樹,越頻繁query的結點越往根上走,前提是須要對query作統計,並且要對key作一些變化。

    另外B樹也好B+樹也好,根或者上面幾層由於被反覆query,因此這幾塊基本都在內存中,不會出現讀磁盤IO,通常已啓動的時候,就會主動換入內存。"

MyISAM索引實現(http://blog.codinglabs.org/articles/theory-of-mysql-index.html)

MyISAM引擎使用B+Tree做爲索引結構,葉節點的data域存放的是數據記錄的地址。下圖是MyISAM索引的原理圖:

 

 

這裏設表一共有三列,假設咱們以Col1爲主鍵,上圖是一個MyISAM表的主索引(Primary key)示意。能夠看出MyISAM的索引文件僅僅保存數據記錄的地址(默認是以存儲順序)。在MyISAM中,主索引和輔助索引(Secondary key)在結構上沒有任何區別,只是主索引要求key是惟一的,而輔助索引的key能夠重複。若是咱們在Col2上創建一個輔助索引,則此索引的結構以下圖所示:

 

 

一樣也是一顆B+Tree,data域保存數據記錄的地址。所以,MyISAM中索引檢索的算法爲首先按照B+Tree搜索算法搜索索引,若是指定的Key存在,則取出其data域的值,而後以data域的值爲地址,讀取相應數據記錄。

MyISAM的索引方式也叫作「非彙集」的,之因此這麼稱呼是爲了與InnoDB的彙集索引區分。

InnoDB索引實現

雖然InnoDB也使用B+Tree做爲索引結構,但具體實現方式卻與MyISAM大相徑庭。

第一個重大區別是InnoDB的數據文件自己就是索引文件。從上文知道,MyISAM索引文件和數據文件是分離的,索引文件僅保存數據記錄的地址。而在InnoDB中,表數據文件自己就是按B+Tree組織的一個索引結構,這棵樹的葉節點data域保存了完整的數據記錄。這個索引的key是數據表的主鍵,所以InnoDB表數據文件自己就是主索引。

 

 

上圖是InnoDB主索引(同時也是數據文件)的示意圖,能夠看到葉節點包含了完整的數據記錄。這種索引叫作彙集索引。由於InnoDB的數據文件自己要按主鍵彙集,因此InnoDB要求表必須有主鍵(MyISAM能夠沒有),若是沒有顯式指定,則MySQL系統會自動選擇一個能夠惟一標識數據記錄的列做爲主鍵,若是不存在這種列,則MySQL自動爲InnoDB表生成一個隱含字段做爲主鍵,這個字段長度爲6個字節,類型爲長整形。

第二個與MyISAM索引的不一樣是InnoDB的輔助索引data域存儲相應記錄主鍵的值而不是地址。換句話說,InnoDB的全部輔助索引都引用主鍵做爲data域。例如,上圖爲定義在Col3上的一個輔助索引:

 

 

 

這裏以英文字符的ASCII碼做爲比較準則。彙集索引這種實現方式使得按主鍵的搜索十分高效,可是輔助索引搜索須要檢索兩遍索引:首先檢索輔助索引得到主鍵,而後用主鍵到主索引中檢索得到記錄。

瞭解不一樣存儲引擎的索引實現方式對於正確使用和優化索引都很是有幫助,例如知道了InnoDB的索引實現後,就很容易明白爲何不建議使用過長的字段做爲主鍵,由於全部輔助索引都引用主索引,過長的主索引會令輔助索引變得過大。再例如,用非單調的字段做爲主鍵在InnoDB中不是個好主意,由於InnoDB數據文件自己是一顆B+Tree,非單調的主鍵會形成在插入新記錄時數據文件爲了維持B+Tree的特性而頻繁的分裂調整,十分低效,而使用自增字段做爲主鍵則是一個很好的選擇。

使用explain對sql進行優化:

1) consts 單表中最多隻有一個匹配行(主鍵或者惟一索引),在優化階段便可讀取到數據。
2) ref 指的是使用普通的索引。(normal index)
3) range 對索引進範圍檢索。
反例:explain 表的結果,type=index,索引物理文件全掃描,速度很是慢,這個 index 級別
比較 range 還低,與全表掃描是小巫見大巫。

當使用索引時,InnoDB會鎖住它不須要的元組。更糟糕的是,若是查詢不能使用索引,MySQL會進行全表掃描,並鎖住每個元組,不論是否真正須要

Hash索引
MySQL中,只有Memory存儲引擎顯示支持hash索引,是Memory表的默認索引類型,儘管Memory表也可使用B-Tree索引。

CREATE TABLE lookup 
(id INT, INDEX USING HASH (id)) 
ENGINE = MEMORY; 
CREATE TABLE lookup 
(id INT, INDEX USING BTREE (id)) 
ENGINE = MEMORY; 

Memory存儲引擎支持非惟一hash索引,這在數據庫領域是罕見的,若是多個值有相同的hash code,索引把它們的行指針用鏈表保存到同一個hash表項中。
假設建立以下一個表:
CREATE TABLE testhash (
   fname VARCHAR(50) NOT NULL,
   lname VARCHAR(50) NOT NULL,
   KEY USING HASH(fname)
) ENGINE=MEMORY;
包含的數據以下:

假設索引使用hash函數f( ),以下:

f('Arjen') = 2323

f('Baron') = 7437

f('Peter') = 8784

f('Vadim') = 2458

此時,索引的結構大概以下:

 

 Slots是有序的,可是記錄不是有序的。當你執行
mysql> SELECT lname FROM testhash WHERE fname='Peter';
MySQL會計算’Peter’的hash值,而後經過它來查詢索引的行指針。由於f('Peter') = 8784,MySQL會在索引中查找8784,獲得指向記錄3的指針。
由於索引本身僅僅存儲很短的值,因此,索引很是緊湊。Hash值不取決於列的數據類型,一個TINYINT列的索引與一個長字符串列的索引可能同樣大。
 
Hash索引有如下一些限制:
(1)因爲索引僅包含hash code和記錄指針,因此,MySQL不能經過使用索引避免讀取記錄。可是訪問內存中的記錄是很是迅速的,不會對性能形成太大的影響。
(2)不能使用hash索引排序。
(3)Hash索引不支持鍵的部分匹配,由於是經過整個索引值來計算hash值的。
(4)Hash索引只支持等值比較,例如使用=,IN( )和<=>。對於WHERE price>100並不能加速查詢。

mysql Btree與hash索引的區別(https://dev.mysql.com/doc/refman/5.5/en/index-btree-hash.html

位圖索引:
位圖索引是一種針對多個字段的簡單查詢設計一種特殊的索引,適用範圍比較小,只適用於字段值固定而且值的種類不多的狀況,好比性別,只能有男和女,或者級別,狀態等等,而且只有在同時對多個這樣的字段查詢時才能體現出位圖的優點。
位圖的基本思想就是對每個條件都用0或者1來表示,若有5條記錄,性別分別是男,女,男,男,女,那麼若是使用位圖索引就會創建兩個位圖,對應男的10110和對應女的01001,這樣作有什麼好處呢,就是若是同時對多個這種類型的字段進行and或or查詢時,可使用按位與和按位或來直接獲得結果了。
反向鍵索引:

考慮這個狀況:某一字段的值是1-1000順序排列,創建B樹索引後依舊遞增,到後來該B數索引不斷在後面增長分支,會造成以下如的不對稱樹:

    

    反向鍵索引是一種特殊的B樹索引,在存儲構造中與B樹索引徹底相同,可是針對數值時,反向鍵索引會先反向每一個鍵值的字節,而後對反向後的新數據進行索引。例如輸入2008則轉換爲8002,這樣當數值一次增長時,其反向鍵在大小中的分佈仍然是比較平均的。

    反向鍵索引的建立示例:

    create index ind_t on t1(id) reverse;

    注:鍵的反轉由系統自行完成。對於用戶是透明的。

Block Nested Loop
mysql的多表join使用的就是nested loop,具體見mysql官網的文檔說明: https://dev.mysql.com/doc/refman/5.5/en/nested-loop-joins.html
 
總結: 本文只是對mysql索引作了一個大概的闡述,僅作幾天來對mysql索引的學習的一個總結,文中對引用部分都加了具體的連接,連接中有許多人對索引的細節部分有着更加清楚的描述,也是對我學習索引發了很好的幫助,在此感謝!
相關文章
相關標籤/搜索