日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

怎么将sql语句转化成语法树_数据库如何解析执行SQL

發(fā)布時間:2024/9/27 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 怎么将sql语句转化成语法树_数据库如何解析执行SQL 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

閱讀文本大概需要3分鐘。

0x01:數(shù)據(jù)庫客戶端發(fā)送查詢SQL

? ? ? 客戶端將查詢的select sql,按照mysql通信協(xié)議傳輸?shù)綌?shù)據(jù)庫服務(wù)。數(shù)據(jù)庫服務(wù)接受查詢sql,執(zhí)行sql前判斷要執(zhí)行的sql是否是查詢語句。

0x02:查詢緩存先行MySQL在開啟查詢緩存的情況下,首先會先在查詢緩存中查找該SQL是否完全匹配,如果完全匹配,驗證當(dāng)前用戶是否具備查詢權(quán)限,如果權(quán)限驗證通過,直接返回結(jié)果集給客戶端,該查詢也就完成了。如果不匹配繼續(xù)向下執(zhí)行。

緩存配置參數(shù):

  • query_cache_limit:?MySQL能夠緩存的最大結(jié)果,如果超出,則增加 Qcache_not_cached的值,并刪除查詢結(jié)果

  • query_cache_min_res_unit: 分配內(nèi)存塊時的最小單位大小

  • query_cache_size:?緩存使用的總內(nèi)存空間大小,單位是字節(jié),這個值必須是1024的整數(shù)倍,否則MySQL實際分配可能跟這個數(shù)值不同(感覺這個應(yīng)該跟文件系統(tǒng)的blcok大小有關(guān))

  • query_cache_type:?是否打開緩存?OFF?關(guān)閉 ;ON?總是打開

  • query_cache_wlock_invalidate: 如果某個數(shù)據(jù)表被鎖住,是否仍然從緩存中返回數(shù)據(jù),默認(rèn)是OFF,表示仍然可以返回

0x03:語法分析器和查詢預(yù)處理器如果在查詢緩存中未匹配成功,則將語句交給分析器作語法分析。MySQL通過關(guān)鍵字將SQL語句進(jìn)行解析,并生成一棵對應(yīng)的“解析樹”。MySQL解析器將使用MySQL語法規(guī)則驗證和解析查詢,通過分析語法知道要查的內(nèi)容。這個步驟會對語法進(jìn)行檢驗,如果語法不對就會返回語法錯誤中斷查詢。否則,下一步預(yù)處理器會驗證權(quán)限。0x04:查詢優(yōu)化器

? ? ? 語法樹被認(rèn)為合法之后,由優(yōu)化器將其轉(zhuǎn)化為執(zhí)行計劃。一條查詢可以有很多種執(zhí)行方式,最后都返回相同的結(jié)果。優(yōu)化器的作用就是找到這其中最好的執(zhí)行計劃。

? ? ? MySQL使用基于成本的優(yōu)化器,它將嘗試預(yù)測一個查詢使用某種執(zhí)行計劃的成本,并選擇其中成本最小的一個。最初,成本的最小單位是隨機讀取一個4K數(shù)據(jù)頁的成本,后來成本計算公式變得更加復(fù)雜,并且引入了一些“因子”來估算某些操作的代價,如當(dāng)執(zhí)行一次where條件比較的成本??梢酝ㄟ^查詢當(dāng)前會話的last_query_cost的值來得知MySQL計算的當(dāng)前查詢的成本。

有很多種原因會導(dǎo)致MySQL優(yōu)化器選擇錯誤的執(zhí)行計劃,比如:

1. 統(tǒng)計信息不準(zhǔn)確。

2. 執(zhí)行計劃中的成本估算不等同于實際的執(zhí)行計劃的成本。

3. MySQL的最優(yōu)可能與你想的最優(yōu)不一樣。

4. MySQL從不考慮其他并發(fā)的查詢,這可能會影響當(dāng)前查詢的速度。

5. MySQL也不是任何時候都是基于成本的優(yōu)化,有時候也會基于一些固定的規(guī)則。

6. MySQL不會考慮不受其控制的成本,例如執(zhí)行存儲過程或者用戶自定義的函數(shù)的成本。

? ? ? MySQL的查詢優(yōu)化使用了很多優(yōu)化策略來生成一個最優(yōu)的執(zhí)行的計劃。優(yōu)化策略可以分為兩種,靜態(tài)優(yōu)化和動態(tài)優(yōu)化。靜態(tài)優(yōu)化可以直接對解析樹進(jìn)行分析,并完成優(yōu)化。例如優(yōu)化器可以通過一些簡單的代數(shù)變換將where條件轉(zhuǎn)換成另一種等價形式。靜態(tài)優(yōu)化不依賴于特別的數(shù)值,如where條件中帶入的一些常數(shù)等。靜態(tài)優(yōu)化在第一次完成后就一直有效,即使使用不同的參數(shù)重復(fù)查詢也不會變化,可以認(rèn)為是一種“編譯時優(yōu)化”。

? ? ? 相反,動態(tài)優(yōu)化則和查詢的上下文有關(guān)。也可能和很多其他因素有關(guān),例如where條件中的取值、索引中條目對應(yīng)的數(shù)據(jù)行數(shù)等,這些需要每次查詢的時候重新評估,可以認(rèn)為是“運行時優(yōu)化”。

下面是一些MySQL能夠處理的優(yōu)化類型:

1. 重新定義關(guān)聯(lián)表的順序

? ? ? 數(shù)據(jù)表的關(guān)聯(lián)并不總是按照在查詢中指定的順序進(jìn)行,決定關(guān)聯(lián)的順序是優(yōu)化器很重要的一部分功能。

