MySQL數據庫技術的方方面面也是不少,這裏只涉及必備的性能調優,推崇從下向上的性能調優,主要包括運行環境,配置參數,SQL性能,和系統架構設計調優。mysql
運行環境調優linux
這裏是Linux的天下,MySQL 運行環境的調優每每和Linux的內核調優一併完成。固然了,對雲服務RDS 也有必定的參考做用。redis
調整Linux默認的IO調度算法算法
IO調度器的整體目標是但願讓磁頭可以老是往一個方向移動,移動到底了再往反方向走,這偏偏就是現實生活中的電梯模型,因此IO調度器也被叫作電梯 (elevator),而相應的算法也就被叫作電梯算法.而Linux中IO調度的電梯算法有好幾種,一個叫作as(Anticipatory),一個叫作 cfq(Complete Fairness Queueing),一個叫作deadline,還有一個叫作noop(No Operation).sql
IO對數據庫的影響較大,linux默認的IO調度算法爲cfq,須要修改成deadline,若是是SSD或者PCIe-SSD設備,須要修改成noop,可使用下面兩種修改方式。數據庫
一、在線動態修改,重啓失效。緩存
echo 「deadline」 > /sys/block/sda/queue/scheduler安全
二、修改/etc/grub.conf,永久生效。服務器
修改/etc/grub.conf配置文件,在kernel那行增長一個配置,例如:session
elevator=deadline
主要關注elevator這個參數,設置內核的話須要重啓系統才能生效。
禁用numa特性
新一代架構的NUMA不適合跑數據庫,NUMA是爲了內存利用率的提升,但反而可能致使一CPU的內存尚有剩餘,另一個卻不夠用了,發生swap的問題,所以通常建議關閉或修改NUMA的調度。
一、修改/etc/grub.conf關閉NUMA,重啓後生效。
numa=off
二、修改/etc/init.d/mysql或mysqld_safe腳本,設置啓動mysqld進程時的NUMA調度機制,如 numactl –interleave=all。
修改swappiness設置
swappiness是linux的一個內核參數,用來控制物理內存交換出去的策略.它容許一個百分比的值,最小的爲0,最大的爲100,改值默認是60.這個設置值到底有什麼影響呢?
vm.swappiness設置爲0表示儘可能少使用swap,100表示儘可能將inactive的內存頁交換到swap裏或者釋放cache。inactive內存的意思是程序映射着,可是」長時間」不用的內存。咱們能夠利用vmstat查看系統裏面有多少inactive的內存。
# vmstat -a 1
這個值推薦設置爲1,設置方法以下,在/etc/sysctl.conf文件中增長一行。
vm.swappiness = 1
擴大文件描述符
這個是常常修改的參數,高併發的程序都會修改.
一、動態修改,重啓失效,只能使用root,而且當前session有效。
ulimit -n 51200
二、修改配置文件,永久生效。
在/etc/security/limits.conf配置文件中增長
* hard nofile 51200
* soft nofile 51200
面向session的進程文件描述符的修改稍有不一樣,在雲上的修改也略有差別,能夠參見同樣的「open too many files」
對於文件系統,如無特殊要求,最好採用ext4.
文件系統掛載參數是在/etc/fstab文件中修改,重啓時候生效。
noatime表示不記錄訪問時間,nodiratime不記錄目錄的訪問時間。
barrier=0,表示關閉barrier功能.
barrier的主要目的是爲了保證磁盤寫數據的安全性,可是會下降性能。若是有BBU之類的電池備份電源保證控制卡不瞬間掉電,那麼這個功能就能夠放心大膽的關閉。
my.cnf中的配置參數調優取決於業務,負載或硬件,在慢內存和快磁盤、高併發和寫密集型負載狀況下,都須要特殊的調整。
query_cache_size
query cache是一個衆所周知的瓶頸,甚至在併發並很少時也如此。 最 好是一開始就停用,設置query_cache_size = 0,並利用其餘方法加速查詢:優化索引、增長拷貝分散負載或者啓用額外的緩存(好比memcache或redis)。若是已經啓用了query cache而且尚未發現任何問題,query cache可能有用。若是想停用它,那就得當心了。
innodb_buffer_pool_size
緩衝池是數據和索引緩存的地方:這個值越大越好,這能保證你在大多數的讀取操做時使用的是內存而不是硬盤。典型的值是5-6GB(8GB內存),20-25GB(32GB內存),100-120GB(128GB內存)。
innodb_log_file_size
redo日誌被用於確保寫操做快速而可靠而且在崩潰時恢復。從MySQL 5.5以後,崩潰恢復的性能的到了很大提高,能夠同時擁有較高的寫入性能和崩潰恢復性能。在MySQL 5.6裏能夠被提升到4GB以上。若是應用程序須要頻繁的寫入數據,能夠一開始就把它這是成4G。
max_connections
max_connection值被設高了(例如1000或更高)以後一個主要缺陷是當服務器運行1000個或更高的活動事務時會變的沒有響應。在應用程序裏使用鏈接池或者在MySQL裏使用進程池有助於解決這一問題。
back_log
要求 mysql 能有的鏈接數量。當主要mysql線程在一個很短期內獲得很是多的鏈接請求,這就起做用,而後主線程花些時間檢查鏈接而且啓動一個新線程。back_log指明在mysql暫時中止回答新請求以前的短期內多少個請求能夠被存在堆棧中。只有若是指望在一個短期內有不少鏈接,須要增長它,換句話說,該值對到來的tcp/ip鏈接的偵聽隊列的大小。
innodb_file_per_table
這項設置告知InnoDB是否須要將全部表的數據和索引存放在共享表空間裏(innodb_file_per_table = OFF)或者爲每張表的數據單獨放在一個.ibd文件(innodb_file_per_table = ON)。每張表一個文件容許你在drop、truncate或者rebuild表時回收磁盤空間。這對於一些高級特性也是有必要的,好比數據壓縮。可是它不會帶來任何性能收益。MySQL 5.6中,這個屬性默認值是ON。
innodb_flush_log_at_trx_commit
默認值爲1,表示InnoDB徹底支持ACID特性。當關注點是數據安全的時候這個值是最合適的,好比在一個主節點上。可是對於磁盤(讀寫)速度較慢的系統,它會帶來很巨大的開銷,由於每次將改變flush到redo日誌都須要額外的fsyncs。若是值爲0速度就更快了,但在系統崩潰時可能丟失一些數據, 因此一遍只適用於備份節點。
innodb_flush_method
這項配置決定了數據和日誌寫入硬盤的方式。通常來講,若是你有硬件RAID控制器,而且其獨立緩存採用write-back機制,並有着電池斷電保護,那麼應該設置配置爲O_DIRECT;不然,大多數狀況下應將其設爲fdatasync(默認值)。sysbench是一個能夠幫助你決定這個選項的好工具。
innodb_log_buffer_size
這項配置決定了爲還沒有執行的事務分配的緩存。可是若是事務中包含有二進制大對象或者大文本字段的話,看Innodb_log_waits狀態變量,若是它不是0,增長innodb_log_buffer_size。
log_bin
若是數據庫服務器充當主節點的備份節點,那麼開啓二進制日誌是必須的。就算只有一個服務器,若是你想作基於時間點的數據恢復,這也是頗有用的。二進制日誌一旦建立就將永久保存。若是不想讓磁盤空間耗盡,你能夠用 PURGE BINARY LOGS 來清除舊文件,或者設置 expire_logs_days 來指定過多少天日誌將被自動清除。記錄二進制日誌不是沒有開銷的,因此若是你在一個非主節點的複製節點上不須要它的話,那麼建議關閉這個選項。
interactive_timeout
服務器在關閉它前在一個交互鏈接上等待行動的秒數。一個交互的客戶被定義爲對 mysql_real_connect()使用 client_interactive 選項的客戶。 默認數值是28800,建議改成7200。
table_open_cache
MySQL每打開一個表,都會讀入一些數據到table_open_cache緩存中,當MySQL在這個緩存中找不到相應信息時,纔會去磁盤上讀取。假定系統有200個併發鏈接,則需將此參數設置爲200*N(N爲每一個鏈接所需的文件描述符數目);當把table_open_cache設置爲很大時,若是系統處理不了那麼多文件描述符,那麼就會出現客戶端失效,鏈接不上。
max_allowed_packet
接受的數據包大小;增長該變量的值十分安全,這是由於僅當須要時纔會分配額外內存。例如,僅當你發出長查詢或MySQLd必須返回大的結果行時MySQLd纔會分配更多內存。該變量之因此取較小默認值是一種預防措施,以捕獲客戶端和服務器之間的錯誤信息包,並確保不會因偶然使用大的信息包而致使內存溢出
skip_name_resolve
當客戶端鏈接數據庫服務器時,且當DNS很慢時,創建鏈接也會很慢。所以建議在啓動服務器時關閉skip_name_resolve選項而不進行DNS查找。
在應用層,經過pt工具和慢查詢日誌的配合,能夠輕鬆地分辨出全表掃描的語句。
避免全表掃描
創建索引
儘可能避免向客戶端返回大數據量,若數據量過大,應該考慮相應需求是否合理
儘可能避免大事務操做,提升系統併發能力
使用基於遊標的方法或臨時表方法以前,應先尋找基於集的解決方案來解決問題,基於集的方法一般更有效。儘可能避免使用遊標,由於遊標的效率較差。
關於where 後的條件
應儘可能避免在 where 子句中使用 != 或 <> 操做符,不然將引擎放棄使用索引而進行全表掃描。
應儘可能避免在 where 子句中使用 or 來鏈接條件,能夠考慮使用union 代替
in 和 not in 也要慎用,對於連續的數值,能用 between 就不要用 in,exists 代替 in
儘可能避免在 where 子句中對字段進行表達式操做和函數操做
關於數據類型
儘可能使用數字型字段,若只含數值信息的字段儘可能不要設計爲字符型,這會下降查詢和鏈接的性能,並會增長存儲開銷。
儘量的使用 varchar/nvarchar 代替 char/nchar ,由於變長字段存儲空間小,對於查詢來講,在一個相對較小的字段內搜索效率顯然要高些。
最好不要給數據庫留NULL,儘量的使用 NOT NULL填充數據庫.備註、描述、評論之類的能夠設置爲 NULL,其餘的,最好不要使用NULL。
任何地方都不要使用 select * from t ,用具體的字段列表代替「*」,不要返回用不到的任何字段。
關於臨時表
避免頻繁建立和刪除臨時表,以減小系統表資源的消耗。對於一次性事件, 最好使用導出表。
在新建臨時表時,若是一次性插入數據量很大,那麼可使用 select into 代替 create table,避免形成大量 log ,以提升速度;若是數據量不大,爲了緩和系統表的資源,應先create table,而後insert。
若是使用到了臨時表,在最後將全部的臨時表顯式刪除時,先 truncate table ,而後 drop table ,這樣能夠避免系統表的較長時間鎖定。
關於索引
先應考慮在 where 及 order by 涉及的列上創建索引。
在使用索引字段做爲條件時,若是該索引是複合索引,那麼必須使用到該索引中的第一個字段做爲條件 時才能保證系統使用該索引, 不然該索引將不會 被使用, 而且應儘量的讓字段順序與索引順序相一致。
索引並非越多越好,索引當然能夠提升相應的 select 的效率,但同時也下降了 insert和update 的效率,由於 insert 或 update 時有可能會重建索引,因此視具體狀況而定。一個表的索引數最好不要超過7個,若太多則應考慮一些不常使用到的列上建的索引是否有必要.
從底層來到了應用層,最終到架構層,然而脫離業務邏輯談架構就是耍流氓。數據庫架構一樣是依賴業務系統的,穩定而又彈性地服務業務系統是關鍵。架構調優的方向有:
分區分表
業務分庫
主從同步與讀寫分離
數據緩存
主從熱備與HA雙活
…..