MySQL 語句執行過程詳解

MySQL 原理篇html

MySQL 索引機制mysql

MySQL 體系結構及存儲引擎linux

MySQL 語句執行過程詳解sql

MySQL 執行計劃詳解數據庫

MySQL InnoDB 緩衝池緩存

MySQL InnoDB 事務服務器

MySQL InnoDB 鎖併發

MySQL InnoDB MVCCapp

MySQL InnoDB 實現高併發原理函數

MySQL InnoDB 快照讀在RR和RC下有何差別

當客戶端向 MySQL 發送一個請求的時候,MySQL 的執行過程以下圖所示:

MySQL 客戶端/服務端通訊

通訊機制

MySQL 客戶端與服務端的通訊方式是 「 半雙工 」。

  • 全雙工:雙向通訊,發送同時也能夠接收
  • 半雙工:雙向通訊,同時只能接收或者是發送,沒法同時作操做
  • 單工:只能單一方向傳送

一旦一端開始發送消息,另外一端要接收完整個消息才能響應它,因此咱們沒法也無須將一個消息切成小塊獨立發送,也沒有辦法進行流量控制。

客戶端用一個單獨的數據包將查詢請求發送給服務器,因此當查詢語句很長的時候,須要設置 max_allowed_packet 參數。

可是須要注意的是,若是查詢實在是太大,服務端會拒絕接收更多數據並拋出異常。

與之相反的是,服務器響應給用戶的數據一般會不少,由多個數據包組成。可是當服務器響應客戶端請求時,客戶端必須完整的接收整個返回結果,而不能簡單的只取前面幾條結果,而後讓服務器中止發送。

於是在實際開發中,儘可能保持查詢簡單且只返回必需的數據,減少通訊間數據包的大小和數量是一個很是好的習慣,這也是查詢中儘可能避免使用 SELECT * 以及加上 LIMIT 限制的緣由之一。

鏈接狀態

對於一個 MySQL 的鏈接,或者說一個線程,時刻都有一個狀態來標識這個鏈接正在作什麼。

能夠經過以下命令來查看鏈接的狀態:

show full processlist
show processlist

詳細的狀態集描述參考官網:https://dev.mysql.com/doc/refman/5.7/en/general-thread-states.html

這裏簡單介紹幾個經常使用的鏈接狀態:

  • Sleep:線程正在等待客戶端發送數據
  • Query:鏈接線程正在執行查詢
  • Locked:線程正在等待表鎖的釋放
  • Sorting result:線程正在對結果進行排序
  • Sending data:向請求端返回數據

對於出現問題的鏈接能夠經過 kill {id} 的方式進行殺掉。

查詢緩存

工做原理:

  • 緩存 SELECT 操做的結果集和 SQL 語句。
  • 新的 SELECT 語句,先去查詢緩存,判斷是否存在可用的記錄集,須要注意的是在判斷的時候,要求 SQL 語句徹底同樣(SQL 兩端容許存在空格)纔會匹配到緩存數據。

緩存參數

MySQL 的緩存參數在配置文件中設置,能夠經過以下命令來查看緩存的參數:

show variables like 'query_cache%'

  1. query_cache_type
    1. 0:不啓用查詢緩存,默認值
    2. 1:啓用查詢緩存,只要符合查詢緩存的要求,客戶端的查詢語句和記錄集均可以緩存起來,供其餘客戶端使用,SQL 語句中加上 SQL_NO_CACHE 將不緩存
    3. 2:啓用查詢緩存,只要查詢語句中添加了參數:SQL_CACHE,且符合查詢緩存的要求,客戶端的查詢語句和記錄集,則能夠緩存起來,供其餘客戶端使用
  1. query_cache_size
    1. 總的緩存池的大小,容許設置 query_cache_size 的值最小爲40K,默認1M,推薦設置爲64M/128M
    2. 當總的緩存池大小超過設置的值時,會按照時間順序,讓最老的緩存失效
  1. query_cache_limit
    1. 指定單個查詢可以使用的緩衝區大小,默認設置爲1M

緩存執行狀況

能夠經過以下命令來查看緩存狀況:

show status like 'Qcache%'

  1. Qcache_free_blocks
    1. Query Cache 中目前還有多少剩餘的 blocks。若是該值顯示較大,則說明 Query Cache 中的內存碎片較多了,可能須要尋找合適的機會進行整理
  1. Qcache_free_memory
    1. Query Cache 中目前剩餘的內存大小。經過這個參數咱們能夠較爲準確的觀察出當前系統中的Query Cache 內存大小是否足夠,是須要增長仍是過多了
  1. Qcache_hits
    1. 緩存命中次數。經過這個參數咱們能夠查看到 Query Cache 的基本效果
  1. Qcache_inserts
    1. 插入緩存的記錄數,經過 Qcache_hits 和 Qcache_inserts 兩個參數咱們就能夠算出 Query Cache 的命中率,Query Cache 命中率 = Qcache_hits / ( Qcache_hits + Qcache_inserts )
  1. Qcache_lowmem_prunes
    1. 多少條 Query 由於內存不足而被清除出 Query Cache。經過 Qcache_lowmem_prunes 和 Qcache_free_memory 相互結合,可以更清楚的瞭解到咱們系統中 Query Cache 的內存大小是否真的足夠,是否常常出現由於內存不足而有 Query 被清除
  1. Qcache_not_cached
    1. 由於 query_cache_type 的設置或者不能被 cache 的 Query 的數量
  1. Qcache_queries_in_cache
    1. 當前 Query Cache 中 cache 的 Query 數量
  1. Qcache_total_blocks
    1. 當前 Query Cache 中的 block 數量

