淺談mysql配置優化和sql語句優化

    作優化,我在這裏引用淘寶系統分析師蔣江偉的一句話:只有敢於承擔,才能讓人有勇氣,有承擔本身的錯誤的勇氣。有承擔錯誤的勇氣,就有去作事得勇氣。不管作什麼事,只要是對的,就要去作,勇敢去作。出了錯誤,承擔錯誤,改正錯誤,這樣的人沒有人會去責怪。
mysql

    好久以前就想寫一篇關於mysql優化方面的文章了,忙於工做,在着也比較懶散。如今網上mysql優化方面的帖子不少,也不乏精品。很早聽一DBA前輩說過:mysql的優化,三分配置的優化,七分sql語句的優化。以前不是很理解,但接觸到高併發大數據的時候,這句話的含義尤其突出,甚至能夠說一分配置的優化,九分語句的優化。sql

mysql的優化,通常分爲配置的優化、sql語句的優化、表結構的優化、索引的優化,這裏着重說前兩點。數據庫

 

1、配置的優化緩存

    配置的優化其實包含兩個方面的:操做系統內核的優化和mysql配置文件的優化安全

    1、系統內核的優化對專用的mysql服務器來講,無非是內存實用、鏈接數、超時處理、TCP處理等方面的優化,根據本身的硬件配置來進行優化,這裏很少講;服務器

    2mysql配置的優化,通常來講包含:IO處理的經常使用參數、最大鏈接數設置、緩存使用參數的設置、慢日誌的參數的設置、innodb相關參數的設置等,若是有主從關係在設置主從同步的相關參數便可,網上的相關配置文件不少,大同小異,經常使用的設置大多修改這些差很少就夠用了。網絡

 

如下是個人一個mysql配置文件,僅供參考:架構

###############################################併發

[mysqld]ide

skip-name-resolve

server-id = 1

bind-address = 0.0.0.0

port = 3306

datadir = /home/mysql

tmpdir = /tmp

 

default_storage_engine = InnoDB

character_set_server = utf8

 

innodb_file_per_table = 1

innodb_log_file_size = 512M

innodb_log_files_in_group = 4

innodb_rollback_on_timeout = 1

 

slow_query_log = 1

slow_query_log_file =/var/log/mysql/mysql-slow.log

long_query_time = 1

#log-queries-not-using-indexes#這個參數不安全,說是記錄沒有用到索引的語句,其實記錄的所有的日誌,佔用大量的IO,建議不要打開

 

 

#relay_log_recovery=1#這個參數在叢庫上必定要加上

 

query_cache_type = off

query_cache_size = 0

#這兩項是禁用緩存,這個使服務器用途而定:寫比較多的數據庫最好禁用,由於沒寫一次他要修改緩存中的數據,給數據庫帶來額外的開銷,讀比較的能夠開啓,能夠提升查詢效率

 

#一下4個參數是mysql5.6上的新特性

innodb_buffer_pool_dump_at_shutdown = 1 #解釋:在關閉時把熱數據dump到本地磁盤。

innodb_buffer_pool_dump_now = 1 #解釋:採用手工方式把熱數據dump到本地磁盤。

innodb_buffer_pool_load_at_startup = 1 #解釋:在啓動時把熱數據加載到內存。

innodb_buffer_pool_load_now = 1 #解釋:採用手工方式把熱數據加載到內存。

 

read_buffer_size = 2M

sort_buffer_size = 2M

join_buffer_size = 1M

key_buffer_size = 2G 

 

thread_cache_size = 2048

open_files_limit=65535

innodb_open_files = 8192

 

max_allowed_packet = 64M

thread_stack = 512k

max_length_for_sort_data = 16k

tmp_table_size = 256M

max_heap_table_size = 256M

 

max_connections = 4000      

max_connect_errors = 30000

 

innodb_read_io_threads = 8

innodb_write_io_threads = 16

innodb_flush_method = O_DIRECT

innodb_io_capacity = 20000#根據硬盤的狀況修改,stat的用100sas200sasriad10的爲400fision-io的能夠設置爲20000

 

innodb_buffer_pool_size = 72G#內存的80%

innodb_buffer_pool_instances=18

 

thread_concurrency=0

innodb_thread_concurrency = 0

innodb_log_buffer_size = 16M

innodb_flush_log_at_trx_commit = 2

innodb_lock_wait_timeout = 60

 

innodb_old_blocks_time=1000

innodb_use_native_aio = 1

innodb_purge_threads=1

innodb_change_buffering=inserts

##############################################

 

2、sql語句的優化

    前期的配置優化作完,其實在很長的一段時間內,基本上不用在去優化了。而一條sql使用不當,導致整個數據庫故障的狀況相信作DBA的常常遇到。因此,sql語句的優化和審覈纔是每一個DBA的重中之重。

sql語句的優化,通常的基本原則有如下幾個方面:

 

一、  儘可能稍做計算

Mysql的做用是用來存取數據的,不是作計算的,作計算的話能夠用其餘方法去實現,mysql作計算是很耗資源的。

 

2.儘可能少 join

 

MySQL 的優點在於簡單,但這在某些方面其實也是其劣勢。MySQL 優化器效率高,可是因爲其統計信息的量有限,優化器工做過程出現誤差的可能性也就更多。對於複雜的多表 Join,一方面因爲其優化器受限,再者在 Join 這方面所下的功夫還不夠,因此性能表現離 Oracle 等關係型數據庫前輩仍是有必定距離。但若是是簡單的單表查詢,這一差距就會極小甚至在有些場景下要優於這些數據庫前輩。

 

