mysql中,一條查詢sql的執行過程

2021-10-03 03:08:01 字數 1995 閱讀 6322

作為乙個程式設計師,最不能避免的就是與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)獲取對應的資料資訊返回。

MySQL中一條SQL語句的執行過程

查詢語句的執行順序 客戶端通過tcp連線傳送連線請求到mysql聯結器,聯結器會對該請求進行許可權驗證及連線資源分配 max connections,8小時超時 建立連線後客戶端傳送一條語句,mysql收到該語句後,通過命令分發器判斷其是否是一條select語句,如果是,在開啟查詢快取的情況下,先在...

MySql 一條查詢SQL語句的執行

這個的快取不是指redis,或者mybatis的快取我們常見的快取,其實mysql自帶了快取模組,但是我們幾乎從來沒有用過他,甚至在mysql8.0直接就給去掉了,所以一定有他的侷限性,大家可以查閱一下,但是確實是存在的。如果開啟的話,所以乙個查詢sql先會查詢快取 我們沒有使用快取的話,就會跳過快...

Oracle中一條sql引發的血案(一)

血案sql如下 create table yw wg 17 as select distinct acc from yw wc cust 1715 a where a.acc not in select distinct acc from yw wc cust 17 b where a.acc b....