============================================
MySQL學習筆記【第二部分】
============================================
一. MySQL查詢優化
1.查詢執行路徑
1.mysql客戶端/服務端通信
Mysql客戶端與服務端的通信方式是“半雙工”;
半雙工通信:在任何一個時刻,要麼是有服務器向客戶端發送數據,要麼是客戶端向服務端發送數據,這兩個動作不能同時發生。所以我們無法也無需將一個消息切成小塊進行傳輸
特點和限制:
-
客戶端一旦開始發送消息,另一端要接收完整個消息才能響應。
-
客戶端一旦開始接收數據沒法停下來發送指令。
查詢狀態:
對於一個mysql連接,或者說一個線程,時刻都有一個狀態來標識這個連接正在做什麼,查看命令showfullprocesslist/showprocesslist -
Sleep線程正在等待客戶端發送數據
-
Query連接線程正在執行查詢
-
Locked線程正在等待表鎖的釋放
-
Sortingresult線程正在對結果進行排序
-
Sendingdata向請求端返回數據
可通過kill{id}的方式進行連接的殺掉
2.查詢緩存
工作原理:緩存SELECT操作的結果集和SQL語句;新的SELECT語句,先去查詢緩存,判斷是否存在可用的記錄集;
判斷標準:與緩存的SQL語句,是否完全一樣,區分大小寫(簡單認爲存儲了一個key-value結構,key爲sql,value爲sql查詢結果集
query_cache_type值:0-–不啓用查詢緩存,默認值;
值:1-–啓用查詢緩存,只要符合查詢緩存的要求,客戶端的查詢語句和記錄集都可以緩存起來,供其他客戶端使用,加上SQL_NO_CACHE將不緩存
值:2-–啓用查詢緩存,只要查詢語句中添加了參數:SQL_CACHE,且符合查詢緩存的要求,客戶端的查詢語句和記錄集,則可以緩存起來,供其他客戶端使用
query_cache_size:允許設置query_cache_size的值最小爲40K,默認1M,推薦設置爲:64M/128M;
query_cache_limit:限制查詢緩存區最大能緩存的查詢記錄集,默認設置爲1Mshowstatuslike’Qcache%'命令可查看緩存情況
showstatuslike’Qcache%'命令可查看緩存情況
查詢緩存不會緩存的情況
- 當查詢語句中有一些不確定的數據時,則不會被緩存。如包含函數NOW(),CURRENT_DATE()等類似的函數,或者用戶自定義的函數,存儲函數,用戶變量等都不會被緩存
- 當查詢的結果大於query_cache_limit設置的值時,結果不會被緩存
- 對於InnoDB引擎來說,當一個語句在事務中修改了某個表,那麼在這個事務提交之前,所有與這個表相關的查詢都無法被緩存。因此長時間執行事務,會大大降低緩存命中率
- 查詢的表是系統表
- 查詢語句不涉及到表
爲什麼mysql默認關閉了緩存開啓?
- 在查詢之前必須先檢查是否命中緩存,浪費計算資源
- 如果這個查詢可以被緩存,那麼執行完成後,MySQL發現查詢緩存中沒有這個查詢,則會將結果存入查詢緩存,這會帶來額外的系統消耗
- 針對表進行寫入或更新數據時,將對應表的所有緩存都設置失效。
- 如果查詢緩存很大或者碎片很多時,這個操作可能帶來很大的系統消耗
適用業務場景:
以讀爲主的業務,數據生成之後就不常改變的業務比如門戶類、新聞類、報表類、論壇類等
3.查詢優化處理
查詢優化處理的三個階段
- 解析SQL【通過lex詞法分析,yacc語法分析將sql語句解析成解析樹】
- 預處理階段 【根據mysql的語法的規則進一步檢查解析樹的合法性,如:檢查數據的表和列是否存在,解析名字和別名的設置。還會進行權限的驗證】
- 查詢優化器【優化器的主要作用就是找到最優的執行計劃】
查詢優化器如何找到最優執行計劃
Mysql的查詢優化器是基於成本計算的原則。他會嘗試各種執行計劃。數據抽樣的方式進行試驗(隨機的讀取一個4K的數據塊進行分析)
- 使用等價變化規則:5=5anda>5改寫成a>5a<banda=5改寫成b>5anda=5基於聯合索引,調整條件位置等
- 優化count、min、max等函數:min函數只需找索引最左邊max函數只需找索引最右邊myisam引擎count(*)
- 覆蓋索引掃描
- 子查詢優化
- 提前終止查詢:用了limit關鍵字或者使用不存在的條件
- IN的優化:先進性排序,再採用二分查找的方式
還有很多優化,這裏則不一一列舉了,有興趣的可以私信我要一份超詳細的資料
執行計劃詳解
1.id
select查詢的序列號,標識執行的順序
1、id相同,執行順序由上至下
2、id不同,如果是子查詢,id的序號會遞增,id值越大優先級越高,越先被執行
3、id相同又不同即兩種情況同時存在,id如果相同,可以認爲是一組,從上往下順序執行;在所有組中,id值越大,優先級越高,越先執行
2.select_type
查詢的類型,主要是用於區分普通查詢、聯合查詢、子查詢等
- SIMPLE:簡單的select查詢,查詢中不包含子查詢或者union
- PRIMARY:查詢中包含子部分,最外層查詢則被標記爲primary
- SUBQUERY/MATERIALIZED:SUBQUERY表示在select或where列表中包含了子查詢
MATERIALIZED表示where後面in條件的子查詢
- UNION:若第二個select出現在union之後,則被標記爲union;
- UNIONRESULT:從union表獲取結果的select
3.table
查詢涉及到的表
直接顯示錶名或者表的別名
<unionM,N>由ID爲M,N查詢union產生的結果
由ID爲N查詢生產的結果
4.type
訪問類型,sql查詢優化中一個很重要的指標,結果值從好到壞依次是:system>const>eq_ref>ref>range>index>ALL
- system:表只有一行記錄(等於系統表),const類型的特例,基本不會出現,可以忽略不計
- const:表示通過索引一次就找到了,const用於比較primarykey或者unique索引
- eq_ref:唯一索引掃描,對於每個索引鍵,表中只有一條記錄與之匹配。常見於主鍵或唯一索引掃描
- ref:非唯一性索引掃描,返回匹配某個單獨值的所有行,本質是也是一種索引訪問
- range:只檢索給定範圍的行,使用一個索引來選擇行
- index:FullIndexScan,索引全表掃描,把索引從頭到尾掃一遍
- ALL:FullTableScan,遍歷全表以找到匹配的行
5.Extra
- Usingfilesort:mysql對數據使用一個外部的文件內容進行了排序,而不是按照表內的索引進行排序讀取
- Usingtemporary:使用臨時表保存中間結果,也就是說mysql在對查詢結果排序時使用了臨時表,常見於orderby或groupby
- Usingindex:表示相應的select操作中使用了覆蓋索引(CoveringIndex),避免了訪問表的數據行,效率高
- Usingwhere:使用了where過濾條件
- selecttablesoptimizedaway:基於索引優化MIN/MAX操作或者MyISAM存儲引擎優化COUNT(*)操作,不必等到執行階段在進行計算,查詢執行計劃生成的階段即可完成優化
6.possible_keys
查詢過程中有可能用到的索引
7.key
實際使用的索引,如果爲NULL,則沒有使用索引
8.rows
根據表統計信息或者索引選用情況,大致估算出找到所需的記錄所需要讀取的行數
9.filtered
它指返回結果的行佔需要讀到的行(rows列的值)的百分比表示返回結果的行數佔需讀取行數的百分比,filtered的值越大越好
4.查詢執行引擎
調用插件式的存儲引擎的原子API的功能進行執行計劃的執行
5.返回客戶端
1、有需要做緩存的,執行緩存操作
2、增量的返回結果:
開始生成第一條結果時,mysql就開始往請求方逐步返回數據好處:mysql服務器無須保存過多的數據,浪費內存用戶體驗好,馬上就拿到了數據
二. MySQL慢查詢定位
1. 如何定位慢SQL
- 業務驅動
- 測試驅動
- 慢查詢日誌
下面主要針對慢查詢日誌進行學習
2. 慢查詢日誌配置
showvariableslike'slow_query_log'
setglobalslow_query_log=on
setglobalslow_query_log_file='/var/lib/mysql/gupaoedu-slow.log'
setgloballog_queries_not_using_indexes=on
setgloballong_query_time=0.1(秒
3. 慢查詢日誌分析
4. 慢查詢日誌分析工具
mysqldumpslow-t10-sat/var/lib/mysql/gupaoedu-slow.log
注:如果有需要這模塊資料的請私信聯繫我發給你