一、sql語(yǔ)句執(zhí)行原理
第一步:客戶端把語(yǔ)句發(fā)給服務(wù)器端執(zhí)行
? ? ? ?在客戶端連接上服務(wù)器后,在客戶端與服務(wù)器端都會(huì)形成一個(gè)進(jìn)程,客戶端上的我們叫做客戶端進(jìn)程;而服務(wù)器上的我們叫做服務(wù)器進(jìn)程,二者之間的進(jìn)程是一一對(duì)應(yīng)的。
? ? ?當(dāng)我們?cè)诳蛻舳藞?zhí)行 select 語(yǔ)句時(shí),客戶端會(huì)把這條 SQL 語(yǔ)句發(fā)送給服務(wù)器端,讓服務(wù)器端的進(jìn)程來(lái)處理這語(yǔ)句。意思是,只有服務(wù)器上的數(shù)據(jù)庫(kù)進(jìn)程才會(huì)對(duì)SQL 語(yǔ)句進(jìn)行相關(guān)的處理。
第二步:語(yǔ)句解析
當(dāng)客戶端把 SQL 語(yǔ)句傳送到服務(wù)器后,服務(wù)器進(jìn)程會(huì)對(duì)該語(yǔ)句進(jìn)行解析。同理,這個(gè)解析的工作,也是在服務(wù)器端所進(jìn)行的。雖然這只是一個(gè)解析的動(dòng)作,但是,其會(huì)做很多“小動(dòng)作”。
1. 查詢高速緩存(library cache)。
? ? 服務(wù)器進(jìn)程在接到客戶端傳送過(guò)來(lái)的 SQL 語(yǔ)句時(shí),不會(huì)直接去數(shù)據(jù)庫(kù)查詢。而是會(huì)先在數(shù)據(jù)庫(kù)的高速緩存中去查找,是否存在相同語(yǔ)句的執(zhí)行計(jì)劃。如果在數(shù)據(jù)高速緩存中,則服務(wù)器進(jìn)程就會(huì)直接執(zhí)行這個(gè) SQL 語(yǔ)句,省去后續(xù)的工作。
2. 語(yǔ)句合法性檢查(data dict cache)。
? ? ?當(dāng)在高速緩存中找不到對(duì)應(yīng)的 SQL 語(yǔ)句時(shí),則服務(wù)器進(jìn)程就會(huì)開始檢查這條語(yǔ)句的合法性。這里主要是對(duì) SQL 語(yǔ)句的語(yǔ)法進(jìn)行檢查,看看其是否合乎語(yǔ)法規(guī)則。如果服務(wù)器進(jìn)程認(rèn)為這條 SQL 語(yǔ)句不符合語(yǔ)法規(guī)則的時(shí)候,就會(huì)把這個(gè)錯(cuò)誤信息,反饋給客戶端。在這個(gè)語(yǔ)法檢查的過(guò)程中,不會(huì)對(duì) SQL 語(yǔ)句中所包含的表名、列名等等進(jìn)行 SQL,它只是語(yǔ)法。
3. 語(yǔ)言含義檢查(data dict cache)。
? ? 若 SQL 語(yǔ)句符合語(yǔ)法上的定義的話,則服務(wù)器進(jìn)程接下去會(huì)對(duì)語(yǔ)句中的字段、表等內(nèi)容進(jìn)行檢查??纯催@些字段、表是否在數(shù)據(jù)庫(kù)中。如果表名與列名不準(zhǔn)確的話,則數(shù)據(jù)庫(kù)會(huì)就會(huì)反饋錯(cuò)誤信息給客戶端。所以,有時(shí)候我們寫 select 語(yǔ)句的時(shí)候,若語(yǔ)法與表名或者列名同時(shí)寫錯(cuò)的話,則系統(tǒng)是先提示說(shuō)語(yǔ)法錯(cuò)誤,等到語(yǔ)法完全正確后,再提示說(shuō)列名或表名錯(cuò)誤。
4. 獲得對(duì)象解析鎖(control structer)。
? ? 當(dāng)語(yǔ)法、語(yǔ)義都正確后,系統(tǒng)就會(huì)對(duì)我們需要查詢的對(duì)象加鎖。這主要是為了保障數(shù)據(jù)的一致性,防止我們?cè)诓樵兊倪^(guò)程中,其他用戶對(duì)這個(gè)對(duì)象的結(jié)構(gòu)發(fā)生改變。
5. 數(shù)據(jù)訪問(wèn)權(quán)限的核對(duì)(data dict cache)。
? ? 當(dāng)語(yǔ)法、語(yǔ)義通過(guò)檢查之后,客戶端還不一定能夠取得數(shù)據(jù)。服務(wù)器進(jìn)程還會(huì)檢查,你所連接的用戶是否有這個(gè)數(shù)據(jù)訪問(wèn)的權(quán)限。若你連接上服務(wù)器的用戶不具有數(shù)據(jù)訪問(wèn)權(quán)限的話,則客戶端就不能夠取得這些數(shù)據(jù)。
6. 確定最佳執(zhí)行計(jì)劃 。
? ? 當(dāng)語(yǔ)句與語(yǔ)法都沒(méi)有問(wèn)題,權(quán)限也匹配的話,服務(wù)器進(jìn)程還是不會(huì)直接對(duì)數(shù)據(jù)庫(kù)文件進(jìn)行查詢。服務(wù)器進(jìn)程會(huì)根據(jù)一定的規(guī)則,對(duì)這條語(yǔ)句進(jìn)行優(yōu)化。不過(guò)要注意,這個(gè)優(yōu)化是有限的。一般在應(yīng)用軟件開發(fā)的過(guò)程中,需要對(duì)數(shù)據(jù)庫(kù)的 sql 語(yǔ)言進(jìn)行優(yōu)化,這個(gè)優(yōu)化的作用要大大地大于服務(wù)器進(jìn)程的自我優(yōu)化。所以,一般在應(yīng)用軟件開發(fā)的時(shí)候,數(shù)據(jù)庫(kù)的優(yōu)化是少不了的。當(dāng)服務(wù)器進(jìn)程的優(yōu)化器確定這條查詢語(yǔ)句的最佳執(zhí)行計(jì)劃后,就會(huì)將這條 SQL 語(yǔ)句與執(zhí)行計(jì)劃保存到數(shù)據(jù)高速緩存(library cache)。如此的話,等以后還有這個(gè)查詢時(shí),就會(huì)省略以上的語(yǔ)法、語(yǔ)義與權(quán)限檢查的步驟,而直接執(zhí)行 SQL 語(yǔ)句,提高 SQL 語(yǔ)句處理效率。
第三步:語(yǔ)句執(zhí)行
? ? ?語(yǔ)句解析只是對(duì) SQL 語(yǔ)句的語(yǔ)法進(jìn)行解析,以確保服務(wù)器能夠知道這條語(yǔ)句到底表達(dá)的是什么意思。等到語(yǔ)句解析完成之后,數(shù)據(jù)庫(kù)服務(wù)器進(jìn)程才會(huì)真正的執(zhí)行這條 SQL 語(yǔ)句。這個(gè)語(yǔ)句執(zhí)行也分兩種情況:
(1)若被選擇行所在的數(shù)據(jù)塊已經(jīng)被讀取到數(shù)據(jù)緩沖區(qū)的話,則服務(wù)器進(jìn)程會(huì)直接把這個(gè)數(shù)據(jù)傳遞給客戶端,而不是從數(shù)據(jù)庫(kù)文件中去查詢數(shù)據(jù);
(2)若數(shù)據(jù)不在緩沖區(qū)中,則服務(wù)器進(jìn)程將從數(shù)據(jù)庫(kù)文件中查詢相關(guān)數(shù)據(jù),并把這些數(shù)據(jù)放入到數(shù)據(jù)緩沖區(qū)中(buffer cache)。
第四步:提取數(shù)據(jù)
? ? ?當(dāng)語(yǔ)句執(zhí)行完成之后,查詢到的數(shù)據(jù)還是在服務(wù)器進(jìn)程中,還沒(méi)有被傳送到客戶端的用戶進(jìn)程。所以,在服務(wù)器端的進(jìn)程中,有一個(gè)專門負(fù)責(zé)數(shù)據(jù)提取的一段代碼。他的作用就是把查詢到的數(shù)據(jù)結(jié)果返回給用戶端進(jìn)程,從而完成整個(gè)查詢動(dòng)作。
二、SQL語(yǔ)句中的函數(shù)、關(guān)鍵字、排序等執(zhí)行順序:
1. FROM 子句返回初始結(jié)果集。
2. WHERE 子句排除不滿足搜索條件的行。
3. GROUP BY 子句將選定的行收集到 GROUP BY 子句中各個(gè)唯一值的組中。
4. 選擇列表中指定的聚合函數(shù)可以計(jì)算各組的匯總值。
5. 此外,HAVING 子句排除不滿足搜索條件的行。
6. 計(jì)算所有的表達(dá)式;
7. 使用 order by 對(duì)結(jié)果集進(jìn)行排序。
8. 查找你要搜索的字段。
文章摘自:http://mp.weixin.qq.com/s?src=3×tamp=1515722713&ver=1&signature=uzprhqOCP8FICSzR1P3IMah4WgSjZSi0*EAZBWbHAYS5EFwkxgEDNQp1p4s5qD6ssS2mvaRwzp*3hUb6A0STmQ*R5ygvvq*ae9TQ9UCfiXhmFdFlJSEOHtpnA0VpYcIiIzlH3ecnCcLM8RyalVEASnX5LJZc*dqXox9vD-xx9a4=