小白學習mysql之索引初步

導語

索引在數據庫中的地位是及其的重要,同時要想徹底的掌握索引並非一件容易的事,須要對數據的查詢原理以及計算機操做系統有深入的認識,固然相關的算法和數據結構也是必須的。所以,這篇文章感到了一些壓力,不過仍是決定先拿出來總結一下,理一理索引,就當作學習筆記了。算法

索引的重要習性猶如一本字典的拼音檢索和部首檢索部分,想象一下你買了一本只有正文的字典,那該有多麼抓狂。並且在一個軟件系統中,一般數據的查詢與修改每每佔到了10:1的比例,也就是咱們須要將大部分的精力投入到數據的查詢上,其中不少工做是用來提高查詢的速度的,那麼在這個過程當中索引就扮演者很是重要的角色。sql

索引的實質

若是說一本字典的正文內容的實質是紙張的話,那麼它前面按照拼音或者部首檢索的索引的實質是什麼呢!固然也是紙張了,可能有人以爲是廢話,當咱們同時類比到索引上就能夠知道,一個數據表的實質是數據文件(即文件),那麼索引的實質也固然是文件了,Mysql的InnoDB的數據表中的索引就是表空間的一部分。所以,初學者能夠把索引徹底想象成爲一本字典,一本字典就是一個數據表,正文部分呢,就是這個數據表的詳細內容,按照拼音和部首的檢索都是索引。
當咱們經過索引查找一條數據項的時候就猶如經過拼音索引查找某一個字,當在索引中查找到那個字的時候,會根據右邊對應的頁碼找到那個字的解釋,一樣,MySQL的索引工做原理也是如此,每一個索引項都有一個建索引列的關鍵字和一個指向該數據項的指針(相似字典中的頁碼),當咱們查找到那個目標關鍵字時,根據指針即可以直接定位到數據表中該關鍵字的位置。數據庫

但現實中的真是數據表並不像字典那樣,內容都是嚴格按照拼音序列排列的,由於有不少不肯定的新內容要插入或者要進行其餘操做,因此字典只是一種特殊的數據表,並不能把全部的數據表都拿來和字典比,這裏用字典來類比只是爲了對索引的實質有一個立體的認識。緩存

索引是如何實現快速查找的

假設A公司有1024名員工(員工編號1-1024),早上的出勤人數爲1023次,如今想知道員工編號爲8的小明是否出勤,如何經過早上的簽到錶快速的查詢小明是否出勤呢!在沒有索引的狀況下,一般的作法是從第一條記錄逐個向後查找,若是小明最後一個來或者沒有來,那麼就須要查找1023次,效率爲O(N)。也許會以爲1023次查找對如今的計算機根本不算什麼,可是對於不少系統動輒都是上千萬的數據記錄,你能夠想象查找的時間,好比你用15分鐘終於經過了qq的身份校驗登錄上了qq是一種怎麼樣的體驗。所以,索引就呼之欲出了,咱們如何經過索引來提升一個數量級的查找效率,這個時候就須要對這1024條數據作些什麼了,在每條記錄插入的時候,能夠根據每條記錄的員工編號和存儲該記錄的地址(指針)創建一個二叉查找樹,這樣1023條記錄即可以經過10次查找即可查到,查找效率足足提升了100倍。數據結構

一樣,爲了效率的提高,也付出了一些代價,由於創建二叉查找樹須要額外的存儲空間,同時每次插入數據的時候須要對二叉查找樹進行維護,減緩了數據的更新速度。但綜合來考慮,通常認爲這樣作是值得的。學習

固然在MySQL中,不是採用的二叉樹查找樹來完成索引的存儲的,上面舉得例子只是爲了說明索引的工做過程,但其思想是相同的。MySQL中沒有特殊說明的話,通常說的索引指的就是B-Tree索引,採用B-Tree這種數據結構是綜合了計算機操做系統以及組成而綜合考慮的。其核心思想主要是減小磁盤的IO次數,提升查詢速度。操作系統

如何理解聚簇索引

你只需記住它的名字叫聚簇索引,它不一樣於其餘普通的索引!聚簇索引不只僅是一種索引,更是一種存儲方式,InnoDB中將B-Tree索引和數據行存儲在一個數據結構中,意味着什麼呢?這意味着數據行即索引,索引即數據行,它們是在一塊兒,在一塊兒,在一塊兒的。指針

接着經過來創建字典的例子來理解聚簇索引和其餘普通索引的區別,如今要創建一本中華字典,這個時候字典是空的,要咱們造一本字典出來,首先咱們要完成字典的正文,咱們按照漢語拼音的順序去組織字典的正文,第一個是「安 an 」,放在一個位置,同時後面附加上註釋(這裏,「an」就至關於聚簇索引的關鍵字,然後面的註釋就是數據行,它們存在一塊兒),第二個是「王 wang」字,經過和「安 an」字比較,拼音順序靠後,因此放第二個。注意這裏的放是指存儲在磁盤中的位置,能夠理解爲存儲順序。第三個字是「小 xiao」字,經過拼音順序,須要將第三個字存在第一個字「安」後面,那「王」字已經佔了磁盤頁面的位置,因此它須要向後面移動,若是移出該列,就致使了也分裂,因此能夠看到彙集索引的更新代價真的很大,那爲何還要這樣作呢?聚簇索引帶來了那些好處?code

