天天看點

帶你一起分析mySQL執行sql原理,領略Oracle公司架構師的核心思想

帶你一起分析mySQL執行sql原理,領略Oracle公司架構師的核心思想

1、把MySQL當個黑盒子一樣執行SQL語句

我們知道執行了insert語句之後,在表裡會多出來一條資料;執行了update語句之後,會對表裡的資料進行更改;執行了delete語句之後,會把表裡的一條資料删除掉;執行了select語句之後,會從表裡查詢一些資料出來。

如果語句性能有點差?沒關系,在表裡建幾個索引就可以了!可能這就是目前行業内很多工程師對資料庫的一個認知,完全當他是一個黑盒子,來建表以及執行SQL語句。

既然開始學習如何優化,就要打破這種把資料庫當黑盒子的認知程度,要深入底層,去探索資料庫的工作原理以及生産問題的優化手段!

2、一個不變的原則:網絡連接配接必須讓線程來處理

現在假設我們的資料庫伺服器的連接配接池中的某個連接配接接收到了網絡請求,假設就是一條SQL語句,那麼大家先思考一個問題,誰負責從這個連接配接中去監聽網絡請求?誰負責從網絡連接配接裡把請求資料讀取出來?

我想很多人恐怕都沒思考過這個問題,但是如果大家對計算機基礎知識有一個簡單了解的話,應該或多或少知道一點,那就是網絡連接配接必須得配置設定給一個線程去進行處理,由一個線程來監聽請求以及讀取請求資料,比如從網絡連接配接中讀取和解析出來一條我們的系統發送過去的SQL語句,如下圖:

帶你一起分析mySQL執行sql原理,領略Oracle公司架構師的核心思想

3、SQL接口:負責處理接收到的SQL語句

接着我們來思考一下,當MySQL内部的工作線程從一個網絡連接配接中讀取出來一個SQL語句之後,此時會如何來執行這個SQL語句呢?

其實SQL是一項偉大的發明,他發明了簡單易用的資料讀寫的文法和模型,哪怕是産品經理,或者是營運專員,甚至是銷售專員,及時他們不會技術,也能輕松學會使用SQL語句。

但如果你要去執行這個SQL語句,去完成底層資料的增删改查,那這就是一項極度複雜的任務了!

是以MySQL内部首先提供了一個元件,就是SQL接口(SQL Interface),他是一套執行SQL語句的接口,專門用于執行我們發送給MySQL的那些增删改查的SQL語句。

是以MySQL的工作線程接收到SQL語句之後,就會轉交給SQL接口去執行,如下圖:

帶你一起分析mySQL執行sql原理,領略Oracle公司架構師的核心思想

4、查詢解析器:讓MySQL能看懂SQL語句

接着下一個問題來了,SQL接口怎麼執行SQL語句呢?你直接把SQL語句交給MySQL,他能看懂和了解這些SQL語句嗎?

我們來舉個例子,現在有一個這樣的SQL語句:

這個SQL語句,我們用人腦是直接就可以處理一下,隻要懂SQL文法的人,立馬就知道他是什麼意思,但是MySQL自己本身也是一個系統,是一個資料庫管理系統,他沒法直接了解這些SQL語句!

是以此時就有一個關鍵的元件要出場了,那就是查詢解析器

這個查詢解析器(Parser)就是負責對SQL語句進行解析的,比如對上面那個SQL語句進行一下拆解,拆解成一下幾個部分:

1我們現在要從users表中查詢資料

2查詢id字段的值等于1的那行資料

3對查出來的那行資料要提取裡面的id,name,age三個字段

所謂的SQL解析,就是按照既定的SQL文法,對我們按照SQL文法規則編寫的SQL語句進行解析,然後了解這個SQL語句要幹什麼事情,如下圖:

帶你一起分析mySQL執行sql原理,領略Oracle公司架構師的核心思想

5、查詢優化器:選擇最優的查詢路徑

當我們通過解析器了解了SQL語句要幹什麼之後,接着會找查詢優化器(Optimizer)來選擇一個最優的查詢路徑。

可能有的同學這裡就不太了解什麼是最優的查詢路徑了,這個看起來有點抽象,當然,這個查詢優化器的工作原理,後續我們會重點分析下,大家現在不用去糾結他的原理。

就用我們剛才說的這個例子,我們現在了解了一個SQL要幹這麼一個事情:我們現在要從“users”表裡查詢資料,查詢“id”字段的值等于1的那行資料,對查出來的那行資料要提取裡面的“id, name, age” 三個字段。

事情是明白了,但是到底應該怎麼來實作呢?

