最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網 會員登陸 & 注冊

02 為了執(zhí)行SQL語句,你知道MySQL用了什么樣的架構設計嗎?

2023-06-09 10:40 作者:儒猿課堂  | 我要投稿

為了執(zhí)行SQL語句,你知道MySQL用了什么樣的架構設計嗎?


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


上一講我們已經說到,我們的系統(tǒng)采用數據庫連接池的方式去并發(fā)訪問數據庫,然后數據庫自己其實也會維護一個連接池,其中管理了各種系統(tǒng)跟這臺數據庫服務器建立的所有連接


我們先看下圖回顧一下

? ? ? ? ? ?

? ? ? ? ? ? ?

當我們的系統(tǒng)只要能從數據庫連接池獲取到一個數據庫連接之后,我們就可以執(zhí)行增刪改查的SQL語句了


從上圖其實我們就可以看到,我們可以通過數據庫連接把要執(zhí)行的SQL語句發(fā)送給MySQL數據庫。


然后呢?大部分同學了解到這個程度就停下來了,然后大家覺得要關注的可能主要就是數據庫里的表結構,建了哪些索引,然后就按照SQL語法去編寫增刪改查SQL語句,把MySQL當個黑盒子去執(zhí)行SQL語句就可以了。


我們只知道執(zhí)行了insert語句之后,在表里會多出來一條數據;執(zhí)行了update語句之后,會對表里的數據進行更改;執(zhí)行了delete語句之后,會把表里的一條數據刪除掉;執(zhí)行了select語句之后,會從表里查詢一些數據出來。


如果語句性能有點差?沒關系,在表里建幾個索引就可以了!可能這就是目前行業(yè)內很多工程師對數據庫的一個認知,完全當他是個黑盒子,來建表以及執(zhí)行SQL語句。


但是大家既然跟著我開始學習了,從現在開始就要打破這種把數據庫當黑盒子的認知程度,要深入底層,去探索數據庫的工作原理以及生產問題的優(yōu)化手段!


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


現在假設我們的數據庫服務器的連接池中的某個連接接收到了網絡請求,假設就是一條SQL語句,那么大家先思考一個問題,誰負責從這個連接中去監(jiān)聽網絡請求?誰負責從網絡連接里把請求數據讀取出來?


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

? ? ? ? ? ?

? ? ? ? ? ? ?

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


接著我們來思考一下,當MySQL內部的工作線程從一個網絡連接中讀取出來一個SQL語句之后,此時會如何來執(zhí)行這個SQL語句呢?


其實SQL是一項偉大的發(fā)明,他發(fā)明了簡單易用的數據讀寫的語法和模型,哪怕是個產品經理,或者是運營專員,甚至是銷售專員,即使他不會技術,他也能輕松學會使用SQL語句。


但如果你要去執(zhí)行這個SQL語句,去完成底層數據的增刪改查,那這就是一項極度復雜的任務了!


所以MySQL內部首先提供了一個組件,就是SQL接口(SQL Interface),他是一套執(zhí)行SQL語句的接口,專門用于執(zhí)行我們發(fā)送給MySQL的那些增刪改查的SQL語句


因此MySQL的工作線程接收到SQL語句之后,就會轉交給SQL接口去執(zhí)行,如下圖。

? ? ? ? ? ?

? ? ? ? ? ? ?

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


接著下一個問題來了,SQL接口怎么執(zhí)行SQL語句呢?你直接把SQL語句交給MySQL,他能看懂和理解這些SQL語句嗎?


比如我們來舉一個例子,現在我們有這么一個SQL語句:

select id,name,age from users where id=1


這個SQL語句,我們用人腦是直接就可以處理一下,只要懂SQL語法的人,立馬大家就知道他是什么意思,但是MySQL自己本身也是一個系統(tǒng),是一個數據庫管理系統(tǒng),他沒法直接理解這些SQL語句!


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


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

  1. 我們現在要從“users”表里查詢數據

  2. 查詢“id”字段的值等于1的那行數據

  3. 對查出來的那行數據要提取里面的“id,name,age”三個字段。


所謂的SQL解析,就是按照既定的SQL語法,對我們按照SQL語法規(guī)則編寫的SQL語句進行解析,然后理解這個SQL語句要干什么事情,如下圖所示:

? ? ? ? ? ?

? ? ? ? ? ? ?

5、查詢優(yōu)化器:選擇最優(yōu)的查詢路徑


當我們通過解析器理解了SQL語句要干什么之后,接著會找查詢優(yōu)化器(Optimizer)來選擇一個最優(yōu)的查詢路徑。


可能有同學這里就不太理解什么是最優(yōu)的查詢路徑了,這個看起來確實很抽象,當然,這個查詢優(yōu)化器的工作原理,后續(xù)將會是我們分析的重點,大家現在不用去糾結他的原理。


但是我們可以用一個極為通俗簡單的例子,讓大家理解一下所謂的最優(yōu)查詢路徑是什么。


就用我們剛才講的那個例子好了,我們現在理解了一個SQL想要干這么一個事兒:我們現在要從“users”表里查詢數據,查詢“id”字段的值等于1的那行數據,對查出來的那行數據要提取里面的“id,name,age”三個字段。


