上一篇咱們說到B+樹拼接一己之力殺出重圍,最後成爲了InnoDB和MyISAM這兩種存儲引擎的索引實現。咱們都知道索引內心是有B+樹的,他知道本身不可能所有存儲在內存中,他通常是以「索引文件的形式存儲的磁盤上」。那麼MySQL讀取數據時都發生了什麼呢?這得從內存開始提及。
IRAM與ROM
ROM,Read-OnlyMemory:只讀儲存器,能夠理解爲電腦的硬盤上存放操做系統的軟件,手機的內置儲存上存放操做系統的軟件,單片機的Flash上存放操做系統的軟件。總之就是用來存儲操做系統的軟件。
RAM,Random-AccessMemory:隨機儲存器,能夠理解爲電腦的內存條。用於存放動態數據,也叫運行內存。系統運行的時候,須要把操做系統從ROM中讀取出來,放在RAM中運行。程序員
CPU要運行程序須要從ROM調取,但ROM又有距離,因此須要用RAM來作一個鏈接。
I主存存儲原理
RAM主要的做用就是存儲代碼和數據供CPU在須要的時候調用,可是這些數據並非像用碗盛飯那麼簡單,咱們是須要知道數據的特定位置信息。他更像是圖書館中用有格子的書架存放書籍同樣,不但要放進去還要可以在須要的時候準確的調用出來,雖然都是書可是每本書是不一樣的。對於RAM等存儲器來講也是同樣的,雖然存儲的都是表明0和1的代碼,可是不一樣的組合就是不一樣的數據。
抽象地看,主存是一系列的存儲單元組成的矩陣,每一個存儲單元存儲固定大小的數據。每一個存儲單元有惟一的地址,現代主存的編址規則比較複雜,這裏將其簡化成一個二維地址:經過一個行地址和一個列地址能夠惟必定位到一個存儲單元。
I離主存讀寫工程
當系統須要讀取主存時,則將地址信號放到地址總線上傳給主存,主存讀到地址信號後,解析信號並定位到指定存儲單元,而後將此存儲單元數據放到數據總線上,供其它部件讀取。寫主存的過程相似,系統將要寫入單元地址和數據分別放在地址總線和數據總線上,主存讀取兩個總線的內容,作相應的寫操做。
因此,主存存取的時間僅與存取次數呈線性關係,由於不存在機械操做,兩次存取的數據的「距離」不會對時間有任何影響,例如,先取A0再取A3和先取B0再取C3的時間消耗是同樣的。
I磁盤的構成
若是咱們將硬盤拆開,能夠發現裏面存在多張磁盤和多個讀寫磁頭,加入一張磁盤有8張磁盤,就會有16個盤面和16個讀寫磁頭了,全部的盤面構成了磁盤組合。
磁盤組合由一個或多個圓盤組成,他們圍繞一根中心主軸旋轉,圓盤的上下表面塗抹了一層磁性材料,二進制位被存儲在這些磁性材料上。其中,0和1在磁材料中表現位不一樣的模式。
盤片被劃分紅一系列同心環,圓心是盤片中心,每一個同心環叫作一個「磁道」,全部半徑相同的磁道組成一個柱面。磁道被沿半徑線劃分紅一個個小的段,每一個段叫作一個「扇區」,每一個扇區是磁盤的最小存儲單元。爲了簡單起見,咱們下面假設磁盤只有一個盤片和一個磁頭。
I隨機讀取
通常來講,主存和磁盤以頁爲單位交換數據。在硬件及操做系統中,咱們每每將主存和磁盤存儲區分割爲連續的大小相等的塊。每一個存儲塊稱爲一頁(在許多操做系統中,頁的大小一般爲4k或者8k)。
I隨機讀取過程
在交換數據時,系統會將數據邏輯地址傳給磁盤,磁盤的控制電路按照尋址邏輯將邏輯地址翻譯成物理地址,即肯定要讀的數據在哪一個磁道,哪一個扇區。爲了讀取這個扇區的數據,須要將磁頭放到這個扇區上方。
I隨機讀取性能瓶頸
隨機讀取主要與性能瓶頸這三個指標有關:
1.磁頭須要移動對準相應磁道的時間即尋道時間
2.磁盤旋轉到指定磁道區域,即旋轉延遲
3.從磁盤讀出或將數據寫入磁盤的時間,即傳輸時間。
通常來講,主流磁盤尋道時間通常在5ms如下;旋轉延遲也就是轉速的通常(對於圓形來講,最多走一半就能到對應區域),對於7200轉的磁盤,旋轉延遲應該在7200/3600/2=4.17ms。傳輸時間能夠忽略不計,因此一次磁盤IO耗時應該在9ms之內。書筆記做文網https://www.yuananren.com其實9ms的隨機讀取其實已是一個災難,好比一臺常規的500-MIPS的機器每秒能夠執行5億條指令,也就是說一次隨機讀取的時間,機器能夠執行5百萬條指令,這個量級對比是驚人的。並且,對於一個百萬級數據庫查詢的話,所花費的時間已經達到了9s,這個數據對於用戶來講實際上是一個難以容忍的數字了。
I局部性原理
考慮到隨機讀取是高昂的消耗這個客觀存在的事實,咱們計算機系統利用了局部性原理對磁盤進行順序讀取。
平常生活中,咱們都知道不少東西的分佈都不是平均的,咱們更常見的機率分佈實際上是正態分佈。一個很形象的例子就是,大學中常常曠課的同窗,他的朋友也會常常曠課,他們造成了一個曠課圈。
磁盤每每不是嚴格按需讀取,而是每次都會預讀,即便只須要一個字節,磁盤也會從這個位置開始,順序向後讀取必定長度的數據放入內存。因此當一個數據被用到時,其附近的數據也一般會立刻被使用。程序運行期間所須要的數據一般比較集中。這就是咱們的局部性原理。
I順序讀取
磁盤順序讀取不須要尋道時間,只需不多的旋轉時間。因此,咱們對於具備局部性的程序來講,預讀能夠提升I/O效率。
I順序讀取過程
當程序要讀取的數據不在主存中時,會觸發一個缺頁異常,此時系統會向磁盤發出讀盤信號,磁盤會找到數據的起始位置並向後連續讀取一頁或幾頁載入內存中,而後異常返回,程序繼續運行。也就是咱們讀取一頁內的數據時候,實際上才發生了一次IO。
若是咱們須要將多個頁讀取到緩衝池中,並按順序處理它們,此時讀取的速度變的很快,此時讀取每一個頁所花費的時間大概爲0.1ms左右,這個時間消耗對隨機IO有很大的優點。
I順序讀取的條件
全表掃描
全索引掃描
索引片掃描
經過聚簇索引掃描錶行
I離順序讀取的優點
節省開銷。讀取多頁意味着平均讀取每頁性能增長。
預讀。因爲數據庫引擎知道須要讀取哪些頁,全部能夠在頁被真正請求以前就提早將其讀取進來。
IMySQL數據讀取
MySQL數據的讀取並非簡單直接將內存與磁盤進行數據交換,而是使用緩衝池最小化磁盤活動。
每個緩衝池都足夠大,大到能夠存放許多頁,多是成千上萬的頁。內存緩衝池和磁盤緩衝池遵循局部性原理,盡力確保常用的數據被保存於池中,以免一些沒必要要的磁盤讀。
根據主存存儲原理,咱們能夠很快在緩衝池找到一個索引或者表頁。若是在緩衝池中,沒有找到數據,會從磁盤服務器的緩衝區裏面去讀取。磁盤緩存池讀取成本大概會在1ms左右。若是磁盤服務器的緩衝池中依然沒有找到數據,此時就必需要從磁盤讀取了。若是知足順序讀取的條件,那麼就會盡快地順序讀取。若是不知足,那麼就會可怕的隨機讀取。
I總結
本文主要闡述了MySQL數據讀取的流程。認識到由於本身的小任性,須要查詢一個值,MySQL這個暖男竟然鞍前馬後幹了這麼多事情。甚至開始心疼軟件工程師,軟件工程師們想盡各類辦法來作優化,性能提高倒是有限的。而硬件上的稍微有優化,性能提高倒是飛躍的。好比順序讀取1MB數據,機械硬盤是20ms,SSD只須要1ms。更改硬盤達到速度的提高可能讓福報程序員能夠掉更少的頭髮,得到更多的休息。數據庫