oracle execute immediate执行多条语句_用数据库的方式思考SQL是如何执行的
私信我或關(guān)注微信號:猿來如此呀,回復(fù):學(xué)習(xí),獲取免費學(xué)習(xí)資源包。
今天我們就從數(shù)據(jù)庫的角度來思考一下 SQL 是如何被執(zhí)行的。
關(guān)于今天的內(nèi)容,你會從以下幾個方面進行學(xué)習(xí):
Oracle 中的 SQL 是如何執(zhí)行的
我們先來看下 SQL 在 Oracle 中的執(zhí)行過程:
從上面這張圖中可以看出,SQL 語句在 Oracle 中經(jīng)歷了以下的幾個步驟。
在共享池中,Oracle 首先對 SQL 語句進行 Hash 運算,然后根據(jù) Hash 值在庫緩存(Library Cache)中查找,如果存在 SQL 語句的執(zhí)行計劃,就直接拿來執(zhí)行,直接進入“執(zhí)行器”的環(huán)節(jié),這就是軟解析。
如果沒有找到 SQL 語句和執(zhí)行計劃,Oracle 就需要創(chuàng)建解析樹進行解析,生成執(zhí)行計劃,進入“優(yōu)化器”這個步驟,這就是硬解析。
共享池是 Oracle 中的術(shù)語,包括了庫緩存,數(shù)據(jù)字典緩沖區(qū)等。我們上面已經(jīng)講到了庫緩存區(qū),它主要緩存 SQL 語句和執(zhí)行計劃。而數(shù)據(jù)字典緩沖區(qū)存儲的是 Oracle 中的對象定義,比如表、視圖、索引等對象。當(dāng)對 SQL 語句進行解析的時候,如果需要相關(guān)的數(shù)據(jù),會從數(shù)據(jù)字典緩沖區(qū)中提取。
庫緩存這一個步驟,決定了 SQL 語句是否需要進行硬解析。為了提升 SQL 的執(zhí)行效率,我們應(yīng)該盡量避免硬解析,因為在 SQL 的執(zhí)行過程中,創(chuàng)建解析樹,生成執(zhí)行計劃是很消耗資源的。
你可能會問,如何避免硬解析,盡量使用軟解析呢?在 Oracle 中,綁定變量是它的一大特色。綁定變量就是在 SQL 語句中使用變量,通過不同的變量取值來改變 SQL 的執(zhí)行結(jié)果。這樣做的好處是能提升軟解析的可能性,不足之處在于可能會導(dǎo)致生成的執(zhí)行計劃不夠優(yōu)化,因此是否需要綁定變量還需要視情況而定。
舉個例子,我們可以使用下面的查詢語句:
SQL> select * from player where player_id = 10001;
你也可以使用綁定變量,如:
SQL> select * from player where player_id = :player_id;
這兩個查詢語句的效率在 Oracle 中是完全不同的。如果你在查詢 player_id = 10001 之后,還會查詢 10002、10003 之類的數(shù)據(jù),那么每一次查詢都會創(chuàng)建一個新的查詢解析。而第二種方式使用了綁定變量,那么在第一次查詢之后,在共享池中就會存在這類查詢的執(zhí)行計劃,也就是軟解析。
因此我們可以通過使用綁定變量來減少硬解析,減少 Oracle 的解析工作量。但是這種方式也有缺點,使用動態(tài) SQL 的方式,因為參數(shù)不同,會導(dǎo)致 SQL 的執(zhí)行效率不同,同時 SQL 優(yōu)化也會比較困難。
MySQL 中的 SQL 是如何執(zhí)行的
Oracle 中采用了共享池來判斷 SQL 語句是否存在緩存和執(zhí)行計劃,通過這一步驟我們可以知道應(yīng)該采用硬解析還是軟解析。那么在 MySQL 中,SQL 是如何被執(zhí)行的呢?
首先 MySQL 是典型的 C/S 架構(gòu),即 Client/Server 架構(gòu),服務(wù)器端程序使用的 mysqld。整體的 MySQL 流程如下圖所示:
你能看到 MySQL 由三層組成:
其中 SQL 層與數(shù)據(jù)庫文件的存儲方式無關(guān),我們來看下 SQL 層的結(jié)構(gòu):
你能看到 SQL 語句在 MySQL 中的流程是:SQL 語句→緩存查詢→解析器→優(yōu)化器→執(zhí)行器。在一部分中,MySQL 和 Oracle 執(zhí)行 SQL 的原理是一樣的。
與 Oracle 不同的是,MySQL 的存儲引擎采用了插件的形式,每個存儲引擎都面向一種特定的數(shù)據(jù)庫應(yīng)用環(huán)境。同時開源的 MySQL 還允許開發(fā)人員設(shè)置自己的存儲引擎,下面是一些常見的存儲引擎:
需要注意的是,數(shù)據(jù)庫的設(shè)計在于表的設(shè)計,而在 MySQL 中每個表的設(shè)計都可以采用不同的存儲引擎,我們可以根據(jù)實際的數(shù)據(jù)處理需要來選擇存儲引擎,這也是 MySQL 的強大之處。
數(shù)據(jù)庫管理系統(tǒng)也是一種軟件
我們剛才了解了 SQL 語句在 Oracle 和 MySQL 中的執(zhí)行流程,實際上完整的 Oracle 和 MySQL 結(jié)構(gòu)圖要復(fù)雜得多:
如果你只是簡單地把 MySQL 和 Oracle 看成數(shù)據(jù)庫管理系統(tǒng)軟件,從外部看難免會覺得“晦澀難懂”,畢竟組織結(jié)構(gòu)太多了。我們在學(xué)習(xí)的時候,還需要具備抽象的能力,抓取最核心的部分:SQL 的執(zhí)行原理。因為不同的 DBMS 的 SQL 的執(zhí)行原理是相通的,只是在不同的軟件中,各有各的實現(xiàn)路徑。
既然一條 SQL 語句會經(jīng)歷不同的模塊,那我們就來看下,在不同的模塊中,SQL 執(zhí)行所使用的資源(時間)是怎樣的。下面我來教你如何在 MySQL 中對一條 SQL 語句的執(zhí)行時間進行分析。
首先我們需要看下 profiling 是否開啟,開啟它可以讓 MySQL 收集在 SQL 執(zhí)行時所使用的資源情況,命令如下:
mysql> select @@profiling;
profiling=0 代表關(guān)閉,我們需要把 profiling 打開,即設(shè)置為 1:
mysql> set profiling=1;
然后我們執(zhí)行一個 SQL 查詢(你可以執(zhí)行任何一個 SQL 查詢):
mysql> select * from wucai.heros;
查看當(dāng)前會話所產(chǎn)生的所有 profiles,你會發(fā)現(xiàn)我們剛才執(zhí)行了兩次查詢,Query ID 分別為 1 和 2。如果我們想要獲取上一次查詢的執(zhí)行時間,可以使用:
mysql> show profile;
當(dāng)然你也可以查詢指定的 Query ID,比如:
mysql> show profile for query 2;
查詢 SQL 的執(zhí)行時間結(jié)果和上面是一樣的。
在 8.0 版本之后,MySQL 不再支持緩存的查詢,原因我在上文已經(jīng)說過。一旦數(shù)據(jù)表有更新,緩存都將清空,因此只有數(shù)據(jù)表是靜態(tài)的時候,或者數(shù)據(jù)表很少發(fā)生變化時,使用緩存查詢才有價值,否則如果數(shù)據(jù)表經(jīng)常更新,反而增加了 SQL 的查詢時間。
你可以使用 select version() 來查看 MySQL 的版本情況。
總結(jié)
我們在使用 SQL 的時候,往往只見樹木,不見森林,不會注意到它在各種數(shù)據(jù)庫軟件中是如何執(zhí)行的,今天我們從全貌的角度來理解這個問題。你能看到不同的 RDBMS 之間有相同的地方,也有不同的地方。
相同的地方在于 Oracle 和 MySQL 都是通過解析器→優(yōu)化器→執(zhí)行器這樣的流程來執(zhí)行 SQL 的。
但 Oracle 和 MySQL 在進行 SQL 的查詢上面有軟件實現(xiàn)層面的差異。Oracle 提出了共享池的概念,通過共享池來判斷是進行軟解析,還是硬解析。而在 MySQL 中,8.0 以后的版本不再支持查詢緩存,而是直接執(zhí)行解析器→優(yōu)化器→執(zhí)行器的流程,這一點從 MySQL 中的 show profile 里也能看到。同時 MySQL 的一大特色就是提供了各種存儲引擎以供選擇,不同的存儲引擎有各自的使用場景,我們可以針對每張表選擇適合的存儲引擎。
今天的內(nèi)容到這里就結(jié)束了,你能說一下 Oracle 中的綁定變量是什么嗎?使用它有什么優(yōu)缺點嗎?MySQL 的存儲引擎是一大特色,其中 MyISAM 和 InnoDB 都是常用的存儲引擎,這兩個搜索引擎的特性和使用場景分別是什么?
最后留一道選擇題吧,解析后的 SQL 語句在 Oracle 的哪個區(qū)域中進行緩存?
A. 數(shù)據(jù)緩沖區(qū)
B. 日志緩沖區(qū)
C. 共享池
D. 大池
如果這篇文章幫你理順了 Oracle 和 MySQL 執(zhí)行 SQL 的過程,歡迎你把它分享給你的朋友或者同事。
來源網(wǎng)絡(luò),侵權(quán)聯(lián)系刪除
總結(jié)
以上是生活随笔為你收集整理的oracle execute immediate执行多条语句_用数据库的方式思考SQL是如何执行的的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 我国首个“风光火储一体化”送电特高压工程
- 下一篇: 代码实现sql编译器_【数据蒋堂】第 1