MySQL查詢步驟及優(yōu)化

過(guò)程概覽

  1. 客戶端發(fā)送一條查詢給服務(wù)器贝奇;
  2. 服務(wù)器檢查查詢緩存,如果命中了緩存靠胜,則立即趕回存儲(chǔ)在緩存中的結(jié)果掉瞳。否則進(jìn)入下一階段;
  3. 服務(wù)器端進(jìn)行SQL解析浪漠,預(yù)處理陕习,再由優(yōu)化器生成對(duì)應(yīng)的執(zhí)行計(jì)劃;
  4. MySQL根據(jù)優(yōu)化器生成的執(zhí)行計(jì)劃址愿,調(diào)用存儲(chǔ)引擎的API來(lái)執(zhí)行查詢该镣;
  5. 將結(jié)果返回給客戶端

查詢緩存

在解析一個(gè)查詢語(yǔ)句之前,如果查詢緩存是打開(kāi)的响谓,那么MySQL會(huì)優(yōu)先檢查這個(gè)查詢是否命中查詢緩存中的數(shù)據(jù)损合。這個(gè)檢查是通過(guò)一個(gè)對(duì)大小寫敏感的哈希查找實(shí)現(xiàn)的。查詢和緩存中的查詢即使只有一個(gè)字節(jié)不同娘纷,那也不會(huì)匹配緩存結(jié)果嫁审,這種情況查詢會(huì)進(jìn)入下一個(gè)階段的處理。
如果當(dāng)前的查詢恰好命中了查詢緩存赖晶,那么在返回查詢結(jié)果之前MySQL會(huì)檢查一次用戶權(quán)限律适。這仍然是無(wú)須解析查詢SQL語(yǔ)句的,因?yàn)樵诓樵兙彺嬷幸呀?jīng)存放了當(dāng)前查詢需要訪問(wèn)的表信息遏插。如果權(quán)限沒(méi)有問(wèn)題捂贿,MySQL會(huì)跳過(guò)所有其他階段,直接從緩存中拿到結(jié)果并返回給客戶端胳嘲。這種情況下眷蜓,查詢不會(huì)被解析,不用生成執(zhí)行計(jì)劃胎围,不會(huì)被執(zhí)行吁系。
緩存配置參數(shù):

image.png

query_cache_limit: MySQL能夠緩存的最大結(jié)果,如果超出,則增加qcache_not_cached的值,并刪除查詢結(jié)果
query_cache_min_res_unit: 分配內(nèi)存塊時(shí)的最小單位大小
query_cache_size: 緩存使用的總內(nèi)存空間大小,單位是字節(jié),這個(gè)值必須是1024的整數(shù)倍,否則MySQL實(shí)際分配可能跟這個(gè)數(shù)值不同(感覺(jué)這個(gè)應(yīng)該跟文件系統(tǒng)的blcok大小有關(guān))
query_cache_type: 是否打開(kāi)緩存 OFF: 關(guān)閉德召,ON: 總是打開(kāi)
query_cache_wlock_invalidate: 如果某個(gè)數(shù)據(jù)表被鎖住,是否仍然從緩存中返回?cái)?shù)據(jù),默認(rèn)是OFF,表示仍然可以返回。

查詢管理器

在緩存中沒(méi)有命中到汽纤,則進(jìn)入MySQL語(yǔ)句的查詢管理器中進(jìn)行處理上岗。
在這里查詢語(yǔ)句可以轉(zhuǎn)換成一個(gè)快速執(zhí)行的代碼,代碼執(zhí)行的結(jié)果被送到客戶端管理器蕴坪。這個(gè)多步驟操作過(guò)程如下

  1. 查詢首先被解析并判斷是否合法
  2. 然后被重寫肴掷,去除了無(wú)用的操作并且加入預(yù)優(yōu)化部分
  3. 然后被重寫,去除了無(wú)用的操作并且加入預(yù)優(yōu)化部分
  4. 接著被優(yōu)化以便提升性能背传,并被轉(zhuǎn)換為可執(zhí)行代碼和數(shù)據(jù)訪問(wèn)計(jì)劃呆瞻。
  5. 然后計(jì)劃被編譯
  6. 最后,被執(zhí)行

這個(gè)過(guò)程涉及到如下幾個(gè)組成器件:
查詢解析器(Query parser):用于檢查查詢是否合法
查詢重寫器(Query rewriter):用于預(yù)優(yōu)化查詢
查詢優(yōu)化器(Query optimizer):用于優(yōu)化查詢
查詢執(zhí)行器(Query executor):用于編譯和執(zhí)行查詢

語(yǔ)法解析器

