學過服務器端開發(fā)的朋友一定知道,程序沒有數據庫索引也可以運行。但是所有學習數據庫的資料、教程,一定會有大量的篇幅在介紹數據庫索引,各種后端開發(fā)工作的面試也一定繞不開索引,甚至可以說數據庫索引是從后端初級開發(fā)跨越到高級開發(fā)的屠龍寶刀,那么索引到底在服務端程序中起著怎樣的作用呢?
這篇文章是一系列數據庫索引文章中的第一篇,這個系列包括了下面四篇文章:
數據庫索引是什么?新華字典來幫你 —— 理解
數據庫索引融會貫通 —— 深入
20分鐘數據庫索引設計實戰(zhàn) —— 實戰(zhàn)
數據庫索引為什么用B+樹實現? —— 擴展
這一系列涵蓋了數據庫索引從理論到實踐的一系列知識,一站式解決了從理解到融會貫通的全過程,相信每一篇文章都可以給你帶來更深入的體驗。
什么是數據庫索引?
用一句話來描述:數據庫索引就是一種加快海量數據查詢的關鍵技術?,F在還不理解這句話?不要緊,往下看,20分鐘以后你就能自己做出這樣的總結來了。
首先給大家看一張圖片

這本書大家一定都很熟悉,小學入門第一課一定就是教小朋友們學習如何使用這本書。那這和我們的數據庫索引有啥關系呢?別著急,我們翻開第一頁看看。

請大家注意右上角的那一排文字,原來目錄就是傳說中的索引呀!從前面的“一句話描述”我們可以知道,索引的目的就是為了加快數據查詢。那么我們查字典時翻的第一個地方是哪里呢,我相信大部分人都會先翻到拼音目錄,畢竟現在很多人都是提筆忘字了??。
數據庫索引的作用和拼音目錄是一樣的,就是最快速的鎖定目標數據所在的位置范圍。比如我們在這里要查險這個字,那么我們找到了Xx部分之后就能按順序找到xian這個拼音所在的頁碼,根據前后的頁碼我們可以知道這個字一定是在519頁到523頁之間的,范圍一下子就縮小到只有4頁了。這相比我們從頭翻到尾可是快多了,這時候就出現了第一個專業(yè)術語——全表掃描,也就是我們說的從頭找到尾了。
果然,我們在第521頁找到了我們要找的“險”字。

那么現在我們就知道數據庫索引大概是一個什么東西了:數據庫索引是一個類似于目錄這樣的用來加快數據查詢的技術。
什么是聯合索引?
相信大家都見過一些包含多個字段的數據庫索引,比如INDEX idx_test(col_a, col_b)。這種包含多個字段的索引就被稱為“聯合索引”。那么在多個字段上建索引能起到什么樣的作用呢?下面還是以新華字典為例,來看看到底什么是聯合索引。
新華字典里還有一種目錄被稱為“部首目錄”,下面可以看到,要使用這個目錄我們首先會根據部首的筆畫數找到對應該能的部分,然后可以在里面找到我們想找的部首。比如如果我們還是要找險字所在的位置:

找到部首后,右邊的頁碼還不是險字真正的頁碼,我們還需要根據右邊的頁碼找到對應部首在檢字表中的位置。找到第93頁的檢字表后我們就可以根據險字余下的筆畫數(7畫)在“6-8畫”這一部分里找到險字真正的頁碼了。

在這個過程中,我們按順序使用了“兩個目錄”,一個叫做“部首目錄”,一個叫做“檢字表”。并且我們可以看到上圖中檢字表的內容都是按部首分門別類組織的。這兩個部分合在一起就是我們在本節(jié)討論的主題——聯合索引。即通過第一個字段的值(部首)在第一級索引中找到對應的第二級索引位置(檢字表頁碼),然后在第二級索引中根據第二個字段的值(筆畫)找到符合條件的數據所在的位置(險字的真正頁碼)。
最左前綴匹配
從前面使用部首目錄的例子中可以看出,如果我們不知道一個字的部首是什么的話,那基本是沒辦法使用這個目錄的。這說明僅僅通過筆畫數(第二個字段)是沒辦法使用部首目錄的。
這就引申出了聯合索引的一個規(guī)則:聯合索引中的字段,只有某個字段(筆畫)左邊的所有字段(部首)都被使用了,才能使用該字段上的索引。例如,有索引INDEX idx_i1(col_a, col_b),如果查詢條件為where col_b = 1,則無法使用索引idx_i1。
但是如果我們知道部首但是不知道筆畫數,比如不知道“橫折豎彎勾”是算一筆還是兩筆,那我們仍然可以使用“部首目錄”部分的內容,只是要把“檢字表”對應部首里的所有字都看一遍就能找到我們要找的字了。
這就引申出了聯合索引的另一個規(guī)則:聯合索引中的字段,即使某個字段(部首)右邊的其他字段(筆畫)沒有被使用,該字段之前(含)的所有字段仍然可以正常使用索引。例如,有索引INDEX idx_i2(col_a, col_b, col_c),則查詢條件where col_a = 1 and col_b = 2在字段col_a和col_b上仍然可以走索引。
但是,如果我們在確定部首后,不知道一個字到底是兩畫還是三畫,這種情況下我們只需要在對應部首的兩畫和三畫部分中找就可以了,也就是說我們仍然使用了檢字表中的內容。所以,使用范圍條件查詢時也是可以使用索引的。
最后,我們可以完整地表述一下最左前綴匹配原則的含義:對于一個聯合索引,如果有一個SQL查詢語句需要執(zhí)行,則只有從索引最左邊的第一個字段開始到SQL語句查詢條件中不包含的字段(不含)或范圍條件字段(含)為止的部分才會使用索引進行加速。
這里出現了一個之前沒有提到的點,就是范圍條件字段也會結束對索引上后續(xù)字段的使用,這是為什么呢?具體原因的解釋涉及到了更深層次的知識,在接下來的第二篇文章的最后就可以找到答案。
什么是聚集索引?
從上文的部首目錄和拼音目錄同時存在但是實際的字典內容只有一份這一點上可以看出,在數據庫中一張表上是可以有多個索引的。那么不同的索引之間有什么區(qū)別呢?
我們在新華字典的側面可以看到一個V字形的一個個黑色小方塊,有很多人都會在側面寫上A, B, C, D這樣對應的拼音字母。因為字典中所有的字都是按照拼音順序排列的,有時候直接使用首字母翻開對應的部分查也很快。

像拼音目錄這樣的索引,數據會根據索引中的順序進行排列和組織的,這樣的索引就被稱為聚集索引,而非聚集索引就是其他的一般索引。因為數據只能按照一種規(guī)則排序,所以一張表至多有一個聚集索引,但可以有多個非聚集索引。
在MySQL數據庫的InnoDB存儲引擎中,主鍵索引就是聚集索引,所有數據都會按照主鍵索引進行組織;而在MyISAM存儲引擎中,就沒有聚集索引了,因為MyISAM存儲引擎中的數據不是按索引順序進行存儲的。