1. 程式人生 > >MySQL優化---DBA對MySQL優化的一些總結

MySQL優化---DBA對MySQL優化的一些總結

本文整理了一些MySQL的通用優化方法,做個簡單的總結分享,旨在幫助那些沒有專職MySQL DBA的企業做好基本的優化工作,至於具體的SQL優化,大部分通過加適當的索引即可達到效果,更復雜的就需要具體分析了,可以參考本站的一些優化案例或者聯絡我,下方有我的聯絡方式。這是下篇。

3、MySQL層相關優化

3.1、關於版本選擇

官方版本我們稱為ORACLE MySQL,這個沒什麼好說的,相信絕大多數人會選擇它。

我個人強烈建議選擇Percona分支版本,它是一個相對比較成熟的、優秀的MySQL分支版本,在效能提升、可靠性、管理型方面做了不少改善。它和官方ORACLE MySQL版本基本完全相容,並且效能大約有20%以上的提升,因此我優先推薦它,我自己也從2008年一直以它為主。

另一個重要的分支版本是MariaDB,說MariaDB是分支版本其實已經不太合適了,因為它的目標是取代ORACLE MySQL。它主要在原來的MySQL Server層做了大量的原始碼級改進,也是一個非常可靠的、優秀的分支版本。但也由此產生了以GTID為代表的和官方版本無法相容的新特性(MySQL 5.7開始,也支援GTID模式線上動態開啟或關閉了),也考慮到絕大多數人還是會跟著官方版本走,因此沒優先推薦MariaDB。

3.2、關於最重要的引數選項調整建議

建議調整下面幾個關鍵引數以獲得較好的效能(可使用本站提供的my.cnf生成器生成配置檔案模板):

1、選擇Percona或MariaDB版本的話,強烈建議啟用thread pool特性,可使得在高併發的情況下,效能不會發生大幅下降。此外,還有extra_port功能,非常實用, 關鍵時刻能救命的。還有另外一個重要特色是 QUERY_RESPONSE_TIME 功能,也能使我們對整體的SQL響應時間分佈有直觀感受;

2、設定default-storage-engine=InnoDB,也就是預設採用InnoDB引擎,強烈建議不要再使用MyISAM引擎了,InnoDB引擎絕對可以滿足99%以上的業務場景;

3、調整innodb_buffer_pool_size大小,如果是單例項且絕大多數是InnoDB引擎表的話,可考慮設定為實體記憶體的50% ~ 70%左右;

4、根據實際需要設定innodb_flush_log_at_trx_commit、sync_binlog的值。如果要求資料不能丟失,那麼兩個都設為1。如果允許丟失一點資料,則可分別設為2和10。而如果完全不用care資料是否丟失的話(例如在slave上,反正大不了重做一次),則可都設為0。這三種設定值導致資料庫的效能受到影響程度分別是:高、中、低,也就是第一個會另資料庫最慢,最後一個則相反;

5、設定innodb_file_per_table = 1,使用獨立表空間,我實在是想不出來用共享表空間有什麼好處了;

6、設定innodb_data_file_path = ibdata1:1G:autoextend,千萬不要用預設的10M,否則在有高併發事務時,會受到不小的影響;

7、設定innodb_log_file_size=256M,設定innodb_log_files_in_group=2,基本可滿足90%以上的場景;

8、設定long_query_time = 1,而在5.5版本以上,已經可以設定為小於1了,建議設定為0.05(50毫秒),記錄那些執行較慢的SQL,用於後續的分析排查;

9、根據業務實際需要,適當調整max_connection(最大連線數)、max_connection_error(最大錯誤數,建議設定為10萬以上,而open_files_limit、innodb_open_files、table_open_cache、table_definition_cache這幾個引數則可設為約10倍於max_connection的大小;

10、常見的誤區是把tmp_table_size和max_heap_table_size設定的比較大,曾經見過設定為1G的,這2個選項是每個連線會話都會分配的,因此不要設定過大,否則容易導致OOM發生;其他的一些連線會話級選項例如:sort_buffer_size、join_buffer_size、read_buffer_size、read_rnd_buffer_size等,也需要注意不能設定過大;

11、由於已經建議不再使用MyISAM引擎了,因此可以把key_buffer_size設定為32M左右,並且強烈建議關閉query cache功能;

3.3、關於Schema設計規範及SQL使用建議

下面列舉了幾個常見有助於提升MySQL效率的Schema設計規範及SQL使用建議:

1、所有的InnoDB表都設計一個無業務用途的自增列做主鍵,對於絕大多數場景都是如此,真正純只讀用InnoDB表的並不多,真如此的話還不如用TokuDB來得划算;

2、欄位長度滿足需求前提下,儘可能選擇長度小的。此外,欄位屬性儘量都加上NOT NULL約束,可一定程度提高效能;

3、儘可能不使用TEXT/BLOB型別,確實需要的話,建議拆分到子表中,不要和主表放在一起,避免SELECT * 的時候讀效能太差。

4、讀取資料時,只選取所需要的列,不要每次都SELECT *,避免產生嚴重的隨機讀問題,尤其是讀到一些TEXT/BLOB列;

5、對一個VARCHAR(N)列建立索引時,通常取其50%(甚至更小)左右長度建立字首索引就足以滿足80%以上的查詢需求了,沒必要建立整列的全長度索引;

6、通常情況下,子查詢的效能比較差,建議改造成JOIN寫法;

7、多表聯接查詢時,關聯欄位型別儘量一致,並且都要有索引;

8、多表連線查詢時,把結果集小的表(注意,這裡是指過濾後的結果集,不一定是全表資料量小的)作為驅動表;

9、多表聯接並且有排序時,排序欄位必須是驅動表裡的,否則排序列無法用到索引;

10、多用複合索引,少用多個獨立索引,尤其是一些基數(Cardinality)太小(比如說,該列的唯一值總數少於255)的列就不要建立獨立索引了;

11、類似分頁功能的SQL,建議先用主鍵關聯,然後返回結果集,效率會高很多;

3.3、其他建議

關於MySQL的管理維護的其他建議有:

1、通常地,單表物理大小不超過10GB,單錶行數不超過1億條,行平均長度不超過8KB,如果機器效能足夠,這些資料量MySQL是完全能處理的過來的,不用擔心效能問題,這麼建議主要是考慮ONLINE DDL的代價較高;

2、不用太擔心mysqld程序佔用太多記憶體,只要不發生OOM kill和用到大量的SWAP都還好;

3、在以往,單機上跑多例項的目的是能最大化利用計算資源,如果單例項已經能耗盡大部分計算資源的話,就沒必要再跑多例項了;

4、定期使用pt-duplicate-key-checker檢查並刪除重複的索引。定期使用pt-index-usage工具檢查並刪除使用頻率很低的索引;

5、定期採集slow query log,用pt-query-digest工具進行分析,可結合Anemometer系統進行slow query管理以便分析slow query並進行後續優化工作;

6、可使用pt-kill殺掉超長時間的SQL請求,Percona版本中有個選項 innodb_kill_idle_transaction 也可實現該功能;

7、使用pt-online-schema-change來完成大表的ONLINE DDL需求;

8、定期使用pt-table-checksum、pt-table-sync來檢查並修復mysql主從複製的資料差異;