事是明白了,但是到底應該怎么來實現呢?


你看,要完成這個事兒我們有以下幾個查詢路徑(純屬用于大家理解的例子,不代表真實的MySQL原理,但是通過這個例子,大家肯定能理解所謂最優(yōu)查詢路徑的意思):


  1. 直接定位到“users”表中的“id”字段等于1的一行數據,然后查出來那行數據的“id,name,age”三個字段的值就可以了

  2. 先把“users”表中的每一行數據的“id,name,age”三個字段的值都查出來,然后從這批數據里過濾出來“id”字段等于1的那行數據的“id,name,age”三個字段


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


所以查詢優(yōu)化器大概就是干這個的,他會針對你編寫的幾十行、幾百行甚至上千行的復雜SQL語句生成查詢路徑樹,然后從里面選擇一條最優(yōu)的查詢路徑出來。


相當于他會告訴你,你應該按照一個什么樣的步驟和順序,去執(zhí)行哪些操作,然后一步一步的把SQL語句就給完成了。


我們來一起看看下面的圖:? ? ? ? ? ?

? ? ? ? ? ? ?

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


最后一步,就是把查詢優(yōu)化器選擇的最優(yōu)查詢路徑,也就是你到底應該按照一個什么樣的順序和步驟去執(zhí)行這個SQL語句的計劃,把這個計劃交給底層的存儲引擎去真正的執(zhí)行。這個存儲引擎是MySQL的架構設計中很有特色的一個環(huán)節(jié)。


不知道大家是否思考過,真正在執(zhí)行SQL語句的時候,要不然是更新數據,要不然是查詢數據,那么數據你覺得存放在哪里?


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


數據庫自己就是一個編程語言寫出來的系統(tǒng)而已,然后啟動之后也是一個進程,執(zhí)行他里面的各種代碼,也就是我們上面所說的那些東西。所以對數據庫而言,我們的數據要不然是放在內存里,要不然是放在磁盤文件里,沒什么特殊的地方!


所以我們來思考一下,假設我們的數據有的存放在內存里,有的存放在磁盤文件里,如下圖所示。

? ? ? ? ? ?

? ? ? ? ? ? ?

那么現在問題來了,我們已經知道一個SQL語句要如何執(zhí)行了,但是我們現在怎么知道哪些數據在內存里?哪些數據在磁盤里?我們執(zhí)行的時候是更新內存的數據?還是更新磁盤的數據?我們如果更新磁盤的數據,是先查詢哪個磁盤文件,再更新哪個磁盤文件?


是不是感覺一頭霧水


所以這個時候就需要存儲引擎了,存儲引擎其實就是執(zhí)行SQL語句的,他會按照一定的步驟去查詢內存緩存數據,更新磁盤數據,查詢磁盤數據,等等,執(zhí)行諸如此類的一系列的操作,如下圖所示。

? ? ? ? ? ?

? ? ? ? ? ? ?

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


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


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


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


那么看完存儲引擎之后,我們回過頭來思考一個問題,存儲引擎可以幫助我們去訪問內存以及磁盤上的數據,那么是誰來調用存儲引擎的接口呢?


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


舉個例子,比如執(zhí)行器可能會先調用存儲引擎的一個接口,去獲取“users”表中的第一行數據,然后判斷一下這個數據的“id”字段的值是否等于我們期望的一個值,如果不是的話,那就繼續(xù)調用存儲引擎的接口,去獲取“users”表的下一行數據。


就是基于上述的思路,執(zhí)行器就會去根據我們的優(yōu)化器生成的一套執(zhí)行計劃,然后不停的調用存儲引擎的各種接口去完成SQL語句的執(zhí)行計劃,大致就是不停的更新或者提取一些數據出來


我們看下圖的示意

? ? ? ? ? ?

? ? ? ? ? ? ?

8、小思考題:打開腦洞,你覺得不同的存儲引擎是用來干什么的?


今天給大家留一個小的思考題,就是你先別管MySQL有哪些存儲引擎,你就從業(yè)務場景來出發(fā)考慮,有的場景可能是高并發(fā)的更新,有的場景可能是大規(guī)模數據查詢,有的場景可能是允許丟失數據的


那么你覺得如果讓你來設計存儲引擎,你覺得應該有哪些存儲引擎,分別適用于什么場景?


希望大家在評論區(qū)留言,踴躍的思考和回復。


End

專欄版權歸公眾號儒猿技術窩所有

未經許可不得傳播,如有侵權將追究法律責任

02 為了執(zhí)行SQL語句,你知道MySQL用了什么樣的架構設計嗎?的評論 (共 條)

分享到微博請遵守國家法律
虎林市| 金川县| 上杭县| 五常市| 临高县| 微博| 克东县| 个旧市| 顺义区| 新沂市| 郸城县| 思南县| 甘泉县| 灯塔市| 巨野县| 大足县| 尼玛县| 潢川县| 阳新县| 重庆市| 广安市| 壤塘县| 广河县| 甘谷县| 峨眉山市| 高阳县| 隆德县| 尼木县| 商丘市| 缙云县| 吉林市| 六盘水市| 广汉市| 宜阳县| 翼城县| 镇宁| 邛崃市| 昆山市| 夏河县| 诸城市| 延庆县|