【數據庫】數據庫建立索引的原因

一、 爲什麼加索引

  • 主要原因:可以利用二分查找大大加快數據的檢索速度(B+樹)

  • 通過創建唯一性索引,可以保證數據庫表中每一行數據的唯一性

  • 可以加速表和表之間的連接

二、 如何加索引

1. 場景介紹

引入一個場景,以下面的表爲例,這個表有5個字段,分別是id,name,time,subject和grade,我們要進行如下兩種操作

  • 查詢某一個人某一門科目在某一天考了多少分
  • 查詢某一個人某一門科目在某個時間範圍內分別考了多少分
字段名 字段含義
id 主鍵id
name 姓名
time 時間
subject 科目
grade 成績

假設數據如下

id name time subject grade
1 Bob 3 English 95
2 Jack 3 English 98
3 Jack 3 Math 97
4 Bob 6 English 90
5 Bob 8 English 93
6 Bob 7 Math 100

假設我們現在需要查詢Bob在第3天英語考了幾分,由於存儲結構亂序的,所以數據庫內部只能一個個遍歷然後比較name,subject和time是否滿足條件,其複雜度爲O(n),非常低效

select * from test_index 
where name = 'Bob' 
and time = 3 
and subject = 'English';

2. 加入索引

給數據表加索引其實就是給某個字段建立了一個排序表,相當於圖書館裏給每本書進行編號,並按照順序放在書架上,我們要想找到指定編號的圖書時,只需要使用類似二分查找的方式,就可以快速找到對應的圖書了。

二分查找時間複雜度爲O(logn),當n爲109時,大約只要執行30次對比,所以相比於O(n)的複雜度高效不少

加了索引之後,數據庫會分配一個額外的空間,用來存儲索引表,每次對數據庫進行插入、刪除和修改的時候也會修改索引表,所以增加索引之後,會增加數據庫的大小和以及數據庫修改的時間。因此如果數據庫修改多而查詢少,就要考慮增加索引的性價比。

舉個例子,我們對上面的表中的name字段增加索引

ALTER TABLE `normandb`.`test_index` 
ADD INDEX `index`(`name`) USING BTREE

然後索引表就會變成如下般呈現

name id time subject grade
Bob 1 3 English 95
Bob 4 6 English 90
Bob 5 8 English 93
Bob 6 7 Math 100
Jack 2 3 English 98
Jack 3 3 Math 97

可以看到,索引表按照name進行了排序,這樣的話,如果我們要按照name去進行查詢的時候,能很快地在索引表裏找到符合要求的name。

顯而易見,之前我們的查詢,需要給name,time和subject都加上索引,那是不是直接給這三個字段都加上索引就行了呢?

ALTER TABLE `normandb`.`test_index` 
ADD INDEX `index`(`name`) USING BTREE,
ADD INDEX `index2`(`time`) USING BTREE,
ADD INDEX `index3`(`subject`) USING BTREE

冷靜分析,這其實是不可以的,如果爲每一個字段各自建一個索引,那就會建立三個依照各自字段進行排序的索引表,當我們使用完name索引之後拿到的數據在time索引表中是亂序的,所以就無法二分查找了。

所以就要用到組合索引。

3. 組合索引

ALTER TABLE `normandb`.`test_index` 
ADD UNIQUE INDEX `index`(`name`, `time`, `subject`) USING BTREE;

用上面語句我們就可以建立一個基於name,time,subject三個字段的索引,數據庫就會按照創建時的順序,對各個字段進行排序建立索引表,如下所示

name time subject grade
Bob 3 English 95
Bob 6 English 90
Bob 7 Math 100
Bob 8 English 93
Jack 3 English 98
Jack 3 Math 97

這樣的話,去查找我們需要的信息,只需要進行三次二分查找就行了,時間複雜度爲O(k*logn)

PS : 可以注意到上面建立索引的時候用了UNIQUE INDEX,這個其實就是唯一索引,確定了唯一索引之後,數據表中這三個字段一模一樣的數據只能出現一次,之後插入會執行失敗,可以保證唯一性

4. 範圍查詢

如果我們想要知道Bob在第5天到第8天的英語成績分別是多少,數據庫語句應該是這樣

select * from test_index 
where name = 'Bob' 
and time >= 5 and time <= 8
and subject = 'English';

這時候我們回去看看上面建立的組合索引,就會發現對time進行排序之後,篩選出的數據subject字段是亂序的,那麼查詢效率就又下降了不少了,因爲subject字段相當於要在time字段相等的情況下才會保持有序。

所以增加索引的語句應該是這樣

ALTER TABLE `normandb`.`test_index` 
ADD UNIQUE INDEX `index`(`name`, `subject`, `time`) USING BTREE;

三、 總結

  • 使用索引能夠加快查詢速度
  • 經常作爲查詢條件的字段可以設置索引
  • 設置索引會降低修改數據時的效率,不是越多越好
  • 在建立索引的時候:等值查詢的字段,儘量放在範圍查詢的字段前面
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章