文章目錄
磁盤存取原理
mysql的數據最終是在磁盤的,讀取數據也是從磁盤讀取。
那麼就有必要知道磁盤的工作原理。
如圖所示磁盤的結構圖。
磁盤是逆時針旋轉的,而磁頭只能左右移動。磁頭通過左右移動來劃定磁道,從磁道中獲取數據,數據存儲在各個磁道的扇區中。
如果一個數據表中的數據,存儲在不同的磁道中,那麼就需要多次尋道,耗時就會長。
數據結構
非常直觀,很好用。
數據結構動態演示網站
mysql爲什麼採取BTREE、HASH的數據結構?而沒有采取二叉樹、紅黑樹的數據結構。可以去這樣網站試一下上述數據結構就清楚了。
因爲二叉樹、紅黑樹當數據量大時,都會導致數據深度太大。
Hash我們也很少用,因爲hash對範圍查詢不友好。
BTREE的優點是的mysql的索引基本都是用BTREE。不過mysql的底層用的是B+TREE,比BTREE更高效。
BTREE的度(Degree)-節點的數據存儲個數。存儲個數不能無限大,因爲磁盤每次讀取數據是有限的,比如磁盤每次讀取20kb的數據,而節點存儲了10M的數據,那麼就需要讀取10M/20kb次。一樣會導致效率極低。
磁盤一頁是4kb大小,而i你如果能保證每個B+TREE的節點是4kb大小。這樣就提高了效率。
二叉樹:
紅黑樹:
B-TREE:
我們提到的查詢磁盤存取原理,我們找磁盤其實是找節點,節點數據會讀取到內存,內存再讀取,內存的速度可以忽略不計。所以BTREE我們查詢0004的話,就是把包含0002、0004的節點讀取到內存。
B+TREE
B-TREE數據存儲方式:
mysql的B+TREE數據存儲方式
B+TREE的指針更方便mysql進行範圍查詢。
B+Tree索引的性能分析:
- 一 般 使 用 磁 盤 I/ O次 數 評 價 索 引 結 構 的 優 劣
- 預 讀 : 磁 盤 一 般 會 順 序 向 後 讀 取 一 定 長度的數據(頁的整數倍)放入內存
- 局 部 性 原 理 : 當 一 個 數 據 坫 用 到 時 , 其 附 近 的 數 據 也 通 常 會 馬 上 被 使 用
- B+ Tree節 點 的 大小 設 爲 等 於 一 個 頁 , 每 次 新 建 節 點 直 接 中 訪 一 個 頁 的 空 間 , 這 樣 就 保 證 一 個 節 點 物理上也 存 儲 在 一 個 頁 裏 , 就 實 現了一 個 節 點 的 載入只需一 次 I/O
- B+ Tree的 度 d—般會超過100,因此h非常小(一般爲3到5之間)
mysql存儲引擎
MyISAM和InnoDB。這兩個存儲引擎都是表級別的。
MyISAM
MyISAM存儲引擎存儲方式:
實際上MyISAM的B+TREE不存儲data,而是存儲data的指針。
MyISAM的主鍵索引和非主鍵索引一樣。。
題外:如果用UUID作爲表的主鍵,方便數據庫做遷移。
InnoDB
實際上InnoDB的B+TREE存儲了data
InnoDB的主鍵索引和非主鍵索引不一樣。
聯合索引的底層數據結構
字符串類型
如title、name兩個字段均爲字符串類型組成聯合索引,那麼聯合索引的就是title+name這樣加起來作爲一個字符串索引。
多種數據類型組成的聯合索引
如圖所示:第一個爲int類型,第二個爲varchar,第三個爲date。
那麼聯合索引會先用第一索引去比較,第一索引相同再用第二索引比較,第二索引相同再用第三索引去比較。
聯合索引使用情況
注意: mysql的單個索引是聯合索引的特殊情況
create table test(
a int ,
b int,
c int,
d int,
key index_abc(a,b,c)
)engine=InnoDB default charset=utf8;
查詢語句
EXPLAIN
SELECT *
FROM `test` WHERE a='a';-- true
EXPLAIN
SELECT *
FROM `test` WHERE b='b'; -- false
EXPLAIN
SELECT *
FROM `test` WHERE c='c'; -- false
EXPLAIN
SELECT *
FROM `test` WHERE a='a' AND b='b'; -- true
EXPLAIN
SELECT *
FROM `test` WHERE b='b' AND a='a';-- true
EXPLAIN
SELECT *
FROM `test` WHERE a='a' AND c='c';-- true
EXPLAIN
SELECT *
FROM `test` WHERE c='c' AND a='a';-- true
EXPLAIN
SELECT *
FROM `test` WHERE c='c' AND b='b';-- false
EXPLAIN
SELECT *
FROM `test` WHERE b='b' AND c='c';-- false
EXPLAIN
SELECT *
FROM `test` WHERE a='a' AND b='b' AND c='c';-- true
EXPLAIN
SELECT *
FROM `test` WHERE a='a' AND c='c' AND b='b';-- true
EXPLAIN
SELECT *
FROM `test` WHERE b='b' AND c='c' AND a='a';-- true
EXPLAIN
SELECT *
FROM `test` WHERE b='b' AND a='a' AND c='c';-- true
EXPLAIN
SELECT *
FROM `test` WHERE c='c' AND b='b' AND a='a';-- true
EXPLAIN
SELECT *
FROM `test` WHERE c='c' AND a='a' AND b='b';-- true
EXPLAIN
select * from test where b<10 and c <10;-- false
EXPLAIN
select * from test where a<10 and c <10;-- ture
mysql查詢優化器會判斷糾正這條sql語句該以什麼樣的順序執行效率最高,最後才生成真正的執行計劃。所以,當然是我們能儘量的利用到索引時的查詢順序效率最高,所以mysql查詢優化器會最終以這種順序進行查詢執行。
所以當a字段不在最左時,mysql會自動調整到最左的位置然後再執行。
而根據聯合索引數據結構圖也可以看出,必須有a字段,聯合索引纔會生效。
另外的例子:
劃重點(∩_∩)
本人程序媛一枚,因爲離港澳較近,週末兼職港澳人肉代購。
歡迎各位大佬添加本人微信,還會經常有點贊活動送價值不菲的小禮品哦。
即使現在不需要代購,等以後有了女(男)朋友、有了寶寶就肯定會需要的嘍。
動動手指頭,掃碼一下,就當是對本博文的支持嘛,也是對一個平凡、勤勞、勇敢、秀外慧中等等優點的程序媛莫大的支持哈。