......,假設按照上面方法已經創建好了字典的正文內容,這個時候就可讓咱們體會一下聚簇索引的好處了,假如你要找「安 an」字,根據拼音序列,你必定知道它必定在前幾個頁面,因此直接能夠翻到前面,同時你也能夠找到拼音「an」所對應的全部的漢字,這就是聚簇索引帶來的好處,同時聚簇索引是和數據行放在一塊兒的,你不須要在根據索引裏的指針找到對應的數據行,而後翻頁找到(翻頁就至關於磁盤IO),這些都是效率的提高。然而,上面也看到了聚簇索引的負面影響好比插入的時候,所以它就像通常利劍,用的合適效率提高,用的糟糕也會帶來很大的很差影響。索引

是時候區別一下非聚聚索引了,這個時候咱們又按照部首創建了一個索引,那麼按照部首創建的索引就是非聚簇索引,它單獨的存在在字典的前幾個頁面,並且同一個部首的字所對應的頁碼也是沒有順序的,若是咱們要山字旁所對應的全部漢字,那就要取不少個頁面的值,致使不少隨機IO產生,同時不能很好利用計算機存儲系統的緩存系統,所以效率遠沒有聚簇索引高。

InnoDB中聚簇索引產生的原則:

  • 當有主鍵時,主鍵爲聚簇索引
  • 當沒有主鍵時,引擎會選擇一個惟一非空列來做爲聚簇索引
  • 若是沒有以上兩種狀況的列,引擎會隱式的定義一個主鍵做爲聚簇索引

最後,經過創建一個數據表來感覺聚簇索引,首先創建有一個沒有主鍵也沒有惟一非空列索引的數據表,即聚簇索引是系統隱式生成這種狀況。這種狀況,通常就是按數據插入的前後順序進行排列。

CREATE TABLE user_log (
    user_id INT NOT NULL,
    place VARCHAR(20) NOT  NULL DEFAULT '',
    login_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP 

) DEFAULT CHARSET utf8;

接下來插入三條數據:

> INSERT INTO user_log(user_id,place)
    VALUES('1','中國');
> INSERT INTO user_log(user_id,place)
    VALUES('2','中國');
> INSERT INTO user_log(user_id,place)
    VALUES('1','美國');

而後,選擇全部列(即按照存儲順序查看數據列),果真如咱們猜測,是按照插入順序存儲的:

>   SELECT * FROM user_log;

user_id place   login_time
1   中國  2015-11-20 10:32:41
2   中國  2015-11-20 10:33:18
1   美國  2015-11-20 10:33:18

接下來,咱們添加一個惟一的索引(ID+login_time),此時 系統引擎應該將此索引做爲聚簇索引,所以咱們再次插入新的數據的時候是按照ID聚簇存儲的,就是說ID相同的會存儲在一塊兒,存儲在同一個頁面,甚至連續的幾個頁面。
下面首先添加這個惟一索引 並接着添加三條新的記錄:

> ALTER TABLE user_log ADD UNIQUE KEY U_USER_LOG_ID_LOGIN_TIME(user_id,login_time);

> INSERT INTO user_log(user_id,place)
    VALUES('1','法國');
> INSERT INTO user_log(user_id,place)
    VALUES('2','日本');
> INSERT INTO user_log(user_id,place)
    VALUES('1','韓國');

而後接着查看數據的存儲狀況:

>   SELECT * FROM user_log;

user_id place   login_time
1   中國  2015-11-20 10:32:41
1   美國  2015-11-20 10:33:18
1   法國  2015-11-20 10:48:00
2   中國  2015-11-20 10:33:18
2   日本  2015-11-20 10:48:00

這樣以來,若是咱們要獲取某一個用戶的登錄狀況,就能夠很是的方便,由於該用戶的全部登錄記錄是按照ID彙集的存儲在一塊兒的,這樣主存緩存一個頁面的數據可能就OK了,若是是非彙集存儲的,假如某個id的數據分散在100個頁面,那麼主存就要緩存這100個頁面,效率可想而知。

總結

這篇文中一開始的構想是想從計算機操做系統的存儲系統和B-Tree入手寫的,結果寫着寫着發現,有點不太現實,一來文章長度可能增長几倍,二來可能本身都寫暈了,既然是小白篇嘛,就先來個綜述吧!總之索引是很是強大並且有意思的,然而當數據量達到必定量時,感受索引也是有點乏力,可是儘可能用好每個索引是很是有必要並且是一種態度。

相關文章
相關標籤/搜索