不會緩存的狀況

  1. 當查詢語句中設置了 SQL_NO_CACHE,則不會被緩存。
  2. 當查詢語句中有一些不肯定的數據時,則不會被緩存。如包含函數 NOW() ,CURRENT_DATE() 等相似的函數,或者用戶自定義的函數,存儲函數,用戶變量等都不會被緩存。
  3. 當查詢的結果大於 query_cache_limit 設置的值時,結果不會被緩存。
  4. 對於 InnoDB 引擎來講,當一個語句在事務中修改了某個表,那麼在這個事務提交以前,全部與這個表相關的查詢都沒法被緩存。所以長時間執行事務,會大大下降緩存命中率。
  5. 查詢的表是系統表。
  6. 查詢語句不涉及到表。

緩存有哪些坑?

  1. 在查詢以前必須先檢查是否命中緩存,浪費計算資源。
  1. 若是這個查詢能夠被緩存,那麼執行完成後,MySQL 發現查詢緩存中沒有這個查詢,則會將結果存入查詢緩存,這會帶來額外的系統消耗。
  1. 針對表進行寫入或更新數據時,將對應表的全部緩存都設置失效。
  1. 若是查詢緩存很大或者碎片不少時,這個操做可能帶來很大的系統消耗。

適用場景

以讀爲主的業務,數據生成 以後就不常改變的業務,好比門戶類、新聞類、報表類、論壇類。

查詢優化處理

查詢優化處理的三個階段

  1. 解析 SQL
    1. 經過 lex 語法分析,yacc 語法分析將 SQL 語句解析成解析樹。
    2. lex、yacc 語法參考:https://www.ibm.com/developerworks/cn/linux/sdk/lex/
  1. 預處理階段
    1. 根據 MySQL 的語法的規則進一步檢查解析樹的合法性,如:檢查數據的表和列是否存在,解析名字和別名的設置。還會進行權限的驗證
  1. 查詢優化器
    1. 優化器的主要做用就是找到最優的執行計劃

查詢優化器如何找到最優執行計劃

這裏介紹幾種優化方式,更多的能夠參考《高性能MySQL_第3版(中文)》

  1. 使用等價變化規則
    1. 5 = 5 and a > 5 改寫成 a > 5
    2. a < b and a = 5 改寫成 b > 5 and a = 5
    3. 基於聯合索引,調整條件位置等
  1. 優化 count、min、max 等函數
    1. InnoDB 引擎 min 函數只需找索引最左邊
    2. InnoDB 引擎 max 函數只需找索引最右邊
    3. MyISAM 引擎 count(*),不須要計算,直接返回
  1. 覆蓋索引掃描
  1. 子查詢優化
    1. select * from (select * from user where id = 1) as t;,會被優化成一級查詢
  1. 提早終止查詢
    1. 用了 limit 關鍵字或者使用不存在的條件,獲取到 limit 所須要的數據後,就再也不遍歷接下來的數據
  1. IN 的優化
    1. MySQL 對於 IN 的查詢,會先進性排序,再採用二分查找的方式查找數據
    2. 好比表中的數據是 1,2,3,4,5,where 條件是 id IN(2,1,3),在進行 IN 操做的時候,會先對 IN 中的數據排序,變成 1,2,3,而後取出一條數據1先和2比較,1<2,則往2的左邊查找,進而找到1,接下來就是再獲取一條數據重複上面的查找步驟。
    3. 其餘關係型數據庫不會採用二分查找的方式,而是和 or 的方式同樣,where id=1 or id=2 or id=3,從表中獲取一條數據和 where 條件中的 or 的數據一個一個比對。

MySQL 的查詢優化器是基於成本計算的原則,它會嘗試各類執行計劃,數據抽樣的方式進行試驗(隨機的讀取一個 4K 的數據塊進行分析)。

執行計劃

這塊內容比較多,後面會單獨提供一篇文章描述

查詢執行引擎

調用插件式的存儲引擎的原子 API 進行執行計劃的執行。

返回客戶端

  1. 有須要作緩存的,執行緩存操做
  2. 增量的返回執行結果,開始生成第一條結果時,MySQL 就開始往請求方逐步返回數據,這樣作的好處是 MySQL 服務器無須保存過多的數據,浪費內存,用戶體驗好,立刻就拿到了數據

參考

http://www.sohu.com/a/233335431_468739

相關文章
相關標籤/搜索