mysql中,一條sql是怎麼執行原理

作爲一個程序員,最不能避免的就是與sql打交道,那麼,在我們平時寫的那麼多sql它們是怎麼執行,並給我們返回數據的?

比如最簡單的一個查詢:

select * from user where id=10;

sql簡單,但問題是你知道它是如何執行的嗎?

先從整體看一下mysql數據庫的執行構造:

1)server層:

所有跨存儲引擎的功能都在這一層,比如:存儲過程、觸發器、視圖等。

2)存儲引擎層

其架構模式是插件的形式,比如,innodb。

以上可以認爲是從宏觀上,查看了mysql各個部分的流程執行順序。

那麼從微觀上看的話,一條查詢語句它是怎麼獲取到數據的呢?

知識儲備:

一、數據頁

在操作系統的概念中,我們從磁盤讀取數據時,操作系統每次會讀取4KB的數據。也就是說,即使你讀取1KB的數據,操作系統也會返回4Kb的數據,先稱其爲頁。其目的就是爲了減少IO的交互。爲什麼它能做到這一點?

舉例說明一下:

假如我們磁盤中有10條數據,並且每一條數據都是1KB,並且每一條都有一個唯一的遞增的id,假如現在,我要讀取id=3的這一條數據,來看一下有什麼不同。

1)不使用頁

我們從id=1的開始讀取,當我們讀取到想要的數據時,我們需要讀取3次,進行了3次磁盤IO。

2)使用頁

我們從id=1開始讀取,然後讀取一次,不符合,但是系統使用了頁,返回了四條數據,其中就包含了id=3的這條數據。這就只進行了一次磁盤io,效率是不是提高了。

那麼接下來,回到mysql中。innodb中也有這個頁的概念,但是它的默認大小是16KB。其作用是一樣的,減少訪問磁盤的次數。

先看一下數據頁的結構,這只是簡化了的結構,其內部結構比這要複雜。只用於幫助理解。

數據在一頁中是以單鏈表的形式存儲的。而其中的slot,佔兩個字節,記錄着相對頁初始位置的偏移量。每一個slot可以 包含4到8條數據,有它輔助,可以實現二分查找,找到對應的數據頁後進行遍歷讀取數據。

擴展:

innodb引擎的邏輯存儲結構從小到大可以分爲:

行、頁、區、段、表空間。

其中區固定爲1M的大小。

二、Buffer  Pool

bufferPool使用來做什麼的?

由上面我們知道,數據庫讀取的時候都會讀取整個頁到內存,那麼內存如何存儲這些頁,存放到那裏面?

這就要使用buffer pool了。那麼它做了什麼?

當mysql啓動時,BufferPool中就會被初始化爲上圖結構。

其中雙向鏈表爲free鏈表,記錄着空閒的數據頁,如果此時開始的sql語句開始訪問,那麼就會去磁盤加載數據頁到內存,將緩存頁填充,然後將其對應的free鏈表的位置刪除。

那如何知道查詢的數據頁在不在BufferPool中呢?

它其中還維護了一張hash表數據空額後,用“表空間號+數據頁號”作爲key,緩存頁的地址作爲value,這樣查詢一下就知道在緩存中存不存在這個數據頁了。

三、索引

innodb所以使用的是B+樹。

上圖是一個主鍵索引數。

有了以上的數據儲備,我們來看看開始的時候,一條查詢語句是如何獲取數據的。

1)通過索引,查詢到對應的數據。

2)遍歷雙向鏈表(頁是一個雙向鏈表),找到數據所對應的頁。

3)將數據對應的頁加載到BufferPool中。

4)獲取對應的數據信息返回。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章