首先径玖,MySQL通過(guò)關(guān)鍵字將SQL語(yǔ)句進(jìn)行解析痴脾,并生成一棵對(duì)應(yīng)的“解析樹(shù)”。MySQL解析器將使用MySQL語(yǔ)法規(guī)則驗(yàn)證和解析查詢梳星。例如赞赖,它將驗(yàn)證是否使用錯(cuò)誤的關(guān)鍵字,或者使用關(guān)鍵字的順序是否正確等冤灾,再或者它還會(huì)驗(yàn)證引號(hào)是否能前后正確的匹配前域。如果查詢有錯(cuò),解析器將拒絕該查詢韵吨。比如匿垄,如果你寫成”SLECT …” 而不是 “SELECT …”,那就沒(méi)有下文了归粉。

解析器還會(huì)檢查關(guān)鍵字是否使用正確的順序椿疗,比如 WHERE 寫在 SELECT 之前會(huì)被拒絕。
然后盏浇,解析器要分析查詢中的表和字段,使用數(shù)據(jù)庫(kù)元數(shù)據(jù)來(lái)檢查:

  • 表是否存在
  • 表的字段是否存在
  • 對(duì)某類型字段的 運(yùn)算 是否 可能(比如芽狗,你不能將整數(shù)和字符串進(jìn)行比較绢掰,你不能對(duì)一個(gè)整數(shù)使用 substring() 函數(shù))

接著,解析器檢查在查詢中你是否有權(quán)限來(lái)讀韧妗(或?qū)懭耄┍淼尉ⅰ?qiáng)調(diào)一下:這些權(quán)限由DBA分配。

查詢重寫器

在這一步顾复,我們已經(jīng)有了查詢的內(nèi)部表示班挖,重寫器的目標(biāo)是:

  1. 預(yù)優(yōu)化查詢
  2. 避免不必要的運(yùn)算
  3. 幫助優(yōu)化器找到合理的最佳解決方案

重寫器按照一系列已知的規(guī)則對(duì)查詢執(zhí)行檢測(cè)。如果查詢匹配一種模式的規(guī)則芯砸,查詢就會(huì)按照這條規(guī)則來(lái)重寫萧芙。下面是(可選)規(guī)則的非詳盡的列表:

  1. 視圖合并:如果你在查詢中使用視圖给梅,視圖就會(huì)轉(zhuǎn)換為它的 SQL 代碼。
  2. 子查詢扁平化:子查詢是很難優(yōu)化的双揪,因此重寫器會(huì)嘗試移除子查詢
  3. 去除不必要的運(yùn)算符:比如动羽,如果你用了 DISTINCT,而其實(shí)你有 UNIQUE 約束(這本身就防止了數(shù)據(jù)出現(xiàn)重復(fù))渔期,那么 DISTINCT 關(guān)鍵字就被去掉了运吓。
  4. 排除冗余的聯(lián)接:如果相同的 JOIN 條件出現(xiàn)兩次,比如隱藏在視圖中的 JOIN 條件疯趟,或者由于傳遞性產(chǎn)生的無(wú)用 JOIN拘哨,都會(huì)被消除。
  5. 常數(shù)計(jì)算賦值:如果你的查詢需要計(jì)算信峻,那么在重寫過(guò)程中計(jì)算會(huì)執(zhí)行一次倦青。比如 WHERE AGE > 10+2 會(huì)轉(zhuǎn)換為 WHERE AGE > 12 , TODATE(“日期字符串”) 會(huì)轉(zhuǎn)換為 datetime 格式的日期值站欺。
  6. (高級(jí))分區(qū)裁剪(Partition Pruning):如果你用了分區(qū)表姨夹,重寫器能夠找到需要使用的分區(qū)。
  7. (高級(jí))物化視圖重寫(Materialized view rewrite):如果你有個(gè)物化視圖匹配查詢謂詞的一個(gè)子集矾策,重寫器將檢查視圖是否最新并修改查詢磷账,令查詢使用物化視圖而不是原始表。
  8. (高級(jí))自定義規(guī)則:如果你有自定義規(guī)則來(lái)修改查詢(就像 Oracle policy)贾虽,重寫器就會(huì)執(zhí)行這些規(guī)則逃糟。
  9. (高級(jí))OLAP轉(zhuǎn)換:分析/加窗 函數(shù),星形聯(lián)接蓬豁,ROLLUP 函數(shù)……都會(huì)發(fā)生轉(zhuǎn)換(但我不確定這是由重寫器還是優(yōu)化器來(lái)完成绰咽,因?yàn)閮蓚€(gè)進(jìn)程聯(lián)系很緊,必須看是什么數(shù)據(jù)庫(kù))地粪。
    重寫后的查詢接著送到優(yōu)化器取募。

查詢優(yōu)化器

現(xiàn)在語(yǔ)法樹(shù)被認(rèn)為合法的了,并且由優(yōu)化器將其轉(zhuǎn)化為執(zhí)行計(jì)劃蟆技。一條查詢可以由很多種執(zhí)行方式玩敏,最后都返回相同的結(jié)果。優(yōu)化器的作用就是找到這其中最好的執(zhí)行計(jì)劃质礼。</br>

