MySQL性能結構優化原理(技術核心)

1、SQL查詢優化(重要)

1.1 獲取有性能問題SQL的三種方式

1.經過用戶反饋獲取存在性能問題的SQL;javascript

2.經過慢查日誌獲取存在性能問題的SQL;java

3.實時獲取存在性能問題的SQL;mysql

1.1.2 慢查日誌分析工具

  • 相關配置參數:
slow_query_log # 啓動中止記錄慢查日誌,慢查詢日誌默認是沒有開啓的能夠在配置文件中開啓(on) slow_query_log_file # 指定慢查日誌的存儲路徑及文件,日誌存儲和數據從存儲應該分開存儲 long_query_time # 指定記錄慢查詢日誌SQL執行時間的閥值默認值爲10秒一般,對於一個繁忙的系統來講,改成0.001秒(1毫秒)比較合適 log_queries_not_using_indexes #是否記錄未使用索引的SQL 
  • 經常使用工具:mysqldumpslowpt-query-digest
pt-query-digest --explain h=127.0.0.1,u=root,p=p@ssWord slow-mysql.log 

1.1.3 實時獲取有性能問題的SQL(推薦)

 
 
SELECT id,user,host,DB,command,time,state,info FROM information_schema.processlist WHERE TIME>=60 

查詢當前服務器執行超過60s的SQL,能夠經過腳本週期性的來執行這條SQL,就能查出有問題的SQL。sql

1.2 SQL的解析預處理及生成執行計劃(重要)

1.2.1 查詢過程描述(重點!!!)

 
 

經過上圖能夠清晰的瞭解到MySql查詢執行的大體過程:數據庫

1.發送SQL語句。緩存

2.查詢緩存,若是命中緩存直接返回結果。bash

3.SQL解析,預處理,再由優化器生成對應的查詢執行計劃。服務器

4.執行查詢,調用存儲引擎API獲取數據。session

5.返回結果。架構

1.2.2 查詢緩存對性能的影響(建議關閉緩存)

第一階段:

相關配置參數:

query_cache_type # 設置查詢緩存是否可用 query_cache_size # 設置查詢緩存的內存大小 query_cache_limit # 設置查詢緩存可用的存儲最大值(加上sql_no_cache能夠提升效率) query_cache_wlock_invalidate # 設置數據表被鎖後是否返回緩存中的數據 query_cache_min_res_unit # 設置查詢緩存分配的內存塊的最小單 
緩存查找是利用對大小寫敏感的哈希查找來實現的,Hash查找只能進行全值查找(sql徹底一致),
若是緩存命中,檢查用戶權限,若是權限容許,直接返回,查詢不被解析,也不會生成查詢計劃。

在一個讀寫比較頻繁的系統中,建議關閉緩存,由於緩存更新會加鎖。將query_cache_type設置爲off,query_cache_size設置爲0

1.2.3 第二階段:MySQL依照執行計劃和存儲引擎進行交互

這個階段包括了多個子過程:

 
 

 
 

 
 

一條查詢能夠有多種查詢方式,查詢優化器會對每一種查詢方式的(存儲引擎)統計信息進行比較,找到成本最低的查詢方式,這也就是索引不能太多的緣由。

1.3 會形成MySQL生成錯誤的執行計劃的緣由

一、統計信息不許確

二、成本估算與實際的執行計劃成本不一樣

 
 

三、給出的最優執行計劃與估計的不一樣


 
 

四、MySQL不考慮併發查詢

五、會基於固定規則生成執行計劃

六、MySQL不考慮不受其控制的成本,如存儲過程,用戶自定義函數

1.4 MySQL優化器可優化的SQL類型

查詢優化器:對查詢進行優化並查詢mysql認爲的成本最低的執行計劃。

爲了生成最優的執行計劃,查詢優化器會對一些查詢進行改寫

能夠優化的sql類型

一、從新定義表的關聯順序;

 
 

二、將外鏈接轉換爲內鏈接;

三、使用等價變換規則;

 
 

四、優化count(),min(),max();


 
 

五、將一個表達式轉換爲常數;

 

 

六、子查詢優化;
 
image.png

七、提早終止查詢,如發現一個不成立條件(如where id = -1),當即返回一個空結果;

八、對in()條件進行優化;

1.5 查詢處理各個階段所須要的時間

1.5.1 使用profile(目前已經不推薦使用了)

  • set profiling = 1; #啓動profile,這是一個session級的配製執行查詢

  • show profiles; # 查詢每個查詢所消耗的總時間的信息

  • show profiles for query N; # 查詢的每一個階段所消耗的時間

