mysql的索引結構


 

為甚要設計索引? 

如何設計索引?

設計索引時使用什么數據結構?

mysql是如何實現的?

 

數據庫里的數據都保存在磁盤里。

 

文件

1.關鍵值:key

2.文件名稱

3.偏移量 offset

 

索引的文件存儲形式與引擎有關:

mysql中的存儲引擎:myisam,innodb,memory

memory用的是hash索引

myisam,innodb 用的是b+tree索引

大部分說的存儲引擎都是innodb。

在mysql中輸入 “show index from 表名” 就可以查看引擎

 

數據都是放在磁盤中,讀數據的時候是從磁盤讀到內存當中的。

磁盤的讀寫速度比內存小很多很多。

因此把磁盤數據加載到內存讀。

把經常訪問的數據可以從磁盤讀出來放在內存中。

 

局部性原理:

程序和數據的訪問都有聚集成群的傾向,

在一段時間內,僅僅使用其中一小部分(稱空間局部性)

或者最近訪問過的程序代碼和數據,很快又被訪問的可能性很大(稱時間局部性)

 

磁盤預讀(預讀的長度一般為頁page的整數倍):

頁是存儲器的邏輯塊

操作系統往往將主存和磁盤分成連續的大小相等的塊,每個存儲塊稱為一頁(頁大小通常為4k),

主存和磁盤以頁為大小交換數據。

磁盤預讀每次讀4k的倍數,一次加載一個磁盤塊16k

即便是查一個數據a,加載的也是一個塊,而不是只加載a。

 

索引是幫助mysql高效獲取數據的數據結構。

索引存儲在文件系統中。

索引文件結構:hash,二叉樹,b tree, b+tree

 

 

為什么mysql中選擇b+ tree??

 二叉樹,BST, AVL, 紅黑樹,這些樹的節點里存的都是一個值。

但是我們索引的時候是從磁盤讀數據的,每次返回的是一個數據塊

而不是取一個值。

像innodb,myisam每次都是取16k的數據,這樣就會取出來很多個節點,

節點越多,樹越深,造成io次數變多。

 

提升IO的效率只有2個途徑:

減少IO的次數

減少IO的量(大小)

所以公司一般不讓用select * 查詢

 mysql里面有一個服務層,每次交互的時候需,

要服務層從存儲引擎里把數據拉出來,

在服務層篩選完畢之后,再返回給客戶端

所以如果用select * 查詢就會增大IO量

 

B樹和B+tree 節點里放的不是一個值而是值的集合:

degree 叫做階,表示單個節點里可以放置多少個數據元素。

degree = 4 的時候,每個節點可以放3個節點。

一個節點可以放置degree - 1 的數據

 

假設查id是28這條數據,這些數據都是在磁盤里的,

假設磁盤塊1是16k(innodb默認讀16k),從磁盤塊1開始找,到磁盤塊8,

一共是磁盤塊1+磁盤塊3+磁盤塊8,內存一共加載了3個16k的磁盤塊

從頭到尾讀了48k數據

 

在B tree中每個磁盤塊的大小跟data 相關,上圖中

一個磁盤塊里有2個data,假如1行數據是1k,那么一個數據塊就存16條

一個磁盤塊16k換算成字節是16000,圖1中“指針”+“鍵值”假如算一組的話,

假設一組10個字節,那么一個磁盤塊可以存1600組。

在第三層的葉子層上,一條數據占1k,那么葉子層還是只有16條數據。

之前的b tree 3層一共存的數據量是16*16*16,

現在b + tree存的數據量是1600*1600*16

 

B+ tree是把所有的data都放在了最下面的葉子上,節點上不再放data,

這樣就節省了節點上的存儲空間

 

b+tree有2種查找方式:從根節點開始查找; 也可以通過雙向鏈表從最小葉子節點開始找。

 

myisam和Innodb的數據結構都是b+tree,從上圖中可以看到區別是:

Innodb最后的葉子節點存放的是完整數據,這種數據和索引存放在一起的叫做聚簇索引

myisam最后的葉子節點放的是地址,通過地址再查找數據,數據和索引分開存放的叫非聚簇索引

 

一般創建數據庫都是主鍵自增的,這種適用於單機數據庫。

如果是分布式就不能用主鍵自增,需要用雪花算法設置主鍵。

 

key值包括:主鍵,唯一鍵,row_id


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM