索引概念
簡單來説是一個已經排好序,能夠提升查詢效率的數據結構
索引分類
聚簇索引【主鍵索引】
就是索引和數據都在一個葉子節點上
非聚簇索引【非主鍵索引】
索引對應存儲的數據是主鍵值
索引底層採用的是B+樹
B樹
B+樹其實是由一個B樹演化而來的,B樹所有的節點都存儲索引值和行數據,其中一個節點包括
索引:8B
行數據:1K
總共1032B
MySQL是以頁來存儲數據的,一頁大小為16K,索引的大小為8B,數據為1K,所以一層可以存15條數據,依此類推第二層存15*15條數據,第三層存 15 * 15* 15數據...。
可是這樣我們會發現要想存儲大量數據,樹的高度就會越來越高,那麼在查詢的時候,走的路勁越長,查詢的效率就會越來越慢
B+樹
B+樹比B樹的優點就是,它所有的非葉子節點存儲的索引值和指向下個索引值的指針(索引值8B,指針6B)。
由此可知一個節點可以存儲1170條數據【16*1024B/15B】,也就是説第一層可以存1170,第二層存1170*1170,如果我們第三存儲的是葉子節點就可以達到2000W+的總數據量。
葉子節點存儲索引值和數據,也會冗餘存儲非葉子節點的索引值,而且葉子節點使用的是雙向鏈表,可以有效的提升區間訪問效率
選擇區別
為什麼不選擇Hash結構呢?
因為Hash結構只支持夠進行等值查詢,不支持範圍查詢
為什麼選擇B+ 樹?
因為非葉子節點和葉子節點存儲的數據是不一樣的。
B樹如果有大量數據的話,樹的深度就會變的很高。當我們查詢時,走的路徑會很長,查詢速度就會變得很慢;
B+樹只有葉子節點存儲數據,這樣可以大大降低樹的深度,當我們查詢時,由於非葉子節點存儲的都是索引,而且葉子節點是一個雙向鏈表,支持範圍範圍查詢,可以大大提高了查詢速度。
主鍵索引
非葉子結點存儲主鍵值,葉子節點存儲行數據,所有可以直接通過主鍵就可以指向在索引樹找到數據,不需要查表,速度非常快。
MySQL默認使用的是InnoDB引擎,InnoDB支持主鍵索引,但是InnoDB引擎必須要主鍵,如果不創建主鍵,那麼數據庫會自動創建並維護這個主鍵索引,但是我們不知道這個主鍵索引是怎麼維護的,所以不推薦。這裏給個建議,創建主鍵一定是沒有業務意義的列,如果是有業務意義的列,後續我們進行業務操作時會很麻煩。
我還推薦使用主鍵自增策略
因為插入的數據始終會放在最後面,可以快速的找到插入的位置,無需做額外的開銷,如移動數據的位置,旋轉樹等;
如果不是自增,那麼就無法判斷要插入的數據具體是插入到索引樹的哪個一位置,所以也無法判斷樹中數據的變化與樹的旋轉。那麼就會帶來不必要的開銷。
非主鍵索引
非主鍵索引分為普通索引、唯一索引、聯合索引、全文索引這裏全文索引我使用的是Elasticsearch所以不多過講解。
普通索引
就是在普通字段上建立索引
非葉子節點存儲索引列值
葉子節點存儲主鍵值
那麼為什麼我們非主鍵索引的葉子節點數據存儲的是主鍵值?
因為如果不存主鍵值,那麼就只能存儲數據。
如果數據發生了變化,不僅要維護主鍵索引,同時還需要維護其他索引。
如果修改了一個索引的數據,會同時修改其他索引的數據,這會帶來額外的開銷
唯一索引
給唯一列創建索引,unique,表示該字段不能夠重複
聯合索引
給主鍵以外的多個列創建索引,也叫聯合索引【組合索引】
比如説一個表中字段有id,name,age,phone,那麼我們就可以創建索引字段為name,age,phone。
創建索引的要求
- 單表索引不超過5個
- 聯合索引的字段不超過5個,如果業務需要超過5個並且能夠提升查詢速度那就儘管創建吧
- 經常增刪改的字段不適合創建索引
- 枚舉值字段不適合創建索引,因為量太小了,例如男女性別枚舉,0保密,1男性,2女性,你就算窮舉也不用花多少時間
- 大長度的字段,可以設置前綴索引(為字段的前幾個字符建立索引)
CREATE TABLE users (
user_id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(255),
email VARCHAR(255)
);
-- 創建前綴索引
CREATE INDEX idx_username_prefix
ON users (username(10));
創建索引語法
主鍵索引:命名要求:pk_列名
普通索引:create index 索引名稱 on 表名(具體的列名) 命名要求:idx_列名
唯一索引:create unique index 索引名稱 on 表名(列名) 命名要求:uk_列名
聯合索引:create index 索引名稱 on 表名(列1,列2) 命名要求:idx_列1_列2