面試官說道,小夥子耗子尾汁,查詢SQL的執行流程難道都不知道嗎?

前言

最近朋友小王正在找工做,而後有一個面試官問他知不知道 「查詢SQL具體的執行流程」

小王說不知道呀,而後面試官直接對小王說:小夥子 耗子尾汁(好自爲之) ,怎麼連這麼簡單的都不知道呢?html

小王聽後脫口而出:哼!面試官你 不講武德 ,不按套路出牌呀,你應該問問索引相關的知識呀,這個我倍清楚。java

在聽完小王描述後,本身也在腦海中搜了搜這個知識點,可憐的是個人知識庫裏也沒找到相關內容,而後就去面壁思過了,隨後本文就誕生了。

注意 :本文主要以 MySql 爲例;說到了MySql了,而後再嘮叨下如今使用十分廣泛的MySql的姊妹數據庫 MariaDBmysql

MariaDB 是個什麼東東呢?

MySql被Oracle收購後,MySql的創始人擔憂MySql數據庫發展的將來(開發緩慢、封閉、可能會被閉源),因而建立了一個分支MariaDB,默認使用全新的Maria存儲引擎,它是原來Mysql中的 MyISAM 存儲引擎的升級版。面試

本文主線:

①、MySql的總體架構描述;sql

②、Server層各節點描述;數據庫

③、InnoDB存儲引擎描述;apache

MySql架構描述

咱啥也先不說,先貼上一張摘抄自網上的大圖:

上面這張圖描述的清不清晰呢?不清晰,那彆着急,咱再貼一張:

Server服務層描述:

經過上面的架構圖能夠得知,Server層中主要由 鏈接器、查詢緩存、解析器/分析器、優化器、執行器 幾部分組成的,下面將主要描述下這幾部分。

鏈接器

客戶端想要對數據庫進行操做時,前提是與數據庫創建好鏈接;而鏈接器就是用來負責跟客戶端創建鏈接、獲取權限、維持和管理鏈接的。

鏈接方式:

MySQL既支持短鏈接,也支持長鏈接。短鏈接就是操做完畢後,立刻close關掉。緩存

長鏈接能夠保持打開,減小服務端建立和釋放鏈接的消耗,後面的程序訪問的時候還可使用這個鏈接。 通常咱們會在鏈接池中使用長鏈接。服務器

長鏈接使用時的注意事項:

客戶端與服務器創建長鏈接,默認有效時間是 8小時 ,超過8小時MySql服務器就會將鏈接斷開了,那麼客戶端再次請求的話,就會報 鏈接已斷開的問題架構

而且保持長鏈接會消耗內存。長時間不活動的鏈接,MySQL服務器會斷開。那這個8小時的超時時間怎麼查看呢?

-- 非交互式超時時間,如 JDBC 程序
show global variables like 'wait_timeout';  

-- 交互式超時時間,如數據庫工具
show global variables like' interactive_timeout';

執行後獲得下圖結果:默認都是28800秒,8小時 。

通常項目中使用的鏈接池中的鏈接都是長鏈接的;(例如:druid、c3p0、dbcp等)

舉個例子,說明下長鏈接超時斷開致使的實際問題:

某個朋友的公司有個管理系統,這個系統使用的時Mysql,可是他最近遇到了一個問題:就是系統明明前天是好用的,可是次日去到公司後就打不開了,只要將系統重啓就行了,一時間不知道什麼緣由,什麼鬼嘛,苦惱?

最後經過查看日誌才發現是鏈接池中的鏈接都斷開了,由於從前天到次日上班這之間隔得時間超過了8小時了。
唉,這麼個小知識點致使好幾天的困惑,實在不應呀,仍是知識掌握的不全面呀。

好了,如今也找到問題緣由了,可是它該怎麼解決呢?

長鏈接超時斷開的解決方案:

①、按期斷開長鏈接。使用一段時間,或者程序裏面判斷執行過一個佔用內存的大查詢後,斷開鏈接,以後要查詢再重連。

②、若是你用的是 MySQL 5.7 或更新版本,能夠在每次執行一個比較大的操做後,經過執行 mysql_reset_connection 來從新初始化鏈接資源。這個過程不須要重連和從新作權限驗證,可是會將鏈接恢復到剛剛建立完時的狀態。

查詢緩存

MySQL緩存是默認關閉的,也就是說不推薦使用緩存,爲何呢?

MySql爲何默認不開啓緩存呢?

主要是因爲它的使用場景限制的:

①、先說下緩存中數據存儲格式:key(sql語句)-value(數據值);因此若是SQL語句(key)只要存在一點不一樣之處就會直接進行數據庫查詢了;

