MySQL性能管理及架構設計:SQL查詢優化、分庫分表
一、SQL查詢優化(重要)
1.1 獲取有性能問題SQL的三種方式
- 通過用戶反饋獲取存在性能問題的SQL;
- 通過慢查日誌獲取存在性能問題的SQL;
- 實時獲取存在性能問題的SQL;
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
常用工具:mysqldumpslow和pt-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,infoFROM information_schema.processlistWHERE TIME>=60
查詢當前伺服器執行超過60s的SQL,可以通過腳本周期性的來執行這條SQL,就能查出有問題的SQL。
1.2 SQL的解析預處理及生成執行計劃(重要)
1.2.1 查詢過程描述(重點!!!)
通過上圖可以清晰的了解到MySql查詢執行的大致過程:
- 發送SQL語句。
- 查詢緩存,如果命中緩存直接返回結果。
- SQL解析,預處理,再由優化器生成對應的查詢執行計劃。
- 執行查詢,調用存儲引擎API獲取數據。
- 返回結果。
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生成錯誤的執行計劃的原因
1、統計信息不準確
2、成本估算與實際的執行計劃成本不同
3、給出的最優執行計劃與估計的不同
4、MySQL不考慮並發查詢
5、會基於固定規則生成執行計劃
6、MySQL不考慮不受其控制的成本,如存儲過程,用戶自定義函數
1.4 MySQL優化器可優化的SQL類型
查詢優化器:對查詢進行優化並查詢mysql認為的成本最低的執行計劃。 為了生成最優的執行計劃,查詢優化器會對一些查詢進行改寫
可以優化的sql類型
1、重新定義表的關聯順序;
2、將外連接轉換為內連接;
3、使用等價變換規則;
4、優化count(),min(),max();
5、將一個表達式轉換為常數;
6、子查詢優化;
7、提前終止查詢,如發現一個不成立條件(如where id = -1),立即返回一個空結果;
8、對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 大表的結構修改
- 利用主從複製,先對從伺服器進入修改,然後主從切換
- (推薦)
添加一個新表(修改後的結構),老表數據導入新表,老表建立觸發器,修改數據同步到新表, 老表加一個排它鎖(重命名), 新表重命名, 刪除老表。
修改語句這個樣子:
alter table sbtest4 modify c varchar(150) not null default
利用工具修改:
1.6.3 優化not in 和 <> 查詢
子查詢改寫為關聯查詢:
二、分庫分表
2.1 分庫分表的幾種方式
分擔讀負載 可通過 一主多從,升級硬體來解決。
2.1.1 把一個實例中的多個資料庫拆分到不同實例(集群)
拆分簡單,不允許跨庫。但並不能減少寫負載。
2.1.2 把一個庫中的表分離到不同的資料庫中
該方式只能在一定時間內減少寫壓力。
以上兩種方式只能暫時解決讀寫性能問題。
2.1.3 資料庫分片
對一個庫中的相關表進行水平拆分到不同實例的資料庫中
2.1.3.1 如何選擇分區鍵
- 分區鍵要能儘可能避免跨分區查詢的發生
- 分區鍵要儘可能使各個分區中的數據平均
2.1.3.2 分片中如何生成全局唯一ID
擴展:表的垂直拆分和水平拆分
文章來源:https://segmentfault.com/a/1190000013781544
Mysql相關視頻內容推薦:http://www.roncoo.com/course/list.html?courseName=mysql
推薦閱讀: