SQL必知必會(SQL 是如何執(zhí)行的)

一、Oracle 中的 SQL 是如何執(zhí)行的

SQL 在 Oracle 中的執(zhí)行過程


從上面這張圖中可以看出,SQL 語句在 Oracle 中經(jīng)歷了以下的幾個步驟

1、語法檢查:檢查 SQL 拼寫是否正確,如果不正確,Oracle 會報語法錯誤。

2、語義檢查:檢查 SQL 中的訪問對象是否存在。比如我們在寫 SELECT 語句的時候,列名寫錯了,系統(tǒng)就會提示錯誤。語法檢查和語義檢查的作用是保證 SQL 語句沒有錯誤。

3、權(quán)限檢查:看用戶是否具備訪問該數(shù)據(jù)的權(quán)限。

4、共享池檢查:共享池(Shared Pool)是一塊內(nèi)存池,最主要的作用是緩存 SQL 語句和該語句的執(zhí)行計劃。Oracle 通過檢查共享池是否存在 SQL 語句的執(zhí)行計劃,來判斷進行軟解析,還是硬解析。那軟解析和硬解析又該怎么理解呢?

在共享池中,Oracle 首先對 SQL 語句進行 Hash 運算,然后根據(jù) Hash 值在庫緩存(Library Cache)中查找,如果存在 SQL 語句的執(zhí)行計劃,就直接拿來執(zhí)行,直接進入“執(zhí)行器”的環(huán)節(jié),這就是軟解析。

如果沒有找到 SQL 語句和執(zhí)行計劃,Oracle 就需要創(chuàng)建解析樹進行解析,生成執(zhí)行計劃,進入“優(yōu)化器”這個步驟,這就是硬解析。

共享池是 Oracle 中的術語,包括了庫緩存,數(shù)據(jù)字典緩沖區(qū)等。我們上面已經(jīng)講到了庫緩存區(qū),它主要緩存 SQL 語句和執(zhí)行計劃。而數(shù)據(jù)字典緩沖區(qū)存儲的是 Oracle 中的對象定義,比如表、視圖、索引等對象。當對 SQL 語句進行解析的時候,如果需要相關的數(shù)據(jù),會從數(shù)據(jù)字典緩沖區(qū)中提取。

5、優(yōu)化器:優(yōu)化器中就是要進行硬解析,也就是決定怎么做,比如創(chuàng)建解析樹,生成執(zhí)行計劃。

6、執(zhí)行器:當有了解析樹和執(zhí)行計劃之后,就知道了 SQL 該怎么被執(zhí)行,這樣就可以在執(zhí)行器中執(zhí)行語句了。

二、MySQL 中的 SQL 是如何執(zhí)行的

首先 MySQL 是典型的C/S 架構(gòu),即 Client/Server 架構(gòu),服務器端程序使用的 mysqld。整體的 MySQL 流程如下圖所示:

MySQL 由三層組成:

  • 連接層:客戶端和服務器端建立連接,客戶端發(fā)送 SQL 至服務器端;
  • SQL 層:對 SQL 語句進行查詢處理;
  • 存儲引擎層:與數(shù)據(jù)庫文件打交道,負責數(shù)據(jù)的存儲和讀取。

SQL 層的結(jié)構(gòu):

    1. 查詢緩存:Server 如果在查詢緩存中發(fā)現(xiàn)了這條 SQL 語句,就會直接將結(jié)果返回給客戶端;如果沒有,就進入到解析器階段。需要說明的是,因為查詢緩存往往效率不高,所以在 MySQL8.0 之后就拋棄了這個功能。
    1. 解析器:在解析器中對 SQL 語句進行語法分析、語義分析。
    1. 優(yōu)化器:在優(yōu)化器中會確定 SQL 語句的執(zhí)行路徑,比如是根據(jù)全表檢索,還是根據(jù)索引來檢索等。
    1. 執(zhí)行器:在執(zhí)行之前需要判斷該用戶是否具備權(quán)限,如果具備權(quán)限就執(zhí)行 SQL 查詢并返回結(jié)果。在 MySQL8.0 以下的版本,如果設置了查詢緩存,這時會將查詢結(jié)果進行緩存。

你能看到 SQL 語句在 MySQL 中的流程是:SQL 語句→緩存查詢→解析器→優(yōu)化器→執(zhí)行器。在一部分中,MySQL 和 Oracle 執(zhí)行 SQL 的原理是一樣的。

與 Oracle 不同的是,MySQL 的存儲引擎采用了插件的形式,每個存儲引擎都面向一種特定的數(shù)據(jù)庫應用環(huán)境。同時開源的 MySQL 還允許開發(fā)人員設置自己的存儲引擎,下面是一些常見的存儲引擎:

  • 1.InnoDB 存儲引擎:它是 MySQL 5.5 版本之后默認的存儲引擎,最大的特點是支持事務、行級鎖定、外鍵約束等。
    1. MyISAM 存儲引擎:在 MySQL 5.5 版本之前是默認的存儲引擎,不支持事務,也不支持外鍵,最大的特點是速度快,占用資源少。
    1. Memory 存儲引擎:使用系統(tǒng)內(nèi)存作為存儲介質(zhì),以便得到更快的響應速度。不過如果 mysqld 進程崩潰,則會導致所有的數(shù)據(jù)丟失,因此我們只有當數(shù)據(jù)是臨時的情況下才使用 Memory 存儲引擎。
    1. NDB 存儲引擎:也叫做 NDB Cluster 存儲引擎,主要用于 MySQL Cluster 分布式集群環(huán)境,類似于 Oracle 的 RAC 集群。
    1. Archive 存儲引擎:它有很好的壓縮機制,用于文件歸檔,在請求寫入時會進行壓縮,所以也經(jīng)常用來做倉庫。

需要注意的是,數(shù)據(jù)庫的設計在于表的設計,而在 MySQL 中每個表的設計都可以采用不同的存儲引擎,我們可以根據(jù)實際的數(shù)據(jù)處理需要來選擇存儲引擎,這也是 MySQL 的強大之處。

三、如何在 MySQL 中對一條 SQL 語句的執(zhí)行時間進行分析

首先我們需要看下 profiling 是否開啟,開啟它可以讓 MySQL 收集在 SQL 執(zhí)行時所使用的資源情況,命令如下:

select @@profiling;


profiling=0 代表關閉,我profiling=1 代表開啟:

set profiling=1;

然后我們執(zhí)行一個 SQL 查詢

select * from course;
show profiles;


如果我們想要獲取上一次查詢的執(zhí)行時間,可以使用:

show profile;

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容