MySQL使用的是“選取-投影-聯(lián)接”策略進(jìn)行查詢旺聚。用一個(gè)例子就可以理解: select uid,name from user where gender = 1;

  1. 這個(gè)select 查詢先根據(jù)where 語(yǔ)句進(jìn)行選取,而不是先將表全部查詢出來(lái)以后再進(jìn)行g(shù)ender過(guò)濾
  2. 這個(gè)select查詢先根據(jù)uid和name進(jìn)行屬性投影眶蕉,而不是將屬性全部取出以后再進(jìn)行過(guò)濾
  3. 將這兩個(gè)查詢條件聯(lián)接起來(lái)生成最終查詢結(jié)果.

MySQL使用基于成本(CBO)的優(yōu)化器砰粹,它將嘗試預(yù)測(cè)一個(gè)查詢使用某種執(zhí)行計(jì)劃的成本,并選擇其中成本最小的一個(gè)造挽。最早的時(shí)候碱璃,成本的最小單位是隨機(jī)讀取一個(gè)4K數(shù)據(jù)頁(yè)的成本弄痹,后來(lái)成本計(jì)算公式變得更加復(fù)雜,并且引入了一些“因子”來(lái)估算某些操作的代價(jià)厘贼,如當(dāng)執(zhí)行一次where條件比較的成本界酒。可以通過(guò)查詢當(dāng)前會(huì)話的last_query_cost的值來(lái)得知MySQL計(jì)算的當(dāng)前查詢的成本嘴秸。

問(wèn)題

  1. 緩存是內(nèi)存還是硬盤(內(nèi)存中)
  2. select->update->select時(shí)候毁欣,update如何通知緩存(發(fā)生更改,緩存立刻失效岳掐,寫入會(huì)導(dǎo)致緩存頻繁失效凭疮,降低效率)

資料

MySQL查詢語(yǔ)句執(zhí)行的過(guò)程
MySQL性能優(yōu)化——易實(shí)現(xiàn)的MySQL優(yōu)化方案匯總
MySQL優(yōu)化原理

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市串述,隨后出現(xiàn)的幾起案子执解,更是在濱河造成了極大的恐慌,老刑警劉巖纲酗,帶你破解...
    沈念sama閱讀 218,607評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件衰腌,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡觅赊,警方通過(guò)查閱死者的電腦和手機(jī)右蕊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)吮螺,“玉大人饶囚,你說(shuō)我怎么就攤上這事○梗” “怎么了萝风?”我有些...
    開(kāi)封第一講書人閱讀 164,960評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)紫岩。 經(jīng)常有香客問(wèn)我规惰,道長(zhǎng),這世上最難降的妖魔是什么泉蝌? 我笑而不...
    開(kāi)封第一講書人閱讀 58,750評(píng)論 1 294
  • 正文 為了忘掉前任歇万,我火速辦了婚禮,結(jié)果婚禮上梨与,老公的妹妹穿的比我還像新娘堕花。我一直安慰自己文狱,他們只是感情好粥鞋,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,764評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著瞄崇,像睡著了一般呻粹。 火紅的嫁衣襯著肌膚如雪壕曼。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 51,604評(píng)論 1 305
  • 那天等浊,我揣著相機(jī)與錄音腮郊,去河邊找鬼。 笑死筹燕,一個(gè)胖子當(dāng)著我的面吹牛轧飞,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播撒踪,決...
    沈念sama閱讀 40,347評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼过咬,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了制妄?” 一聲冷哼從身側(cè)響起掸绞,我...
    開(kāi)封第一講書人閱讀 39,253評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎耕捞,沒(méi)想到半個(gè)月后衔掸,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,702評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡俺抽,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,893評(píng)論 3 336
  • 正文 我和宋清朗相戀三年敞映,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片凌埂。...
    茶點(diǎn)故事閱讀 40,015評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡驱显,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出瞳抓,到底是詐尸還是另有隱情埃疫,我是刑警寧澤,帶...
    沈念sama閱讀 35,734評(píng)論 5 346
  • 正文 年R本政府宣布孩哑,位于F島的核電站栓霜,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏横蜒。R本人自食惡果不足惜胳蛮,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,352評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望丛晌。 院中可真熱鬧仅炊,春花似錦、人聲如沸澎蛛。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,934評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至呆馁,卻和暖如春桐经,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背浙滤。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,052評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工阴挣, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人纺腊。 一個(gè)月前我還...
    沈念sama閱讀 48,216評(píng)論 3 371
  • 正文 我出身青樓畔咧,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親揖膜。 傳聞我的和親對(duì)象是個(gè)殘疾皇子盒卸,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,969評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容