mysql查询过程从客户端发送查询请求_MySQL查询过程和高级查询
最近有個需求,要修改現有存儲結構,涉及查詢條件和查詢效率的考量,看了幾篇索引和HBase相關的文章,回憶了相關知識,結合項目需求,說說自己的理解和總結。
總體目錄如下,上篇介紹了前3小節,分析了索引為什么快,總結了它的優點和分類,以及索引的演化過程,中篇會重點介紹索引分析方法和常見索引優化:
為什么需要索引
索引的類別
MySQL索引演化
MySQL索引優化
HBase介紹
HBase存儲結構
HBase索引介紹
業務需求及設計
部分內容摘錄了幾個博友的文章,最后會給出文章鏈接,感謝他們的精彩分析。
通過中篇的介紹,你會了解到:
MySQL查詢過程
高級查詢相關概念
explain命令詳細介紹
索引優化建議
MySQL查詢過程
想要更好的優化查詢,首先要了解其整體查詢過程,從客戶端發送查詢請求,到接收到查詢結果,MySQL服務器做了很多工作。
邏輯架構
MySQL邏輯架構整體分為三層,分別為客戶端層、核心服務層、存儲引擎層,共同協作完成。
最上層為客戶端層,比如:連接處理、授權認證、安全等功能等。
中間層是MySQL的核心服務,包括查詢解析、分析、優化、緩存、內置函數(比如:時間、數學、加密等),另外,所有的跨存儲引擎的功能也在這一層實現:存儲過程、觸發器、視圖等。
最下層為存儲引擎,負責數據存儲和提取,中間的服務層通過API與存儲引擎通信,這些API接口屏蔽了不同存儲引擎間的差異。
具體執行過程
重點看下MySQL是如何優化和執行查詢的,很多的查詢優化工作就是遵循一些原則讓MySQL的優化器能夠按照預想的方式運行而已。
先說下總體流程:
客戶端發送一條查詢SQL給服務器;
服務器先檢查查詢緩存,如果命中了緩存,則立即返回存儲在緩存中的結果;
服務器端進行SQL解析、預處理,再由優化器生成對應的執行計劃;
查詢執行引擎根據優化器生成的執行計劃,調用存儲引擎的API來執行查詢;
將結果返回給客戶端;
1.客戶端/服務端通信協議
MySQL客戶端和服務器之間的通信協議是「半雙工」:在任何一個時刻,要么由服務器向客戶端發送數據,要么由客戶端向服務器發送數據,不能同時發生,這也就意味著沒法進行流量控制。
客戶端用一個單獨的數據包將查詢請求發送給服務器,服務器響應給用戶的數據通常會很多,由多個數據包組成,需要注意的是當服務器響應客戶端請求時,客戶端必須完整的接收整個返回結果,而不能簡單的只取前面幾條結果,然后讓服務器停止發送。
2.查詢緩存
如果查詢緩存是打開的,會檢查這個查詢語句是否命中查詢緩存中的數據,如果命中,在檢查一次用戶權限后直接返回緩存中的結果。
查詢緩存系統會跟蹤查詢中涉及的每個表,在任何的寫操作時,MySQL必須將對應表的所有緩存都設置為失效,如果查詢緩存非常大或者碎片很多,這個操作就可能帶來很大的系統消耗。
另外,任何的查詢語句在開始之前都必須經過檢查,即使這條SQL語句永遠不會命中緩存,如果查詢結果可以被緩存,那么執行完成后,會將結果存入緩存,也會帶來額外的系統消耗。
所以,打開緩存要慎重,只有當緩存帶來的資源節約大于其本身消耗的資源時,才會給系統帶來性能提升,可以將query_cache_type設置為DEMAND,這時只有加入SQL_CACHE的查詢才會走緩存,其他查詢則不會。
3.語法解析和預處理
通過關鍵字將SQL語句進行解析,生成一顆解析樹,預處理則會根據MySQL規則進一步檢查解析樹是否合法。
4.查詢優化
一條查詢可以有很多種執行方式,優化器的作用就是找到這其中最好的執行計劃,MySQL使用基于成本的優化器,它嘗試預測一個查詢使用某種執行計劃時的成本,并選擇其中成本最小的一個。
5.查詢執行引擎
存儲引擎接口提供了非常豐富的功能,但其底層僅有幾十個接口,這些接口像搭積木一樣完成了一次查詢的大部分操作。
6.返回結果給客戶端
結果集返回客戶端是一個增量且逐步返回的過程,這樣服務端就無須存儲太多結果而消耗過多內存,也可以讓客戶端第一時間獲得返回結果。
SELECT執行順序
下面來看看SQL查詢語句的執行順序,每一步都會生成一個虛擬臨時表,作為下一步的輸入。
標準的SQL語法如下:
SELECT?DISTINCT? ?< select_list >FROM? ?< left_table > < join_type >JOIN?< right_table >?ON?< join_condition >WHERE? ?< where_condition >GROUP?BY? ?< group_by_list >HAVING? ?< having_condition >ORDER?BY? ?< order_by_condition >LIMIT?< limit_number >
但執行順序是這樣的:
FROM? ON??JOIN?WHERE? GROUP BY? HAVING? SELECT?DISTINCT?? ORDER?BY?? LIMIT??
1.FROM
當涉及多個表的時候,左邊表的輸出會作為右邊表的輸入,之后會生成一個虛擬表VT1:
計算兩個相關聯表的笛卡爾積(CROSS JOIN) ,生成虛擬表VT1-J1;
基于虛擬表VT1-J1進行過濾,過濾出所有滿足ON謂詞條件的行,生成虛擬表VT1-J2;
如果使用了外連接(LEFT,RIGHT,FULL),主表(保留表)中的不符合ON條件的列也會被加入到VT1-J2中,生成虛擬表VT1-J3;
2.WHERE
對VT1過程中生成的臨時表進行過濾,滿足WHERE子句的列被插入到VT2表中:
與ON的區別:如果有外連接,ON針對過濾的是關聯表,主表會返回所有的列,如果沒有外連接,效果相同;
對主表的過濾應該放在WHERE;
于關聯表,先條件查詢后連接則用ON,先連接后條件查詢則用WHERE;
3.GROUP BY
這個子句會把VT2中生成的表按照GROUP BY中的列進行分組,生成VT3表。
其后處理過程的語句,如SELECT,HAVING,所用到的列必須包含在GROUP BY中,對于沒有出現的,得用聚合函數;
4.HAVING
對VT3表中的不同的組進行過濾,只用于分組后的數據,滿足HAVING條件的子句被加入到VT4表中。
5.SELECT
這個子句對SELECT子句中的元素進行處理,生成VT5表:
計算SELECT子句中的表達式,生成VT5-J1;
DISTINCT:尋找重復列,并刪掉,會創建一張內存臨時表VT5-J2,和虛擬表VT5-J1一樣,不同的是對DISTINCT的列增加唯一索引,以此來除重復數據;
6.ORDER BY
從VT5-J2中的表中,根據ORDER BY 子句的條件對結果進行排序,生成VT6表,這是唯一可使用SELECT中別名的地方。
7.LIMIT
從上一步得到的VT6虛擬表中選出從指定位置開始的指定行數據。
高級查詢相關概念
本小節介紹下常用的高級查詢概念。
連接查詢
將多張表按照某個指定的條件進行數據拼接,SQL中將連接查詢分成四類: 內連接、外連接、自然連接、交叉連接,其中自然連接和交叉連接很少用到,就不過多介紹了。
1.內連接 inner join
從左表中取出每一條記錄,分別與右表中所有的記錄進行匹配,匹配必須左表和右表中都滿足條件,匹配的會保留結果,否則不保留。
2.外連接 left/right join
外連接分為兩種:
left join: 左外連接(左連接),以左表為主表;
right join: 右外連接(右連接),以右表為主表;
以某張表為主,取出里面的所有記錄,不管能不能匹配上條件,主表最終都會保留,然后與另外一張表進行連接,如果不能匹配,其他表的字段都置空NULL。
子查詢
是在某個查詢結果之上再進行查詢,也就是一條select語句內部包含了另外一條select語句。
按子查詢所在位置,可以劃分為:
From子查詢:子查詢跟在from之后;
Where子查詢: 子查詢出where條件中;
exists子查詢: 子查詢出現在exists里面;
下面舉幾個例子:
查找部門名稱前綴為「小米」的所有員工:
SELECT?name?, sex , ?sal? ? ??FROM?emp? ? ??WHERE?no?in?(?? ? ? ? ??SELECT?no?FROM?dept?? ? ? ? ? ? ??WHERE?name?LIKE?'小米%'? ? ? );
查看所有員工的薪水,并按薪水排序:
SELECT?name?, sal? ? ??FROM?(? ? ? ? ??SELECT?name?, sal?? ? ? ? ? ? ?FROM?emp?ORDER?BY?sal? ? ? );
聯合查詢
將多次查詢, 將結果進行拼接,字段不會增加,每一條select語句獲取的字段數必須嚴格一致。
語法如下:
Select?語句1Union?[union選項]Select語句2...
Union選項:
All: 保留所有;
Distinct: 去重,默認選項;
又寫多了,再加一篇吧,中篇未完待續。。。
參考文章:
MySQL優化原理
步步深入:SQL解析順序
END
如果讀完覺得有收獲的話,歡迎點贊、關注、加公眾號【匠心零度】,查閱更多精彩歷史!!!
總結
以上是生活随笔為你收集整理的mysql查询过程从客户端发送查询请求_MySQL查询过程和高级查询的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python库的使用手册_Python
- 下一篇: android勾选控件_Android中