深入浅出MySQL之优化
深入淺出MySQL之優化
最近經常問別人MySQL優化,發現大家對這塊熟悉,但是不夠了解。因此反思總結下,MySQL優化,會有哪些方面呢?本文將其分成應用優化,查詢緩存優化,內存管理優化,并發參數調整和鎖問題,以及常用MySQL技巧
在實際生產環境中,由于數據庫本身的性能局限,就必須要對 前臺的應用進行一些優化,來降低數據庫的訪問壓力。
對于訪問數據庫來說,建立連接的代價是比較昂貴的,因為我們頻繁的創建關閉連接,是比較耗費資源的,我們有 必要建立 數據庫連接池,以提高訪問的性能。
避免對數據進行重復檢索,比如查一次能獲取所需字段,就不要分多次查詢,減少對數據庫的無用重復請求。
增加cache層
我們在應用中可以增加緩存來減輕數據庫負擔,緩存層有多種,也有很多實現方式。因此可以部分數據從數據庫中抽取出來放到應用端以文本方式存儲, 或者使用框架(Mybatis, Hibernate)提供的一 級緩存/二級緩存,或者使用redis數據庫來緩存數據。
負載均衡是應用中使用非常普遍的一種優化方法,它的機制就是利用某種均衡算法,將固定的負載量分布到不同的服務器上, 以此來降低單臺服務器的負載,達到優化的效果。
利用MySQL復制分流查詢。通過MySQL的主從復制,實現讀寫分離,使增刪改操作走主節點,查詢操作走從節點,從而可以降低單臺服務器的 讀寫壓力。
采用分布式數據庫架構。分布式數據庫架構適合大數據量、負載高的情況,它有良好的拓展性和高可用性。通過在多臺服務器之間分布數 據,可以實現在多臺服務器之間的負載均衡,提高訪問效率。
查詢緩存select選項。可以在SELECT語句中指定兩個與查詢緩存相關的選項 :
SQL_CACHE : 如果查詢結果是可緩存的,并且 query_cache_type 系統變量的值為ON或 DEMAND ,則緩存查詢結果 。
SQL_NO_CACHE : 服務器不使用查詢緩存。它既不檢查查詢緩存,也不檢查結果是否已緩存,也不緩存查詢結果。
例子:
查詢緩存失效有下列幾種:
MySQL內存優化原則:
1) 將盡量多的內存分配給MySQL做緩存,但要給操作系統和其他程序預留足夠內存。
2) MyISAM 存儲引擎的數據文件讀取依賴于操作系統自身的IO緩存,因此,如果有MyISAM表,就要預留更多的 內存給操作系統做IO緩存。
3) 排序區、連接區等緩存是分配給每個數據庫會話(session)專用的,其默認值的設置要根據最大連接數合理 分配,如果設置太大,不但浪費資源,而且在并發連接較高時會導致物理內存耗盡。
InnoDB內存優化:
nnodb用一塊內存區做IO緩存池,該緩存池不僅用來緩存innodb的索引塊,而且也用來緩存innodb的數據塊。
Innodb_buffer_pool_size
?????? 該變量決定了 innodb 存儲引擎表數據和索引數據的最大緩存區大小。在保證操作系統及其他程序有足夠內存可用的情況下,innodb_bu?er_pool_size 的值越大,緩存命中率越高,訪問InnoDB表需要的磁盤I/O 就越少,性能也就越高。
Innodb_log_buffer_size
?????? 決定了innodb重做日志緩存的大小,對于可能產生大量更新記錄的大事務,增加innodb_log_bu?er_size的大小,可以避免innodb在事務提交前就執行不必要的日志寫入磁盤操作。
從實現上來說,MySQL Server是多線程結構,包括后臺線程和客戶服務線程。多線程可以有效利用服務器資源,提高數據庫的并發性能。在Mysql中,控制并發連接和線程的主要參數包括 max_connections、back_log、 thread_cache_size、table_open_cahce。
采用max_connections 控制允許連接到MySQL數據庫的最大數量,默認值是 151。如果狀態變量 connection_errors_max_connections 不為零,并且一直增長,則說明不斷有連接請求因數據庫連接數已達到允許最大值而失敗,這是可以考慮增大max_connections 的值。
Mysql 最大可支持的連接數,取決于很多因素,包括給定操作系統平臺的線程庫的質量、內存大小、每個連接的負荷、CPU的處理速度,期望的響應時間等。在Linux 平臺下,性能好的服務器,支持 500-1000 個連接不是難事,需要根據服務器性能進行評估設定。
back_log 參數控制MySQL監聽TCP端口時設置的積壓請求棧大小。如果MySql的連接數達到max_connections時, 新來的請求將會被存在堆棧中,以等待某一連接釋放資源,該堆棧的數量即back_log,如果等待連接的數量超過 back_log,將不被授予連接資源,將會報錯。5.6.6 版本之前默認值為 50 , 之后的版本默認為 50 +(max_connections / 5), 但最大不超過900。如果需要數據庫在較短的時間內處理大量連接請求??梢钥紤]適當增大back_log 的值。 ?
該參數用來控制所有SQL語句執行線程可打開表緩存的數量, 而在執行SQL語句時,每一個SQL執行線程至少要打開 1個表緩存。該參數的值應該根據設置的最大連接數 max_connections 以及每個連接執行關聯查詢中涉及的表的最大數量來設定 :
max_connections x N ;
為了加快連接數據庫的速度,MySQL 會緩存一定數量的客戶服務線程以備重用,通過參數 thread_cache_size 可 控制 MySQL 緩存客戶服務線程的數量。
該參數是用來設置InnoDB 事務等待行鎖的時間,默認值是50ms,可以根據需要進行動態設置。對于需要快速反饋的業務系統來說,可以將行鎖的等待時間調小,以避免事務長時間掛起;對于后臺運行的批量處理程序來說,可以將行鎖的等待時間調,以避免發生大的回滾操作。
MySQL中的鎖要詳細了解,篇幅較大,本節大致概過。
鎖是計算機協調多個進程或線程并發訪問某一資源的機制(避免爭搶)。在數據庫中,除傳統的計算資源(如 CPU、RAM、I/O 等)的爭用以外,數據也是一種供許多用戶共享的資源。如何保證數據并發訪問的一致性、有效性是所有數據庫必須解決的一個問題,鎖沖突也是影響數據庫并發訪問性能的一個重要因素。從這個角度來說,鎖對數據庫而言顯得尤其重要,也更加復雜。
鎖分類:
從對數據操作的粒度分 :
1) 表鎖:操作時,會鎖定整個表。
2) 行鎖:操作時,會鎖定當前操作行。
從對數據操作的類型分:
行鎖特點 :
偏向InnoDB 存儲引擎,開銷大,加鎖慢;會出現死鎖;鎖定粒度最小,發生鎖沖突的概率最低,并發度 也最高。InnoDB 與 MyISAM 的最大不同有兩點:一是支持事務;二是采用了行級鎖。
InnoDB 實現了以下兩種類型的行鎖。
共享鎖(S):又稱為讀鎖,簡稱S鎖,共享鎖就是多個事務對于同一數據可以共享一把鎖,都能訪問到數據,但是只能讀不能修改。
排他鎖(X):又稱為寫鎖,簡稱X鎖,排他鎖就是不能與其他鎖并存,如一個事務獲取了一個數據行的排他 鎖,其他事務就不能再獲取該行的其他鎖,包括共享鎖和排他鎖,但是獲取排他鎖的事務是可以對數據就行 讀取和修改。對于UPDATE、DELETE和INSERT語句,InnoDB會自動給涉及數據集加排他鎖(X); 對于普通SELECT語句,InnoDB不會加任何鎖;
InnoDB存儲引擎由于實現了行級鎖定,雖然在鎖定機制的實現方面帶來了性能損耗可能比表鎖會更高一些,但是 在整體并發處理能力方面要遠遠由于MyISAM的表鎖的。當系統并發量較高的時候,InnoDB的整體性能和MyISAM 相比就會有比較明顯的優勢。
但是,InnoDB的行級鎖同樣也有其脆弱的一面,當我們使用不當的時候,可能會讓InnoDB的整體性能表現不僅不 能比MyISAM高,甚至可能會更差。
優化建議:
1)盡可能讓所有數據檢索都能通過索引來完成,避免無索引行鎖升級為表鎖。
2)合理設計索引,盡量縮小鎖的范圍。
3)盡可能減少索引條件,及索引范圍,避免間隙鎖。
4)盡量控制事務大小,減少鎖定資源量和時間長度。
5)盡可使用低級別事務隔離(但是需要業務層面滿足需求)。
6.??? 常用MySQL技巧
?????? SQL的執行順序。舉例如下:
?????? 編寫順序:
?????? ELECT DISTINCT
??? ?????? <select list>
FROM
??? ?????? <left_table> <join_type> JOIN
??? ?????? <right_table> ON <join_condition> WHERE
??? ?????? <where_condition>
GROUP BY
??? ?????? <group_by_list>
HAVING
??? ?????? <having_condition>
ORDER BY
??? ?????? <order_by_condition>
LIMIT
??? ?????? <limit_params>
?????? 執行順序:
?????? FROM??? <left_table>
ON????? <join_condition>? <join_type>????
JOIN???? <right_table>
WHERE?? <where_condition>
GROUP BY??? <group_by_list>
HAVING????? <having_condition>
SELECT DISTINCT???? <select list>
ORDER BY??? <order_by_condition>
LIMIT?????? <limit_params>
正則表達式的運用,以及常用的函數,如數字函數,字符串函數和日期函數等。
總結:本篇文章大致說到一些工作中常常用到的優化技巧,可做參考,更細致請關注公眾號,后續陸續推送。
總結
以上是生活随笔為你收集整理的深入浅出MySQL之优化的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: hql 语法详解
- 下一篇: mybatis如何防止SQL注入?