1.5.2 performance_schema是5.5引入的一個性能分析引擎(5.5版本時期開銷比較大)

啓動監控和歷史記錄表:use performance_schema

update setup_instruments set enabled='YES',TIME = 'YES' WHERE NAME LIKE 'stage%'; update set_consumbers set enabled='YES',TIME = 'YES' WHERE NAME LIKE 'event%'; 
 
 
 
 

1.6 特定SQL的查詢優化

1.6.1 大表的數據修改

 
 

 
 

1.6.2 大表的結構修改

 
 

1.利用主從複製,先對從服務器進入修改,而後主從切換

2.(推薦)

添加一個新表(修改後的結構),老表數據導入新表,老表創建觸發器,修改數據同步到新表,
老表加一個排它鎖(重命名), 新表重命名, 刪除老表。
 
 

修改語句這個樣子:

alter table sbtest4 modify c varchar(150) not null default '' 

利用工具修改:

 
 

1.6.3 優化not in 和 <> 查詢

子查詢改寫爲關聯查詢:

 
 

2、分庫分表

2.1 分庫分表的幾種方式

分擔讀負載 可經過 一主多從,升級硬件來解決。

2.1.1 把一個實例中的多個數據庫拆分到不一樣實例(集羣)

 
 
拆分簡單,不容許跨庫。但並不能減小寫負載

2.1.2 把一個庫中的表分離到不一樣的數據庫中

 
 

該方式只能在必定時間內減小寫壓力。

以上兩種方式只能暫時解決讀寫性能問題。

2.1.3 數據庫分片

對一個庫中的相關表進行水平拆分到不一樣實例的數據庫中
 
 

2.1.3.1 如何選擇分區鍵

1.分區鍵要能儘量避免跨分區查詢的發生

2.分區鍵要儘量使各個分區中的數據平均

2.1.3.2 分片中如何生成全局惟一ID

 
 

擴展:表的垂直拆分和水平拆分

隨着業務的發展,數據庫成爲了整個系統性能的一個瓶頸,這時候就須要對數據庫進行優化,可是單單是優化只能提升有限的一點性能,這時候要想解決問題須要的是從數據庫架構層面去思考問題。數據庫的架構是一個很大的課題,裏面最實用的有兩個,一個是數據庫拆分,一個是讀寫分離。今天就來談談數據庫的兩種拆分方式。

1、垂直拆分

垂直拆分很簡單,就是根據不一樣的業務來劃分不一樣的數據庫。好比一個電商系統根據業務能夠分紅商品表、會員表、訂單表。原先,這些表都是放在同一個數據庫服務器上,如今須要垂直拆分數據庫,就是將商品表單獨放在一個數據庫中,會員表單獨放在一個數據庫中,訂單表單獨放在一個數據庫中,這樣就解決了表與表之間的io競爭。

2、水平拆分

垂直拆分比較簡單,水平拆分就比較複雜了,要考慮不少東西。垂直拆分根據業務來拆分,或者說的直白點就是根據表名來拆分,而水平拆分是根據表裏面的字段來拆分(記住是根據字段來拆分,而不是拆分字段,拆分後的每一張表的表結構都是同樣)。好比要拆分用戶表,能夠根據用戶的註冊時間這一字段來拆分整個表,2016年註冊的用戶放在用戶表1中,2017年註冊的用戶放在用戶表2中,2018年註冊的用戶放在用戶表3中。這就是水平拆分,看似很簡單,實際上要考慮的東西是不少的。就好比上述的例子,咱們用時間來拆分,就會有侷限性。一個好產品上線後,在開始的時候用戶數量都是不多的,都須要必定時間的沉澱,纔會有一個用戶數量的爆發期。若是用時間來拆分,就會出現一種狀況,就是用戶表1的規模很小,而用戶表2的規模卻很大,是用戶表1的好幾倍,而用戶表三多是用戶表1的好幾十倍。這樣的話,拆分水平拆分的意義就不大了。通常用戶表都是用戶id來拆分的,具體還要結合實際業務去分析。因此,水平拆分是一件很複雜的事情,你們在進行水平拆分的時候必定要考慮到方方面面,這樣才能設計出優秀的數據庫架構方案。

做者:若丨寒 連接:https://www.jianshu.com/p/999537f158b1 來源:簡書 簡書著做權歸做者全部,任何形式的轉載都請聯繫做者得到受權並註明出處。
相關文章
相關標籤/搜索