hql取满足条件最新一条记录_MySql 之一条查询sql的执行过程
每當(dāng)我把一條查詢sql語(yǔ)句寫完了,并且執(zhí)行完得到想要的結(jié)果。這時(shí)我就在想為什么我寫這樣的一條sql語(yǔ)句,就能給我查詢出我想要的結(jié)果,為什么我寫了update就能更新一條語(yǔ)句?它們的執(zhí)行過程是什么樣的?它們的原理是什么?那么接下來我們就來說說這個(gè)。
select上面這條查詢語(yǔ)句非常簡(jiǎn)單,就是查詢一個(gè)id為8的用戶信息。那么它的執(zhí)行流程是怎么樣的?別急,咱們先看一張圖,
根據(jù)上面的圖,咱們一步一步來分析。從圖中可以看出整個(gè)執(zhí)行過程大致可以分為兩部分,分別是server層和引擎層。
server層中又分為連接器、分析器、查詢緩存、優(yōu)化器以及執(zhí)行器幾部分。
引擎層則是主要負(fù)責(zé)存儲(chǔ)數(shù)據(jù),提供讀寫接口。
那么接下來從頭開始分析。
1、連接器
首先要操作數(shù)據(jù)庫(kù),那么必須得連接上數(shù)據(jù)庫(kù),所以這時(shí)候就用到了連接器。當(dāng)你輸入 “mysql -h$ip -P$端口 -u$登錄名 -p ” 時(shí)就表示要進(jìn)行連接數(shù)據(jù)庫(kù)了,然后輸入密碼進(jìn)行連接。如果密碼或者用戶名錯(cuò)了,則會(huì)報(bào)如下錯(cuò)誤:
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)如果輸入用戶名和密碼正確,那么連接器接下來就去權(quán)限表中查詢你登錄用戶所擁有的權(quán)限,之后此用戶操作數(shù)據(jù)的權(quán)限判斷邏輯都將依賴查詢到的權(quán)限。哪怕你修改了此用戶的權(quán)限也還是沒用,必須重新新建連接,修改的權(quán)限才會(huì)生效。
另外說到這里就順便提一下,客戶端連接mysql服務(wù)器時(shí),如果連接一直處于空閑狀態(tài),那么到了一定的時(shí)候就會(huì)斷開連接,多長(zhǎng)時(shí)間是由 wait_timeout 控制的,其默認(rèn)是8個(gè)小時(shí)。如果超過8個(gè)小時(shí),你執(zhí)行操作數(shù)據(jù)庫(kù)時(shí)就回提示 “Lost connection to MySQL server during query”,這時(shí)只有重新連接數(shù)據(jù)庫(kù)方能進(jìn)行操作。
說到連接器,咱們得說一下長(zhǎng)連接和短鏈接。長(zhǎng)連接就是如果客戶端一直都有請(qǐng)求操作數(shù)據(jù)庫(kù),那么就會(huì)一直使用這個(gè)連接進(jìn)行操作。短鏈接就是每次執(zhí)行完很少的數(shù)據(jù)庫(kù)操作就斷開連接了,如果再有請(qǐng)求就必須重新連接。
所以這里建議減少數(shù)據(jù)庫(kù)的連接操作,盡量使用長(zhǎng)連接。但是長(zhǎng)時(shí)間使用長(zhǎng)連接會(huì)導(dǎo)致一個(gè)問題,那就是mysql的占用的內(nèi)存會(huì)越來越大,甚至到最后可能會(huì)出現(xiàn)OOM情況,導(dǎo)致mysql異常重啟,那么這就尷尬了。
針對(duì)上面的情況有兩種解決辦法:
(1)、定期斷開長(zhǎng)連接,或者斷開一些查詢占用內(nèi)存比較大的操作的連接,釋放資源。
(2)、如果是5.7及以上版本,可以使用 mysql_reset_connection 來重置連接,但是需要注意以下幾點(diǎn)
- 活躍事務(wù)會(huì)被回滾,自動(dòng)提交模式也會(huì)被重置;
- 釋放所有表鎖;
- 關(guān)閉&刪除所有臨時(shí)表;
- 會(huì)話變量(選項(xiàng))被重置成和全局變量一致;
- 用戶級(jí)變量丟失;
- PREPARE語(yǔ)句會(huì)被釋放(其相應(yīng)的HANDLER也會(huì)被關(guān)閉);
- LAST_INSERT_ID值重置為0;
- 利用GET_LOCK獲取的鎖會(huì)被釋放。
以上是mysql官微給出的解釋,所以重置連接的時(shí)候以上因素,以免對(duì)數(shù)據(jù)庫(kù)中的數(shù)據(jù)產(chǎn)生影響。
2、查詢緩存
客戶端連接成功mysql服務(wù)器后,執(zhí)行上面的一條sql時(shí),首先會(huì)去緩存中查詢是否有數(shù)據(jù),如果有數(shù)據(jù),那么直接把數(shù)據(jù)返回給客戶端,后面的步驟都省略了。它的原理怎樣的呢?請(qǐng)接著往下看,一條查詢sql的首次執(zhí)行完成后,會(huì)把sql語(yǔ)句作為key,把查詢出來的數(shù)據(jù)作為value放入到緩存中,如果后面再有相同的查詢,那么直接從緩存中取值便可。
看到這里也許你們會(huì)想緩存這么好用,那以后要多用緩存。別急,請(qǐng)接著往下看。查詢緩存用起來確實(shí)好用,但是它有一個(gè)弊端,那就是當(dāng)這個(gè)表做了更新操作時(shí),那么此表的緩存將會(huì)全部清空。也許當(dāng)你辛辛苦苦緩存起來的數(shù)據(jù),還沒來得及用時(shí)就可能被一條update語(yǔ)句給全部干掉。
所以如果更新比較頻繁的表是不適合使用緩存的,如果是某些配置表倒是比較適合緩存的使用。
在mysql中的查詢語(yǔ)句使不使用緩存時(shí)看query_cache_type的值,當(dāng)為0時(shí)關(guān)閉緩存,當(dāng)為1時(shí)表示開啟緩存,當(dāng)為2(DEMAND)時(shí)表示只有在sql語(yǔ)句中帶有 SQL_CACHE 關(guān)鍵字才會(huì)使用緩存,如下sql
select SQL_CACHE * from user where id=8不過需要注意的一點(diǎn)是 mysql 8.0 版本已經(jīng)把緩存功能完全移除,所以這一塊需要注意一下。
3、分析器
當(dāng)執(zhí)行一條查詢sql時(shí),會(huì)優(yōu)先取查詢緩存,如果緩存中沒有數(shù)據(jù),那么便會(huì)開始sql的真正的執(zhí)行流程。首先是分析器,其主要就是對(duì)sql語(yǔ)句進(jìn)行 “詞法分析” 和 “語(yǔ)法分析”。
詞法分析 就是對(duì)sql中的單詞進(jìn)行逐個(gè)的分析,比如 從 select 可以識(shí)別出要執(zhí)行查詢操作,user則是識(shí)別成表user,id則識(shí)別成user表中字段id。
語(yǔ)法分析就是分析整條sql是否符合mysql的語(yǔ)句,比如 你故意把sql中的 where 后面不跟條件,那么語(yǔ)法就肯定會(huì)問題,那么此時(shí)就會(huì)給你提示 “You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1” 。如果給出類似的提示,那么基本就是語(yǔ)法錯(cuò)了,那就得仔細(xì)檢查一下寫的sql語(yǔ)句了。
4、優(yōu)化器
經(jīng)過了分析器這一層,那么接下來就要進(jìn)入優(yōu)化器了。從分析器中我們已經(jīng)知道這條sql是要執(zhí)行更新還是查詢操作。那么優(yōu)化器便是要對(duì)這條sq執(zhí)行之前l(fā)進(jìn)行優(yōu)化處理,有哪些優(yōu)化處理呢?例如 某表有多個(gè)索引的時(shí)候 決定用哪一個(gè)索引;或者多關(guān)聯(lián)(join)查詢的時(shí)候,決定關(guān)聯(lián)的順序。比如下面一條sql
select * from user u join score s using(ID) where u.id=20 and s.scores=80;上面一條 sql 可以分為兩種情況
- 既可以先從表user里面取出id=20的記錄的ID值,再根據(jù)ID值關(guān)聯(lián)到表socre,再判斷score表里scores的值是否等于80。
- 也可以先從表score里面取出scores=80的記錄的ID值,再根據(jù)ID值關(guān)聯(lián)到user,再判斷user表里面id的值是否等于20。
這兩種方案得出的結(jié)果是一樣的,但是執(zhí)行的效率是不一樣的,而優(yōu)化器作用便是從中選擇一個(gè)方案。
5、執(zhí)行器
當(dāng)優(yōu)化器選擇好了方案,那么便進(jìn)入執(zhí)行器階段,這時(shí)候就要開始執(zhí)行sql了。執(zhí)行sql前要查詢一下你對(duì)需要操作的表是否有對(duì)應(yīng)的操作權(quán)限,如果沒有操作權(quán)限,則會(huì)給出提示 “ERROR 1142 (42000): SELECT command denied to user 'b'@'localhost' for table 'XXX‘ “ 。
如果有對(duì)應(yīng)表的操作權(quán)限,那么便打開表繼續(xù)執(zhí)行,執(zhí)行器會(huì)根據(jù)定義的表的引擎,來執(zhí)行引擎提供的對(duì)應(yīng)讀寫的接口,mysql 5.5版本之后 默認(rèn)的引擎為 InnoDB。
其大致流程如下:(假如 id 是沒有索引的)
如果是 id 是有索引的,第一次調(diào)用的是“取滿足條件的第一行”這個(gè)接口,之后循環(huán)取“滿足條件的下一行”這個(gè)接口,基本和上面差不多。這些接口都是引擎中已經(jīng)定義好的。
至此 一條 sql 便執(zhí)行完成。
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的hql取满足条件最新一条记录_MySql 之一条查询sql的执行过程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql in优化_MySQL 探秘:
- 下一篇: .net post提交后接收返回数据_A