②、因爲表中的數據不是一成不變的,大多數是常常變化的,而當數據庫中的數據變化了,那麼相應的與此表相關的緩存數據就須要移除掉;

須要注意的是, MySQL 8.0 版本直接將查詢緩存的整塊功能刪掉了,也就是說8.0開始完全沒有這個功能了。

分析器

分析器的工做主要是對要執行的SQL語句進行解析,最終獲得抽象語法書,而後再使用預處理器判斷抽象語法樹中的表是否存在,若是存在的話,在接着判斷select投影列字段是否在表中存在等。

詞法分析

詞法分析用於將SQL拆解爲不可再分的原子符號,稱爲Token。並根據不一樣數據庫方言所提供的字典,將其歸類爲關鍵字,表達式,字面量和操做符。

語法分析

語法分析就是根據詞法分析拆解出來的Token(原子符號)將SQL語句轉換爲抽象語法樹。下面就直接舉例說明,看一個SQL它的抽象語法書到底長神魔樣:

SQL語句:

SELECT id, name FROM t_user WHERE status = 'ACTIVE' AND age > 18

而後上面的SQL語句通過詞法分析、語法分析後獲得的抽象語法書以下:

圖片摘自:https://shardingsphere.apache...

注意,爲了便於理解,抽象語法樹中的關鍵字的Token用綠色表示,變量的Token用紅色表示,灰色表示須要進一步拆分。

預處理器

預處理是用來對生成的 抽象語法樹 進行語義校驗,語義校驗就是對查詢的表、select投影列字段進行校驗,判斷表、字段是否存在等;

優化器

優化器的做用:
主要是將SQL通過詞法解析/語法解析後獲得的語法樹,經過MySQL的數據字典和統計信息的內容,通過 一系列運算 ,從而得出一個 執行計劃

在優化過程當中,通過的一系列運算是什麼呢?下面簡單說下:

①、邏輯變換:例如SQL的where條件中存在 8>9,那邏輯轉換就是將語法樹中存在的這種常量表達式直接進行化簡,化簡爲 false;除了化簡還有常量表達式計算等。

②、代價優化:就是經過付出一些數據統計分析的代價,來獲得這個SQL執行是否能夠走索引,以及走哪些索引;除此以外,在多表關聯查詢中,肯定最終表join的順序等;

在分析是否走索引查詢時,是經過進行 動態數據採樣統計分析 出來;只要是統計分析出來的,那就可能會存在分析錯誤的狀況,因此在SQL執行不走索引時,也要考慮到這方面的因素。

MySql執行計劃怎麼查看呢?

在執行的SQL語句前添加上 explain 關鍵字便可;

擴展: Oracle怎麼查看執行計劃? 參考此文章 Oracle經過執行計劃查看查詢語句是否使用索引

執行器

MySQL 經過分析器知道了你要作什麼,經過優化器知道了該怎麼作,因而就進入了執行器階段,開始執行語句。
開始執行的時候,要先判斷一下創建鏈接的對象對這個表有沒有執行操做的權限,若是沒有,就會返回沒有權限的錯誤;若是有,就按照生成的執行計劃進行執行。

經過文章最開始的架構圖可知,執行器下面鏈接的就是存儲引擎了,執行器就是經過調用存儲引擎提供的API接口進行調用操做數據的。

存儲引擎描述

存儲引擎是對底層物理數據執行實際操做的組件,爲Server服務器層提供各類操做數據的 API。MySQL 支持插件式的存儲引擎,包括 InnoDB 、MyISAM、Memory 等。通常狀況下,MySQL默認使用的存儲引擎是 InnoDB

InnoDB 存儲引擎支持的功能總覽

擴展

InnoDB存儲引擎深刻學習,啥也不說了,先貼上其總體架構圖:以下圖所示,InnoDB存儲引擎總體分爲內存架構(Memory Structures)和磁盤架構(Disk Structures)。

若是想深刻學習,請參考此文章 你竟然還不知道Mysql存儲引擎InnoDB分爲內存架構、磁盤架構?

❤ 關注 + 點贊 + 收藏 + 評論 喲

若是本文對您有幫助的話,請揮動下您愛發財的小手點下贊呀,您的支持就是我不斷創做的動力,謝謝!

您能夠VX搜索【木子雷】公衆號,堅持高質量原創java技術文章,值得您關注!

參考資料

①、查詢sql的執行過程及MySQL架構分析

②、執行SQL查詢語句時,其底層到底經歷了什麼?

相關文章
相關標籤/搜索