數據庫磁盤讀取與系統磁盤讀取
1,系統從磁盤中讀取數據到內存時是以磁盤塊(block)為基本單位,位於同一個磁盤塊中的數據會被一次性讀取出來。
2,innodb存儲引擎中有頁(Page)的概念,頁是數據庫管理磁盤的最小單位,innodb存儲引擎中默認每個頁的大小為16kb,每次讀取磁盤時都將頁載入內存中。
3,系統一個磁盤塊的大小空間往往沒有16kb這么大,因此innodb每次io操作時都會將若干個地址連續的磁盤塊的數據讀入內存,從而實現整頁讀入內存
問題:數據庫的數據結構時怎樣的?B樹和B+樹有什么區別,為什么選擇B+樹作為存儲數據的結構,而不是B樹?
B樹和B+樹
Btree
一個M階的B-tree有如下特點
1,每個節點最多有m個孩子(分叉),
2,除了根節點和葉子節點外,其他每個節點至少有ceil(m/2)個孩子
3,若根節點不是葉子節點,則至少有兩個孩子
4,所有葉子節點都再同一層,且不包含其他關鍵字信息
5,每個非終端節點包含n個關鍵字信息,關鍵字的個數n滿足ceil(m/2)-1<=n<= m-1 其中m為階數
6,ki(i=1,…n)為關鍵字,且關鍵字(主鍵primary key)升序排序。
7,. Pi(i=1,…n)為指向子樹根節點的指針。P(i-1)指向的子樹的所有節點關鍵字均小於ki,但都大於k(i-1);
B-tree每個節點都包含指針,key以及data,每個節點含有三個指向子節點的指針和兩個升序排序的關鍵字(key)
模擬查找關鍵字29的過程:
1. 根據根節點找到磁盤塊1,讀入內存。【磁盤I/O操作第1次】
2. 比較關鍵字29在區間(17,35),找到磁盤塊1的指針P2。
3. 根據P2指針找到磁盤塊3,讀入內存。【磁盤I/O操作第2次】
4. 比較關鍵字29在區間(26,30),找到磁盤塊3的指針P2。
5. 根據P2指針找到磁盤塊8,讀入內存。【磁盤I/O操作第3次】
6. 在磁盤塊8中的關鍵字列表中找到關鍵字29。
分析上面過程,發現需要3次磁盤I/O操作,和3次內存查找操作。由於內存中的關鍵字是一個有序表結構,可以利用二分法查找提高效率。而3次磁盤I/O操作是影響整個B-Tree查找效率的決定因素。
B樹上大部分的操作(插入、刪除、查詢)所需要的磁盤存取次數和B樹的高度是成正比的,並且B樹是盡量多的在節點上存儲信息,保證導數盡量少,在B樹中可以檢查多個子結點,由於在一棵樹中檢查任意一個結點都需要一次磁盤訪問,所以B樹避免了大量的磁盤訪問,減少了磁盤I/O。
B+tree
毫無疑問,減少樹的高度是有效減少IO次數提高效率的方式,b-tree結構每個節點不僅包含key值,還有data值,每一個頁的存儲(16kb)是有限的,每個節點可容納的指針和keydata是有,如果data數據含量大,那么一個頁保存的指針和key的數量就會減少,從而增頁節點的數量,這就增加btree的深度,增加讀取磁盤的次數,進而影響查詢效率
而在b+tree中,一個節點記錄的都是key值和指針(排除了data值),這樣就可以記錄更多的key值,其key值是升序排序,
B+tree和b-tree有如下不同點
1,非葉子節點只存儲鍵值信息(key信息)
2,所有葉子節點之間都有一個鏈指針,數據都存放再葉子節點中
推算
innodb存儲引擎一頁的大小為16kb,一般主鍵類型為int占4個字節,或bigint占8個字節,指針類型頁一般4個或8個字節,也就是說一個頁中大概存儲16*1024/16=1024個key,深度為3的B+tree索引(三頁)可以維護1024*1024*1024=10億條記錄,實際情況每個節點不可能填滿,B+tree的高度一般為2-4曾,mysql的innodb存儲引擎將根節點常駐內存,也就是查找某一鍵值的行記錄最多需要1-3次磁盤IO操作
頁的概念,
頁是innodb讀取磁盤的最小單位,整頁整頁的讀取
頁分為,數據頁(BTreeNode),Undo頁(undo Log page),系統頁(Systempage),事務數據頁(Transaction SystemPage)每個數數據頁的大小為16kb,每個page使用一個32位int值來表示,
一個page的基本結構
1,0-38:page頭部,id,類型信息等占38個字節,頭部保存兩個指針分別指向前一個page和后一個page,page是一個雙向列表
2,38-16376:不同的類型頁所含的數據不同,這部分空間包含系統記錄(SystemRecord)和用戶記錄(UserRecord),我們表中的一條條記錄就放在UserRecord部分,UserRecord存放的內容可以是以下內容
a,主鍵索引樹非葉子節點,B+tree索引,和指針
b,主鍵索引樹葉子節點,key和data(就是記錄本身)
c,輔助鍵索引樹非葉子節點,B+tree輔助索引
d,輔助鍵索引樹葉子節點,key和data(這里的data是主鍵)
頁可以裝很多種數據信息,有的頁是B+樹的所有主鍵索引,有的頁是B+樹的葉子節點也就是數據記錄本身,有的頁是我們創建的二級索引,
16376-16384:page尾部
頁和節點的關系
頁和節點沒有強相關關系
由頁組成的鏈表,頁之間是雙向列表,頁里面的數據是單向鏈表,這種結構組成了主鍵索引B+樹,組成了葉子節點數據。
定位一條記錄的過程,select * from table where id = 29
系統經過解析sql語句,首先讀取裝有非葉子節點page頁,遍歷非葉子節點,這個過程隨着節點的遍歷會將一個或多個page頁加載到內存,直到定位到這條記錄的葉子節點,然后遍歷找出該條記錄。
如果使用了二級索引則先讀取二級索引page遍歷這個二級索引,找到裝有主鍵信息葉子節點page頁,遍歷找到該主鍵。然后再根據主鍵索引尋找到該條記錄