3.儘可能少排序

 

  排序操做會消耗較多的 CPU 資源,因此減小排序能夠在緩存命中率高等 IO 能力足夠的場景下會較大影響 SQL 的響應時間。

  對於MySQL來講,減小排序有多種辦法,好比:

  經過利用索引來排序的方式進行優化

  減小參與排序的記錄條數

  非必要不對數據進行排序

 

4.儘可能避免 select *

 

  在數據量少而且訪問量不大的狀況下,select * 沒有什麼影響,可是量級達到必定級別的時候,在執行效率和IO資源的使用上,仍是有很大關係的,用什麼字段取什麼字段,減小沒必要要的資源浪費。

    以前遇到過由於一個字段存儲的數據比較大,併發高的狀況下把網絡帶寬跑滿的狀況,形成網站打不開或是打開速度極慢的狀況。

 

5.儘可能用 join 代替子查詢

 

  雖然 Join 性能並不佳,可是和 MySQL 的子查詢比起來仍是有很是大的性能優點。MySQL 的子查詢執行計劃一直存在較大的問題,雖然這個問題已經存在多年,可是到目前已經發布的全部穩定版本中都廣泛存在,一直沒有太大改善。雖然官方也在很早就認可這一問題,而且承諾儘快解決,可是至少到目前爲止咱們尚未看到哪個版本較好的解決了這一問題。

 

6.儘可能少 or

 

  當 where 子句中存在多個條件以「或」並存的時候,MySQL 的優化器並無很好的解決其執行計劃優化問題,再加上 MySQL 特有的 SQL Storage 分層架構方式,形成了其性能比較低下,不少時候使用 union all 或者是union(必要的時候)的方式來代替「or」會獲得更好的效果。

 

7.儘可能用 union all 代替 union

 

union union all 的差別主要是前者須要將兩個(或者多個)結果集合並後再進行惟一性過濾操做,這就會涉及到排序,增長大量的 CPU 運算,加大資源消耗及延遲。因此當咱們能夠確認不可能出現重複結果集或者不在意重複結果集的時候,儘可能使用 union all 而不是 union

 

8.儘可能早過濾

 

  這一優化策略其實最多見於索引的優化設計中(將過濾性更好的字段放得更靠前)

 

  在 SQL 編寫中一樣可使用這一原則來優化一些 Join SQL。好比咱們在多個表進行分頁數據查詢的時候,咱們最好是可以在一個表上先過濾好數據分好頁,而後再用分好頁的結果集與另外的表 Join,這樣能夠儘量多的減小沒必要要的 IO 操做,大大節省 IO 操做所消耗的時間。

 

9.避免類型轉換

 

  這裏所說的「類型轉換」是指 where 子句中出現 column 字段的類型和傳入的參數類型不一致的時候發生的類型轉換:

A:人爲在column_name 上經過轉換函數進行轉換

  直接致使 MySQL(實際上其餘數據庫也會有一樣的問題)沒法使用索引,若是非要轉換,應該在傳入的參數上進行轉換

B:由數據庫本身進行轉換

  若是咱們傳入的數據類型和字段類型不一致,同時咱們又沒有作任何類型轉換處理,MySQL 可能會本身對咱們的數據進行類型轉換操做,也可能不進行處理而交由存儲引擎去處理,這樣一來,就會出現索引沒法使用的狀況而形成執行計劃問題。

    以上兩種狀況在開發者由於某種緣由常常會有,原本能夠用到索引的結果類型不對沒有用到索引,或是由於類型不對又有越界的狀況發生形成沒法使用索引的狀況,結果形成很嚴重的事故。

 

10.優先優化高併發的 SQL,而不是執行頻率低某些「大」SQL

 

  對於破壞性來講,高併發的 SQL 老是會比低頻率的來得大,由於高併發的 SQL 一旦出現問題,甚至不會給咱們任何喘息的機會就會將系統壓跨。而對於一些雖然須要消耗大量 IO 並且響應很慢的 SQL,因爲頻率低,即便遇到,最多就是讓整個系統響應慢一點,但至少可能撐一下子,讓咱們有緩衝的機會。

 

11.從全局出發優化,而不是片面調整

 

SQL 優化不能是單獨針對某一個進行,而應充分考慮系統中全部的 SQL,尤爲是在經過調整索引優化 SQL 的執行計劃的時候,千萬不能顧此失彼,因小失大。

 

12.儘量對每一條運行在數據庫中的SQL進行 explain

 

優化 SQL,須要作到心中有數,知道SQL 的執行計劃才能判斷是否有優化餘地,才能判斷是否存在執行計劃問題。在對數據庫中運行的 SQL 進行了一段時間的優化以後,很明顯的問題 SQL 可能已經不多了,大多都須要去發掘,這時候就須要進行大量的 explain 操做收集執行計劃,並判斷是否須要進行優化。

 

題外話:不少剛接觸mysql的朋友問,有什麼mysql專業書籍推薦?我推薦《MySQL高性能》第三版,是mysql 領域的經典之做,擁有普遍的影響力,涵蓋的知識面也比較面,一本在手,基礎知識無憂,其餘須要在實戰中積累經驗了,本人也是此書的受益者。

相關文章
相關標籤/搜索