要完成這件事情我們有以下這幾個查詢路徑(純屬用于了解例子,不代表真實MySQL原理,但是通過這個例子,大家應該能了解最優查詢路徑的意思):

思路1.直接定位到“users”表中的“id” 字段等于1的一行資料,然後查出來那行資料的“id, name, age”三個字段的值就可以了 思路2.先把"users"表中的每一行資料的“id, name, age”三個字段的值都查出來,然後從這批資料裡面過濾出來“id”字段等于1的那行資料的“id, name, age”三個字段

上面這就是一個最簡單的SQL語句的兩種實作路徑,其實我們會發現,要完成這個SQL語句的目标,兩個路徑都可以做到,但是哪一種最好呢?顯然感覺上是第一種查詢路徑更好一些。

是以查詢優化器大概就是幹這個的,他會針對你編寫的幾十行、幾百行甚至上千行複雜的SQL語句生成查詢路徑樹,然後從裡面選擇一條最優的查詢路徑出來。

相當于他會告訴你,你應該按照一個什麼樣的步驟和順序,去執行哪些操作,然後一步一步的把SQL語句就給完成了。如下圖:

帶你一起分析mySQL執行sql原理,領略Oracle公司架構師的核心思想

6、調用存儲引擎接口,真正執行SQL語句

最後一步,就是把查詢優化器選擇的最優查詢路徑,也就是到底應該按照一個什麼樣的順序和步驟去執行這個SQL語句的計劃,把這個計劃交給底層的存儲引擎去真正的執行。這個存儲引擎是MySQL的架構設計中很有特色的一個環節。

不知道大家是否思考過,真正在執行SQL語句的時候,要不然是更新資料,要不然是查詢資料,那麼資料你覺得存放在哪裡?

說白了,資料庫也不是什麼神秘莫測的東西,可以把他了解為本身就是一個類似平時寫的圖書館管理系統、電信計費系統、電商訂單系統之類的系統罷了。

資料庫自己就是一個程式設計語言寫出來的系統而已,然後啟動之後也是一個程序,執行他裡面的各種代碼,也就是我們上面所說的那些東西。是以對資料庫而言,我們的資料要不然是放在記憶體裡,要不然是放在磁盤檔案裡,沒什麼特殊的地方!

是以我們來思考一下,假設我們的資料有的存放在記憶體裡,有的存放在磁盤檔案裡,如下圖所示:

帶你一起分析mySQL執行sql原理,領略Oracle公司架構師的核心思想

那麼現在問題來了,我們已經知道一個SQL語句要如何執行了,但是我們現在怎麼知道哪些資料在記憶體裡?哪些資料在磁盤裡?我們執行的時候是更新記憶體的資料?還是更新磁盤的資料,是先查詢哪個磁盤檔案,再更新哪個磁盤檔案?

是不是感覺一頭霧水

是以這個時候就需要存儲引擎了,存儲引擎其實就是執行SQL語句的,他會按照一定的步驟去查詢記憶體緩存資料,更新磁盤資料,查詢磁盤資料,等等,執行諸如此類的一系列的操作,如下圖所示:

帶你一起分析mySQL執行sql原理,領略Oracle公司架構師的核心思想

MySQL的架構設計中,SQL接口、SQL解析器、查詢優化器其實都是通用的,他就是一套元件而已。

但是儲存引擎的話,他是支援各種各樣的存儲引擎的,比如我們常見的InnoDB、MyISAM、Memory等等,我們是可以選擇使用哪種存儲引擎來負責具體的SQL語句執行的。

當然現在MySQL一般都是使用InnoDB儲存引擎的,至于存儲引擎的原理,後續我們也會深入一步一步分析,大家不必着急。

7、執行器:根據執行計劃調用儲存引擎的接口

那麼看完存儲引擎之後,我們回過頭來思考一個問題,存儲引擎可以幫助我們去通路記憶體以及磁盤上的資料,那麼是誰來調用儲存引擎的接口呢?

其實我們現在還漏了一個執行器的概念,這個執行器會根據優化器選擇的執行方案,去調用存儲引擎的接口按照一定的順序和步驟,就把SQL語句的邏輯給執行了。

舉個例子,比如執行器可能會先調用存儲引擎的一個接口,去擷取“users”表中的第一行資料,然後判斷一下這個資料的"id"字段的值是否等于我們期望的一個值,如果不是的話,那就繼續調用存儲引擎的接口,去擷取“users”表的下一行資料。

就是基于上述的思路,執行器就會去根據我們的優化器生成的一套執行計劃,然後不停的調動存儲引擎的各種接口去完成SQL語句的執行計劃,大緻就是不停的更新或者提取一些資料出來,如下圖所示: