MySQL原理解析

邏輯架構mysql

MySQL邏輯架構總體分爲三層:sql

  1. 客戶端層,鏈接處理、受權認證、安全等功能均在這一層處理。 
  2. 核心服務層,包括查詢解析、分析、優化、緩存、內置函數(好比:時間、數學、加密等函數)。全部的跨存儲引擎的功能也在這一層實現:存儲過程、觸發器、視圖等。
  3.  存儲引擎,其負責MySQL中的數據存儲和提取。和Linux下的文件系統相似,每種存儲引擎都有其優點和劣勢。中間的服務層經過API與存儲引擎通訊,這些API接口屏蔽了不一樣存儲引擎間的差別

存儲引擎數據庫

主要介紹InnoDB引擎和MyISAM引擎緩存

InnoDB引擎:安全

  1. 將數據存儲在表空間中,表空間由一系列的數據文件組成,由InnoDB管理;
  2. 支持每一個表的數據和索引存放在單獨文件中(innodb_file_per_table);
  3. 支持事務,採用MVCC來控制併發,並實現標準的4個事務隔離級別,支持外鍵;
  4. 索引基於聚簇索引創建,對於主鍵查詢有較高性能;
  5. 數據文件的平臺無關性,支持數據在不一樣的架構平臺移植;
  6. 可以經過一些工具支持真正的熱備。如XtraBackup等;
  7. 內部進行自身優化如採起可預測性預讀,可以自動在內存中建立hash索引等。

MyISAM引擎:服務器

  1.    不支持事務和行級鎖;
  2.    提供大量特性如全文索引、空間函數、壓縮、延遲更新等;
  3.    數據庫故障後,安全恢復性差;
  4.    對於只讀數據能夠忍受故障恢復,MyISAM依然很是適用;
  5.   日誌服務器的場景也比較適用,只需插入和數據讀取操做;
  6.    不支持單表一個文件,會將全部的數據和索引內容分別存在兩個文件中;
  7.    MyISAM對整張表加鎖而不是對行,因此不適用寫操做比較多的場景;
  8.    支持索引緩存不支持數據緩存。

查詢過程數據結構

咱們但願經過MySQL能夠得到更好的查詢性能,最好的方式就是弄清楚MySQL是如何執行查詢的,理解了這一點,咱們能夠依據它的規則去優化SQL語句。架構

當向MySQL發送一個SQL請求的時候,究竟發生了什麼呢,以下:併發

客戶端/服務端通訊協議數據庫設計

一、MySQL客戶端/服務端通訊協議是半雙工的:在任一時刻,要麼是服務器向客戶端發送數據,要麼是客戶端向服務器發送數據,這兩個動做不能同時發生。一旦一端開始發送消息,另外一端要接收完整個消息才能響應它,因此咱們沒法將一個消息切成小塊獨立發送,也沒有辦法進行流量控制。 

 

二、客戶端用一個單獨的數據包將查詢請求發送給服務器,因此當查詢語句很長的時候,須要設置max_allowed_packet參數。可是須要注意的是,若是查詢實在是太大,服務端會拒絕接收更多數據並拋出異常。

 

三、服務器響應給用戶的數據一般會不少,由多個數據包組成。可是當服務器響應客戶端請求時,客戶端必須完整的接收整個返回結果,而不能只取部分結果,而後讓服務器中止發送。於是在實際開發中,儘可能保持查詢簡單且只返回必需的數據,減少通訊間數據包的大小和數量是一個很是好的習慣,這也是查詢中儘可能避免使用SELECT *以及加上LIMIT限制的緣由之一。

 

小結:請求語句有大小限制,不該過長;減少通訊間數據包大小及通訊數量

 

查詢緩存

在解析一個查詢語句前,若是查詢緩存是打開的,那麼MySQL會檢查這個查詢語句是否命中查詢緩存中的數據。若是當前查詢剛好命中查詢緩存,在檢查一次用戶權限後直接返回緩存中的結果。這種狀況下,查詢不會被解析,也不會生成執行計劃,更不會執行。

 

MySQL將緩存存放在一個引用表(相似於HashMap的數據結構),經過一個哈希值索引,這個哈希值經過查詢語句、查詢的數據庫、客戶端協議版本號等一些可能影響結果的信息計算得來。因此兩個查詢在任何字符上的不一樣(例如:空格、註釋),都會致使緩存不會命中。

 

若是查詢中包含任何用戶自定義函數、存儲函數、用戶變量、臨時表、mysql庫中的系統表,其查詢結果都不會被緩存。好比函數NOW()或者CURRENT_DATE()會由於不一樣的查詢時間,返回不一樣的查詢結果,再好比包含CURRENT_USER或者CONNECION_ID()的查詢語句會由於不一樣的用戶而返回不一樣的結果,將這樣的查詢結果緩存起來沒有任何的意義。

 

MySQL的查詢緩存系統會跟蹤查詢中涉及的每一個表,若是這些表(數據或結構)發生變化,那麼和這張表相關的全部緩存數據都將失效。正由於如此,在任何的寫操做時,MySQL必須將對應表的全部緩存都設置爲失效。若是查詢緩存很是大或者碎片不少,這個操做就可能帶來很大的系統消耗,甚至致使系統僵死一下子。

查詢緩存對系統的額外消耗不只僅在寫操做,讀操做也不例外:

  • 任何的查詢語句在開始以前都必須通過檢查,即便這條SQL語句永遠不會命中緩存
  • 若是查詢結果能夠被緩存,那麼執行完成後,會將結果存入緩存,也會帶來額外的系統消耗基於此,咱們要知道並非什麼狀況下查詢緩存都會提升系統性能,緩存和失效都會帶來額外消耗,只有當緩存帶來的資源節約大於其自己消耗的資源時,纔會給系統帶來性能提高。但要如何評估打開緩存是否可以帶來性能提高是一件很是困難的事情,也不在本文討論的範疇內。若是系統確實存在一些性能問題,能夠嘗試打開查詢緩存,並在數據庫設計上作一些優化,好比:
  • 用多個小表代替一個大表,注意不要過分設計
  • 批量插入代替循環單條插入
  • 合理控制緩存空間大小,通常來講其大小設置爲幾十兆比較合適
  • 能夠經過SQL_CACHE和SQL_NO_CACHE來控制某個查詢語句是否須要進行緩存

 

不要輕易打開查詢緩存,特別是寫密集型應用。若是必定要開啓查詢緩存,能夠將query_cache_type設置爲DEMAND,只有查詢語句加入SQL_CACHE的查詢纔會走緩存,其餘查詢則不會,這樣能夠很是自由地控制哪些查詢須要被緩存。

 

語法解析和預處理

MySQL經過關鍵字將SQL語句進行解析,而且建立內部數據結構解析樹,這個過程解析器主要經過語法規則來驗證和解析,好比是否使用了錯誤的關鍵字,查詢的數據表和列是否存在等,而後對其進行各類優化,包括重寫查詢,決定表的讀寫順序,以及選擇合適的索引等。用戶能夠經過特殊的關鍵字提示(hint)優化器,影響它的決策過程。也能夠請求優化器解釋(explain)優化過程的各個因素,使用戶知道服務器如何進行優化決策的,這個比較實用,尤爲是優化某個查詢語句時。

相關文章
相關標籤/搜索