MySQL索引机制:索引分类、索引的实现原理、索引的优化 - 公开课笔记
概要
oracle市場份額在降低,mysql變得越來越重要
樣本數據可以使用 sakila 數據庫
你會怎么設計索引?
加索引目的是快速查找數據,最終要快速從文件中快速獲取一條記錄。
如果使用id+偏移量+數據文件作為索引,會使得索引文件非常大,然后需要給索引文件加索引
于是會產生索引,索引的索引,索引的索引的索引...
OLAP:對歷史數據的分析,比如Hive
OLTP:關系型數據庫都是OLTP,要求在最短時間內返回最終結果
為什么選擇B+樹?
MySQL B+ 樹的根節點、葉子結點都存儲與磁盤中。加載時,優先將根節點加載至內存中。現在PC的內存大了,可以將所有的非葉子結點都加載進內存中。
局部性原理
空間局部性、時間局部性、磁盤預讀(一次讀一頁,通常操作系統設定為為4k)
應用程序也能自己設定頁的大小,innodb一頁為16kb
索引是什么?
存儲引擎是不同的數據表在文件系統中的組織形式。
不同存儲引擎之間的區別
常見存儲引擎: innodb, myisam, memory…
數據組織的形式不同;
innodb支持事務,myisam不支持事務
innodb支持行鎖+表鎖,myisam只支持表鎖
innodb這么好,為什么還要有myisam?
myisam的查詢、計算效率較高。
mysql誕生以來,只有myisam。innodb是后來以插件的形式集成到mysql中,現在默認是innodb
其他幾種數據結構
Hash索引
memory存儲引擎在使用Hash索引。innodb默認使用B-tree,但根據官網文檔,Memory tables也支持哈希索引。
Hash劣勢:rehash,哈希沖突問題。不好的hash算法導致散列不均勻,浪費磁盤空間。
jdk1.8的哈希函數算法使用了擾動函數,也是為了讓散列更均勻
二叉樹
提升IO效率:減少IO次數、減少IO量(生產中SQL語句中不要隨意用*匹配,應該只取有用數據)
https://www.cs.usfca.edu/~galles/visualization/Algorithms.html
二叉樹:如果在插入的時候排序,形成BST(二叉搜索樹)
二叉搜索樹
插入遞增時,退化成鏈表:
AVL(二叉平衡樹)
最長路徑、最短路徑之差不能超過1,是一棵嚴格的平衡樹,插入過程中需要頻繁旋轉,插入性能高,查詢性能低。
紅黑樹
不是一棵嚴格意義上的平衡樹,是相對平衡。
紅黑樹的最長路徑只要不超過最短路徑的2倍即可。
還有一些其他限制…
但也存在存數較高的問題
層數高,問題在于一個節點中有且只有兩個分支。于是有了B樹:
B樹
Degree用來表示每一個節點中最多能放多少條數據。
MySQL中的層高是由數據量決定的,無法人為控制。3層高,千萬數據量都能存放進去。
一個磁盤16kb,一條數據1kb,假設其他指針不占用空間,每個空間能放16條數據,4096條數據就要存3層,原因是數據放在節點上,占用了磁盤空間
如果把所有的數據都存儲在葉子結點里面,節省了空間,就成為了B+樹
B+樹
非葉子結點只存儲key,不存儲數據。所有數據都放在葉子結點中存儲。
8條數據的 B樹
8條數據的 B+ 樹
聚簇索引:innodb,數據和索引放在一起。如果不設置主鍵,innodb會選擇一個唯一鍵,如果沒有唯一鍵,innodb會生成一個6字節的rowid存儲,對用戶是不可見的。
oracle中可以看到rowid
非聚簇索引:數據和索引不放在一起,myisam
上圖中,id是索引。如果給name又加了索引,會再建立一個B+樹,葉子結點存的是關聯主鍵,而不是直接存數據。如下:
索引分幾類
按照索引的存儲來劃分:
聚簇索引:innodb
非聚簇索引:myisam
按照使用來分:
主鍵索引:主鍵所關聯的數據
唯一索引:mysql 默認會給唯一鍵添加索引
普通索引(輔助):
- 回表:通過普通索引去樹中查找返回主鍵值,根據主鍵取索引樹查找數據。(line18)
- 覆蓋索引:執行計劃能看到using index。不需要回表(line19)
組合索引:
- 最左匹配原則
- 謂詞下推、索引下推:
join有幾種實現方式?
什么時候會索引失效?
全文索引:
雖然提供了全文索引這種功能,但很少有人用。
檢索一般不在數據庫層面用模糊查詢like去做。搜索引擎常用Solr,ES和Lucene 信息檢索庫
驗證 mysql 默認會給唯一鍵添加索引:
show index from test查看索引,看到name已經加了索引
其他
阿里一個面試題:MySQL的一個自增列,當前id為9,兩個線程同時寫,怎么保證寫入的是10和11而不是兩個10?
索引選擇性:如果age列一共100條記錄,唯一值只有10個,不建議添加索引。比如一些flag字段。
要看基數
hyperloglog算法用來計算基數,redis中使用到了這個算法。
創建表的時候要不要讓id自增?
要,這樣每次都是往后追加,不涉及頁分裂過程
總結
以上是生活随笔為你收集整理的MySQL索引机制:索引分类、索引的实现原理、索引的优化 - 公开课笔记的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于MySQL使用Float存储时的精度
- 下一篇: linux cmake编译源码,linu