2. 將外連接轉(zhuǎn)化成內(nèi)連接

? ? ? ?并不是所有的outer join語句都必須以外連接的方式執(zhí)行。諸多因素,例如where條件、庫表結(jié)構(gòu)都可能會讓外連接等價于一個內(nèi)連接。MySQL能夠識別這點并重寫查詢,讓其可以調(diào)整關(guān)聯(lián)順序。

3. 使用等價變換規(guī)則

? ? ? ?MySQL可以使用一些等價變換來簡化并規(guī)范表達(dá)式。它可以合并和減少一些比較,還可以移除一些恒成立和一些恒不成立的判斷。例如:(5=5 and a>5)將被改寫為a>5。類似的,如果有(a5 and b=c and a=5。

4. 優(yōu)化count()、min()和max()

? ? ? 索引和列是否為空通??梢詭椭鶰ySQL優(yōu)化這類表達(dá)式。例如,要找到一列的最小值,只需要查詢對應(yīng)B-tree索引最左端的記錄,MySQL可以直接獲取索引的第一行記錄。在優(yōu)化器生成執(zhí)行計劃的時候就可以利用這一點,在B-tree索引中,優(yōu)化器會講這個表達(dá)式最為一個常數(shù)對待。類似的,如果要查找一個最大值,也只需要讀取B-tree索引的最后一個記錄。如果MySQL使用了這種類型的優(yōu)化,那么在explain中就可以看到“select tables optimized away”。從字面意思可以看出,它表示優(yōu)化器已經(jīng)從執(zhí)行計劃中移除了該表,并以一個常數(shù)取而代之。

? ? ? ?類似的,沒有任何where條件的count(*)查詢通常也可以使用存儲引擎提供的一些優(yōu)化,例如,MyISAM維護(hù)了一個變量來存放數(shù)據(jù)表的行數(shù)。

5. 預(yù)估并轉(zhuǎn)化為常數(shù)表達(dá)式

6. 覆蓋索引掃描

? ? ? ?當(dāng)索引中的列包含所有查詢中需要使用的列的時候,MySQL就可以使用索引返回需要的數(shù)據(jù),而無需查詢對應(yīng)的數(shù)據(jù)行。

7. 子查詢優(yōu)化

? ? ? MySQL在某些情況下可以將子查詢轉(zhuǎn)換成一種效率更高的形式,從而減少多個查詢多次對數(shù)據(jù)進(jìn)行訪問。

8. 提前終止查詢

? ? ? 在發(fā)現(xiàn)已經(jīng)滿足查詢需求的時候,MySQL總是能夠立即終止查詢。一個典型的例子就是當(dāng)使用了limit子句的時候。除此之外,MySQL還有幾種情況也會提前終止查詢,例如發(fā)現(xiàn)了一個不成立的條件,這時MySQL可以立即返回一個空結(jié)果。

上面的例子可以看出,查詢在優(yōu)化階段就已經(jīng)終止。

9. 等值傳播

10. 列表in()的比較

? ? ? 在很多數(shù)據(jù)庫系統(tǒng)中,in()完全等同于多個or條件的字句,因為這兩者是完全等價的。在MySQL中這點是不成立的,MySQL將in()列表中的數(shù)據(jù)先進(jìn)行排序,然后通過二分查找的方式來確定列表中的值是否滿足條件,這是一個o(log n)復(fù)雜度的操作,等價轉(zhuǎn)換成or的查詢的復(fù)雜度為o(n),對于in()列表中有大量取值的時候,MySQL的處理速度會更快。

0x05:查詢執(zhí)行器

? ? ? ?在解析和優(yōu)化階段,MySQL將生成查詢對應(yīng)的執(zhí)行計劃,MySQL的查詢執(zhí)行引擎則根據(jù)這個執(zhí)行計劃來完成整個查詢。這里執(zhí)行計劃是一個數(shù)據(jù)結(jié)構(gòu),而不是和很多其他的關(guān)系型數(shù)據(jù)庫那樣會生成對應(yīng)的字節(jié)碼。

? ? ? ?相對于查詢優(yōu)化階段,查詢執(zhí)行階段不是那么復(fù)雜:MySQL只是簡單的根據(jù)執(zhí)行計劃給出的指令逐步執(zhí)行。在根據(jù)執(zhí)行計劃逐步執(zhí)行的過程中,有大量的操作需要通過調(diào)用存儲引擎實現(xiàn)的接口來完成,這些接口就是我們稱為“handler API”的接口。實際上,MySQL在優(yōu)化階段就為每個表創(chuàng)建了一個handler實例,優(yōu)化器根據(jù)這些實例的接口可以獲取表的相關(guān)信息,包括表的所有列名、索引統(tǒng)計信息等。

? ? ?最后,交給執(zhí)行器去具體執(zhí)行該查詢語句。執(zhí)行器開始執(zhí)行后,會逐漸將數(shù)據(jù)保存到結(jié)果集中,同時會逐步將數(shù)據(jù)緩存到查詢緩存中,最終將結(jié)果集返回給客戶端。

往期精彩

01?漫談發(fā)版哪些事,好課程推薦

02?Linux的常用最危險的命令

03?精講Spring Boot—入門+進(jìn)階+實例

04?優(yōu)秀的Java程序員必須了解的GC哪些

05?互聯(lián)網(wǎng)支付系統(tǒng)整體架構(gòu)詳解

關(guān)注我

每天進(jìn)步一點點

喜歡!在看?

總結(jié)

以上是生活随笔為你收集整理的怎么将sql语句转化成语法树_数据库如何解析执行SQL的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。