sqlserver查詢表是否存在的語句 sql數(shù)據(jù)庫查詢中,空值查詢條件怎么寫?
sql數(shù)據(jù)庫查詢中,空值查詢條件怎么寫?在MSSQLServer和Oraclmysql:一條SQL查詢語句是如何執(zhí)行的?本文將分析下一條sql語句在Mysql中的執(zhí)行過程,包括sql的查詢將如何在My
sql數(shù)據(jù)庫查詢中,空值查詢條件怎么寫?
在MSSQLServer和Oracl
mysql:一條SQL查詢語句是如何執(zhí)行的?
本文將分析下一條sql語句在Mysql中的執(zhí)行過程,包括sql的查詢將如何在Mysql內(nèi)部流動,以及SQL語句的更新是如何完成的。
在分析之前,我先給大家展示一下MySQL的基礎(chǔ)架構(gòu),了解一下MySQL由哪些組件組成,可以幫助我們理解和解決這些問題。
MySQL基礎(chǔ)架構(gòu)分析1.1 MySQL基礎(chǔ)架構(gòu)概述
下圖是MySQL的簡要架構(gòu)圖,從中可以清楚地看到用戶 的SQL語句在MySQL內(nèi)部執(zhí)行。
讓 下面我們簡單介紹一下下圖中涉及到的一些組件的基本功能,幫助你理解這個圖,這些組件的功能將在1.2節(jié)詳細(xì)介紹。
連接器:認(rèn)證與權(quán)限相關(guān)(登錄MySQL時)。查詢緩存:在執(zhí)行一條查詢語句的時候,會先查詢緩存(MySQL版以后去掉了,因為這個功能不是很實用)。如果解析器:不;如果沒有命中緩存,SQL語句將通過解析器。說白了,解析器首先要看你的SQL語句是干什么用的,然后檢查你的SQL語句的語法是否正確。優(yōu)化器:按照MySQL認(rèn)為最好的方案實現(xiàn)。執(zhí)行器:執(zhí)行該語句,然后從存儲引擎返回數(shù)據(jù)。
簡單來說,MySQL主要分為服務(wù)器層和存儲引擎層:
服務(wù)器層:主要包括連接器、查詢緩存、分析器、優(yōu)化器、執(zhí)行器等??绱鎯σ娴乃泄δ芏荚谶@一層實現(xiàn),比如存儲過程、觸發(fā)器、視圖、函數(shù)等。還有一個通用的日志模塊,binglog日志模塊。存儲引擎:主要負(fù)責(zé)數(shù)據(jù)存儲和讀取,采用可替換插件架構(gòu),支持InnoDB、MyISAM、Memory等多種存儲引擎,其中InnoDB引擎自帶日志模塊redolog模塊。現(xiàn)在最常用的存儲引擎是InnoDB,從MySQL 5 . 5 . 5版開始,它就被視為默認(rèn)的存儲引擎。1.2服務(wù)器層基本組件介紹
1)連接器
連接器主要涉及與身份驗證和權(quán)限相關(guān)的功能,就像高級門衛(wèi)一樣。
它主要負(fù)責(zé)用戶登錄數(shù)據(jù)庫和用戶認(rèn)證。;的身份,包括檢查賬戶密碼、權(quán)限等操作。如果用戶 的帳戶密碼已過,連接器將在權(quán)限表中查找該用戶的所有權(quán)限,然后該連接中權(quán)限的邏輯判斷將取決于此時讀取的權(quán)限數(shù)據(jù),也就是說,只要連接持續(xù)打開,即使管理員修改了用戶 的權(quán)限。
2)查詢緩存(MySQL版后移除)
查詢緩存主要用于緩存我們執(zhí)行的SELECT語句以及該語句的結(jié)果集。
連接建立后,執(zhí)行查詢語句時,會先查詢緩存。Mysql會先檢查這條sql是否已經(jīng)執(zhí)行,并以Key-Value的形式緩存在內(nèi)存中,其中Key是查詢預(yù)期,Value是結(jié)果集。如果命中緩存鍵,將直接返回給客戶端。如果未命中,則執(zhí)行后續(xù)操作,完成后緩存結(jié)果,方便下次調(diào)用。當(dāng)然,當(dāng)實際執(zhí)行緩存查詢時,用戶 的權(quán)限,以及該表是否有查詢條件。
不建議對MySQL查詢使用緩存,因為在實際的業(yè)務(wù)場景中,查詢緩存失效可能會非常頻繁。如果更新一個表,該表上的所有查詢緩存都將被清空。對于不經(jīng)常更新的數(shù)據(jù),仍然可以使用緩存。
因此,在大多數(shù)情況下,我們一般不 不建議使用查詢緩存。
MySQL版之后,刪除了緩存功能,官方認(rèn)為實際應(yīng)用場景中該功能較少,所以干脆刪除了。
3)分析儀
如果MySQL不 t命中緩存,就會進(jìn)入分析器,分析器主要用來分析SQL語句是干什么用的,分析器會分為幾個步驟:
第一步,詞法分析,一條SQL語句由多個字符串組成。首先,需要提取關(guān)鍵字,比如select、引發(fā)查詢的表、字段名、查詢條件等等。完成這些操作后,你將進(jìn)入第二步。
第二步,語法分析,主要是判斷你輸入的sql是否正確,是否符合MySQL的語法。
完成這兩步,MySQL就準(zhǔn)備開始執(zhí)行了,但是怎么執(zhí)行,怎么執(zhí)行才是最好的結(jié)果?這時候優(yōu)化器就需要發(fā)揮作用了。
4)優(yōu)化器
優(yōu)化器的作用是它認(rèn)為最優(yōu)的執(zhí)行方案被實現(xiàn)(有時可能不是最優(yōu)的,本文涉及到這部分知識的深入講解),比如使用多個索引時如何選擇索引,如何查詢多個表。何時以及如何選擇關(guān)聯(lián)順序等。
可以說優(yōu)化器之后,可以說如何執(zhí)行這個語句已經(jīng)決定了。
5)致動器
當(dāng)執(zhí)行方案選定后,MySQL就準(zhǔn)備開始執(zhí)行了。首先,在執(zhí)行之前,它會檢查用戶是否有權(quán)限。否則,它將返回一條錯誤消息。如果有權(quán)限,它會調(diào)用引擎的接口,返回接口執(zhí)行的結(jié)果。
兩句話分析2.1查詢語句
說到這里,一條sql語句到底是怎么執(zhí)行的呢?其實我們的sql可以分為兩種,一種是查詢,一種是更新(添加、更新、刪除)。讓 讓我們首先分析查詢語句。聲明如下:
Select * from tb_student A where和張三
結(jié)合上面的描述,我們分析一下這條語句的執(zhí)行過程:
首先,檢查語句是否有權(quán)限。如果沒有,直接返回錯誤信息。如果有,在Mysql8.0版本之前,先查詢緩存,以此sql語句為關(guān)鍵字查詢內(nèi)存中是否有結(jié)果。如果有直接緩存,如果沒有,執(zhí)行下一步。由分析器進(jìn)行詞法分析,提取sql語句的關(guān)鍵元素,比如提取上面的語句是query select,提取要查詢的表名為tb_student,需要查詢所有列,查詢條件為該表的id1。然后判斷這條sql語句是否存在語法錯誤,比如關(guān)鍵詞是否正確等。如果沒有問題,執(zhí)行下一步。接下來,優(yōu)化器確定執(zhí)行方案。上面的sql語句可以有兩種執(zhí)行方案:
A.首先檢查名為 "張三 "在學(xué)生表中,然后判斷年齡是否為18歲。首先找出18歲的學(xué)生,然后查詢名字是 "張三 "。
然后優(yōu)化器根據(jù)自己的優(yōu)化算法選擇最高效的方案(優(yōu)化器認(rèn)為有時候不一定是最好的)。然后確認(rèn)執(zhí)行計劃后,就準(zhǔn)備開始執(zhí)行了。
檢查權(quán)限。如果沒有權(quán)限,將返回一條錯誤消息。如果有權(quán)限,會調(diào)用數(shù)據(jù)庫引擎接口,返回引擎的執(zhí)行結(jié)果。
2.2更新聲明
以上是查詢sql的一個執(zhí)行過程,所以讓 讓我們看看update語句是如何執(zhí)行的。sql語句如下所示:
更新tb _學(xué)生一集張三在哪里
讓 s修改張三 年代。實際數(shù)據(jù)庫中肯定不會設(shè)置年齡字段,否則由技術(shù)負(fù)責(zé)人鍵入。其實這個語句基本會遵循上一次查詢的流程,只是更新時必須記錄日志,這就要介紹日志模塊,MySQL 自己的日志模塊binlog(歸檔日志)和所有存儲引擎??梢允褂?,我們常用的InnoDB引擎還自帶了一個日志模塊redo log(重做日志),所以我們將在InnoDB模式下討論這條語句的執(zhí)行過程。流程如下:
先查詢張三的數(shù)據(jù)。如果有緩存,也會使用它。然后獲取查詢語句,把年齡改成19,然后調(diào)用引擎的API接口寫這一行數(shù)據(jù)。InnoDB引擎將數(shù)據(jù)保存在內(nèi)存中,并記錄重做日志。此時重做日志進(jìn)入準(zhǔn)備狀態(tài),然后告訴執(zhí)行人執(zhí)行完成,可以隨時提交。收到通知后,執(zhí)行器記錄binlog,然后調(diào)用引擎接口,提交重做日志作為提交狀態(tài)。更新完成。這里肯定有同學(xué)會問,為什么要用兩個日志模塊,而不是一個日志模塊?
這是因為MySQL沒有 t一開始用InnoDB engine(InnoDB engine是其他公司作為插件插入MySQL的),MySQL 的引擎是MyISAM,但是我們知道重做日志是InnoDB引擎獨有的,其他存儲引擎都沒有。這樣一來,就不會有崩潰安全的能力(即使數(shù)據(jù)庫非正常重啟,之前提交的記錄也不會丟失),binlog日志只能用于存檔。
It 不是那樣的。;不可能只使用一個日志模塊,但是InnoDB引擎支持通過重做日志處理事務(wù)。然后,有些同學(xué)會問,我用兩個日志模塊,但是可以 不會這么復(fù)雜吧?為什么重做日志引入了準(zhǔn)備提交前狀態(tài)?這里我們用歸謬法來解釋為什么要這樣做。
先寫重做日志直接提交,再寫binlog。假設(shè)寫完重做日志后,機(jī)器掛起,binlog日志沒有寫,那么機(jī)器重啟后,機(jī)器會通過重做日志恢復(fù)數(shù)據(jù),但此時binlog沒有記錄數(shù)據(jù),所以后面?zhèn)浞輽C(jī)器時會丟失,同時主從同步也會丟失這些數(shù)據(jù)。首先寫binlog,然后重做log。假設(shè)寫完binlog后,機(jī)器異常重啟。因為沒有重做日志,所以這臺機(jī)器無法恢復(fù)這個記錄,但是binlog有一個記錄。然后和上面一樣,會出現(xiàn)數(shù)據(jù)不一致的情況。如果重做日志分兩個階段提交,會有所不同。編寫binglog后,提交Redlog會防止上述問題,從而保證數(shù)據(jù)的一致性。那么問題來了。嗯,有沒有極端的情況?假設(shè)重做日志處于提交前狀態(tài),binglog已經(jīng)完成。如果此時出現(xiàn)異常重啟會怎么樣?這取決于MySQL的處理機(jī)制,MySQL的處理過程如下:
判斷重做日志是否完整,如果完整,立即提交。如果重做日志只是預(yù)提交,而不是提交狀態(tài),此時會判斷binlog是否完整,如果完整就提交重做日志,如果不完整就回滾事務(wù)。這就解決了數(shù)據(jù)一致性的問題。
第三,MySQL主要分為服務(wù)器層和引擎層。服務(wù)器層主要包括連接器、查詢緩存、分析器、優(yōu)化器和執(zhí)行器,還有一個日志模塊(binlog),所有執(zhí)行引擎都可以共享,redolog只有InnoDB才有。引擎層是插件,主要包括MyISAM、InnoDB、Memory等等。查詢語句的執(zhí)行流程如下:權(quán)限檢查(如果命中緩存)-查詢緩存-分析器-優(yōu)化器-權(quán)限檢查-執(zhí)行器。引擎更新語句的執(zhí)行流程如下:分析器-權(quán)限檢查-執(zhí)行器。