MySQL 性能调优专题一(索引数据结构详解)
索引的本質(zhì)
索引是幫助MySQL 高效獲取數(shù)據(jù)的排好序的數(shù)據(jù)結(jié)構(gòu)。
MySQL 默認使用的是B+Tree數(shù)據(jù)結(jié)構(gòu)。
磁盤的讀取原理
在介紹結(jié)構(gòu)之前,先簡單說下磁盤的讀取原理:
操作系統(tǒng)讀寫磁盤的基本單位是扇區(qū),而文件系統(tǒng)的基本單位是簇(Cluster)。
MySQL在存儲數(shù)據(jù)時數(shù)據(jù)都存儲在磁盤的一道道扇區(qū)中,磁盤是旋轉(zhuǎn)的,每次存儲的數(shù)據(jù)可能會存儲在不同的扇區(qū)中。
在讀取時,磁道每次需要先進行尋道操作(速度慢),磁頭只能進行左右移動,每一次尋道都是一次I/O操作。
如果數(shù)據(jù)都存在同一磁道中,那么旋轉(zhuǎn)磁盤(速度快)就可以取到數(shù)據(jù),不需要進行尋道操作,會大大減少開銷。
(這里是我自己的理解,如果有不對的地方,歡迎大家指出來)
索引結(jié)構(gòu)
給大家推薦一個數(shù)據(jù)結(jié)構(gòu)可視化網(wǎng)站,可以直觀的演示各種結(jié)構(gòu)
二叉樹
如果普通的一顆二叉樹,在極端情況下會退化成鏈表結(jié)構(gòu)。如圖:
紅黑樹
和二叉樹一樣,在數(shù)據(jù)量大的情況下,樹的深度太大,查詢次數(shù)過高。
比如,有500W的數(shù)據(jù),假如樹的高度有20層,你要查詢的數(shù)據(jù)剛好在葉子節(jié)點,那么需要進行20次尋道操作,和磁盤進行20次I/O交互操作,大大加大了開銷。
HASH 索引
HASH索引,相比較于B-Tree 而言,不需要從根節(jié)點到葉子節(jié)點的遍歷,可以一次定位到位置,查詢效率更高,但缺點也很明顯:
-
僅能滿足全值查詢,不能使用范圍查詢。因為是通過HASH值進行計算,HASH值是沒規(guī)律的,所以只能精確查詢,不能保證順序和原來一致,所以不行進行范圍查詢。
-
不能進行排序,原因如上。
-
HASH碰撞。
B+Tree
-
B+Tree 是平衡樹的一種,并且所有葉子節(jié)點位于同一層,是不會退化成鏈表結(jié)構(gòu)的。
-
B+Tree 有一個度的概念,指節(jié)點的數(shù)據(jù)存儲個數(shù)。度越大,節(jié)點保存的數(shù)據(jù)個數(shù)就越多。那么相應(yīng)的樹的高度降低,在進行查詢時,需要進行的I/O操作更少,讀取數(shù)據(jù)的速度更快。
-
非葉子節(jié)點不存儲data,只存儲key,可以增大度。葉子節(jié)點只存儲data, 不存儲指針,順序訪問指針,可以提高區(qū)間訪問的性能。
-
進行查找操作時,首先在根節(jié)點進行二分查找,找到一個key所在的指針,然后遞歸的在指針所指向的節(jié)點進行查找。直到查找到葉子節(jié)點,然后在葉子節(jié)點上進行二分查找,找出 key 所對應(yīng)的 data。
B+Tree 結(jié)構(gòu)示意圖
B+Tree 索引的性能分析
-
一般使用磁盤I/O次數(shù)評價索引結(jié)構(gòu)的優(yōu)劣
-
預(yù)讀:磁盤一般會順序向后讀取一定長度的數(shù)據(jù)(頁的整數(shù)倍)放入內(nèi)存。
-
局部性原理:當一個數(shù)據(jù)被用到時,其附近的數(shù)據(jù)也通常會馬上被使用。
-
B+Tree 節(jié)點的大小設(shè)為等于一個頁,每次新建節(jié)點直接申請一個頁的空間,這樣就保證一個節(jié)點物理上也存儲在一個頁里,就實現(xiàn)了一個節(jié)點的載入只需一次I/O。
-
B+Tree 的度一般會超過100,因此高度非常小(一般為3到5之間)
MySQL 存儲引擎
MyISAM (非聚集)
-
MyISAM 索引文件和數(shù)據(jù)文件是分離的。
-
MyISAM 引擎使用B+Tree 作為索引結(jié)構(gòu),MyISAM的索引文件僅僅保存數(shù)據(jù)記錄的地址。
-
MyISAM中,主索引和輔助索引在結(jié)構(gòu)上沒有任何區(qū)別,只是主索引要求key是唯一的,而輔助索引的key可以重復(fù)。
MyISAM存儲結(jié)構(gòu)示意圖
InnoDB (聚集)
-
數(shù)據(jù)文件本身就是索引文件。
-
InnoDB 引擎也使用B+Tree 作為索引結(jié)構(gòu),葉節(jié)點包含了完整的數(shù)據(jù)記錄。
-
InnoDB的數(shù)據(jù)文件本身要按主鍵聚集,所以InnoDB要求表必須有主鍵(MyISAM可以沒有)。
-
InnoDB中,主鍵索引包含了完整的數(shù)據(jù)記錄,而輔助索引都引用主鍵作為data域。
InnoDB存儲結(jié)構(gòu)示意圖
知道了InnoDB的索引實現(xiàn)后,就明白了為什么不建議使用過長的字段作為主鍵了,因為所有輔助索引都用主索引,過長的主索引會令輔助索引變得過大。
MyISAM和InnoDB區(qū)別
-
事物:InnoDB支持事務(wù),可以使用 Commit 和 Rollback 語句。MyISAM不支持。
-
并發(fā):MyISAM 只支持表級鎖,而InnoDB 還支持行級鎖。
-
外鍵:InnoDB 支持外鍵,MyISAM不支持。
-
備份:InnoDB 支持在線熱備份,MyISAM不支持。
-
崩潰恢復(fù):MyISAM 崩潰后發(fā)生損壞的概率比 InnoDB 高很多,而且恢復(fù)的速度也更慢。
-
其它特性:
InnoDB是聚集索引,MyISAM是非聚集索引。
InnoDB不保存表的具體行數(shù),MyISAM用變量保存了整個表的行數(shù)。
InnoDB不支持全文索引,MyISAM支持全文索引。
MyISAM 支持壓縮表和空間數(shù)據(jù)索引。
索引分類
索引分類
-
主鍵索引:是一種特殊的唯一索引,不允許有空值。設(shè)定為主鍵后數(shù)據(jù)庫會自動建立索引innodb為聚集索引。
-
唯一索引:索引列中的值必須是唯一的,但是允許為空值。
-
單值索引:索引只包含單個列,但一個表中可以有多個單值索引。
-
復(fù)合索引:在表中的多個字段組合上創(chuàng)建的索引,只有在查詢條件中使用了這些字段的左邊字段時,索引才會被使用,使用組合索引時遵循最左前綴原則。
-
全文索引:只有在MyISAM引擎上才能使用,只能在CHAR、VARCHAR、TEXT類型字段上使用全文索引,在一堆文字中,通過其中的某個關(guān)鍵字等,就能找到該字段所屬的記錄行。比如有"怡紅院、金鳳樓"等等,可以 通過金鳳樓,可能就可以找到該條記錄。
-
空間索引:只有在MyISAM引擎上才能使用,創(chuàng)建空間索引的列,必須將其聲明為NOT NULL。空間索引是對空間數(shù)據(jù)類型的字段建立的索引,MySQL中的空間數(shù)據(jù)類型有四種,GEOMETRY、POINT、LINESTRING、POLYGON。在創(chuàng)建空間索引時,使用SPATIAL關(guān)鍵字。
最左前綴原則
-
B+Tree 是按照第一個關(guān)鍵字進行索引,然后在葉子節(jié)點上按照第一個關(guān)鍵字、第二個關(guān)鍵字、第三個關(guān)鍵字…進行排序。使用復(fù)合索引的時候,會根據(jù)你的索引順序,從左開始匹配。
-
索引只能用于查找key是否存在(相等),遇到范圍查詢(>、<、between、like左匹配)等就不能進一步匹配了,后續(xù)退化為線性查找。
復(fù)合索引的底層存儲結(jié)構(gòu)
索引的優(yōu)缺點
優(yōu)點
-
提高查詢效率(降低IO使用率)。
-
降低CPU使用率, 例如:...order by age desc,因為B+Tree 索引本身就是一個排好序的結(jié)構(gòu),因此在排序時可以直接使用。
缺點
-
索引本身很大,實際上索引也是一張表,該表保存了主鍵與索引字段,并指向?qū)嶓w表的記錄,所以索引列也是要占用空間。
-
索引會降低增刪改的效率,MySQL不僅要保存數(shù)據(jù),還要保存一下索引文件每次更新添加了索引列的字段, 都會調(diào)整因為更新所帶來的鍵值變化后的索引信息。
-
索引不是所有情況均適用:A. 少量數(shù)據(jù) B.頻繁更新的字段 C.很少使用的字段
需要建立索引的情況
-
主鍵自動建立唯一索引。
-
頻繁作為查詢條件的字段應(yīng)該創(chuàng)建索引,WHERE 后面的語句。
-
查詢中與其它表關(guān)聯(lián)的字段,外鍵關(guān)系建立索引。
-
單鍵/組合索引的選擇問題,who?在高并發(fā)下傾向創(chuàng)建組合索引。
-
查詢中排序的字段,排序字段若通過索引去訪問將大大提高排序速度。
-
查詢中統(tǒng)計或者分組字段。
轉(zhuǎn)載于:https://juejin.im/post/5ce4106d6fb9a07ed91196ad
總結(jié)
以上是生活随笔為你收集整理的MySQL 性能调优专题一(索引数据结构详解)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: vue输入框联想词功能
- 下一篇: linux cmake编译源码,linu