mysql性能優化的核心

在平時被問及最多的問題就是關於MySQL數據庫性能優化方面的問題,所以最近打算寫一個MySQL數據庫性能優化方面的系列文章,希望對初中級MySQL DBA以及其他對MySQL性能優化感興趣的朋友們有所幫助。

數據庫屬於IO密集型的應用程序,其主職責就是數據的管理及存儲工作。而我們知道,從內存中讀取一個數據庫的時間是微秒級別,而從一塊普通硬盤上讀取一個IO是在毫秒級別,二者相差3個數量級。所以,要優化數據庫,首先第一步需要優化的就是IO,儘可能將磁盤IO轉化爲內存IO。本文先從MySQL數據庫IO相關參數(緩存參數)的角度來看看可以通過哪些參數進行IO優化:

•query_cache_size/query_cache_type (global)

Query cache作用於整個MySQL Instance,主要用來緩存MySQL中的ResultSet,也就是一條SQL語句執行的結果集,所以僅僅只能針對select語句。當我們打開了 Query Cache功能,MySQL在接受到一條select語句的請求後,如果該語句滿足Query Cache的要求(未顯式說明不允許使用Query Cache,或者已經顯式申明需要使用Query Cache),MySQL會直接根據預先設定好的HASH算法將接受到的select語句以字符串方式進行hash,然後到Query Cache中直接查找是否已經緩存。也就是說,如果已經在緩存中,該select請求就會直接將數據返回,從而省略了後面所有的步驟(如SQL語句的解析,優化器優化以及向存儲引擎請求數據等),極大的提高性能。

當然,Query Cache也有一個致命的缺陷,那就是當某個表的數據有任何任何變化,都會導致所有引用了該表的select語句在Query Cache中的緩存數據失效。所以,當我們的數據變化非常頻繁的情況下,使用Query Cache可能會得不償失。

Query Cache的使用需要多個參數配合,其中最爲關鍵的是query_cache_size和query_cache_type,前者設置用於緩存ResultSet的內存大小,後者設置在何場景下使用Query Cache。在以往的經驗來看,如果不是用來緩存基本不變的數據的MySQL數據庫,query_cache_size一般256MB是一個比較合適的大小。當然,這可以通過計算Query Cache的命中率(Qcache_hits/(Qcache_hits+Qcache_inserts)*100))來進行調整。query_cache_type可以設置爲0(OFF),1(ON)或者2(DEMOND),分別表示完全不使用query cache,除顯式要求不使用query cache(使用sql_no_cache)之外的所有的select都使用query cache,只有顯示要求才使用query cache(使用sql_cache)。

•binlog_cache_size (global)

Binlog Cache用於在打開了二進制日誌(binlog)記錄功能的環境,是MySQL用來提高binlog的記錄效率而設計的一個用於短時間內臨時緩存binlog數據的內存區域。

一般來說,如果我們的數據庫中沒有什麼大事務,寫入也不是特別頻繁,2MB~4MB是一個合適的選擇。但是如果我們的數據庫大事務較多,寫入量比較大,可與適當調高binlog_cache_size。同時,我們可以通過binlog_cache_use以及binlog_cache_disk_use來分析設置的binlog_cache_size是否足夠,是否有大量的binlog_cache由於內存大小不夠而使用臨時文件(binlog_cache_disk_use)來緩存了。

•key_buffer_size(global)

Key Buffer可能是大家最爲熟悉的一個MySQL緩存參數了,尤其是在MySQL沒有更換默認存儲引擎的時候,很多朋友可能會發現,默認的MySQL配置文件中設置最大的一個內存參數就是這個參數了。key_buffer_size參數用來設置用於緩存MyISAM存儲引擎中索引文件的內存區域大小。如果我們有足夠的內存,這個緩存區域最好是能夠存放下我們所有的MyISAM引擎表的所有索引,以儘可能提高性能。

此外,當我們在使用MyISAM存儲的時候有一個及其重要的點需要注意,由於MyISAM引擎的特性限制了他僅僅只會緩存索引塊到內存中,而不會緩存表數據庫塊。所以,我們的SQL一定要儘可能讓過濾條件都在索引中,以便讓緩存幫助我們提高查詢效率。

•bulk_insert_buffer_size (thread)

和key_buffer_size一樣,這個參數同樣也僅作用於使用MyISAM存儲引擎,用來緩存批量插入數據的時候臨時緩存寫入數據。當我們使用如下幾種數據寫入語句的時候,會使用這個內存區域來緩存批量結構的數據以幫助批量寫入數據文件:

insert … select …

insert … values (…) ,(…),(…)…

load data infile… into… (非空表)

•innodb_buffer_pool_size(global)

當我們使用InnoDB存儲引擎的時候,innodb_buffer_pool_size參數可能是影響我們性能的最爲關鍵的一個參數了,他用來設置用於緩存InnoDB索引及數據塊的內存區域大小,類似於MyISAM存儲引擎的key_buffer_size參數,當然,可能更像是Oracle的db_cache_size。簡單來說,當我們操作一個InnoDB表的時候,返回的所有數據或者去數據過程中用到的任何一個索引塊,都會在這個內存區域中走一遭。

和key_buffer_size對於MyISAM引擎一樣,innodb_buffer_pool_size設置了InnoDB存儲引擎需求最大的一塊內存區域的大小,直接關係到InnoDB存儲引擎的性能,所以如果我們有足夠的內存,儘可將該參數設置到足夠打,將盡可能多的InnoDB的索引及數據都放入到該緩存區域中,直至全部。

我們可以通過(Innodb_buffer_pool_read_requests – Innodb_buffer_pool_reads) / Innodb_buffer_pool_read_requests * 100%計算緩存命中率,並根據命中率來調整innodb_buffer_pool_size參數大小進行優化。

•innodb_additional_mem_pool_size(global)

這個參數我們平時調整的可能不是太多,很多人都使用了默認值,可能很多人都不是太熟悉這個參數的作用。innodb_additional_mem_pool_size設置了InnoDB存儲引擎用來存放數據字典信息以及一些內部數據結構的內存空間大小,所以當我們一個MySQL Instance中的數據庫對象非常多的時候,是需要適當調整該參數的大小以確保所有數據都能存放在內存中提高訪問效率的。

這個參數大小是否足夠還是比較容易知道的,因爲當過小的時候,MySQL會記錄Warning信息到數據庫的error log中,這時候你就知道該調整這個參數大小了。

•innodb_log_buffer_size (global)

這是InnoDB存儲引擎的事務日誌所使用的緩衝區。類似於Binlog Buffer,InnoDB在寫事務日誌的時候,爲了提高性能,也是先將信息寫入Innofb Log Buffer中,當滿足innodb_flush_log_trx_commit參數所設置的相應條件(或者日誌緩衝區寫滿)之後,纔會將日誌寫到文件(或者同步到磁盤)中。可以通過innodb_log_buffer_size 參數設置其可以使用的最大內存空間。

注:innodb_flush_log_trx_commit參數對InnoDB Log的寫入性能有非常關鍵的影響。該參數可以設置爲0,1,2,解釋如下:

0:log buffer中的數據將以每秒一次的頻率寫入到log file中,且同時會進行文件系統到磁盤的同步操作,但是每個事務的commit並不會觸發任何log buffer 到log file的刷新或者文件系統到磁盤的刷新操作;

1:在每次事務提交的時候將log buffer 中的數據都會寫入到log file,同時也會觸發文件系統到磁盤的同步;

2:事務提交會觸發log buffer到log file的刷新,但並不會觸發磁盤文件系統到磁盤的同步。此外,每秒會有一次文件系統到磁盤同步操作。

此外,MySQL文檔中還提到,這幾種設置中的每秒同步一次的機制,可能並不會完全確保非常準確的每秒就一定會發生同步,還取決於進程調度的問題。實際上,InnoDB能否真正滿足此參數所設置值代表的意義正常Recovery還是受到了不同OS下文件系統以及磁盤本身的限制,可能有些時候在並沒有真正完成磁盤同步的情況下也會告訴mysqld 已經完成了磁盤同步。

•innodb_max_dirty_pages_pct (global)

這個參數和上面的各個參數不同,他不是用來設置用於緩存某種數據的內存大小的一個參數,而是用來控制在InnoDB Buffer Pool中可以不用寫入數據文件中的Dirty Page的比例(已經被修但還沒有從內存中寫入到數據文件的髒數據)。這個比例值越大,從內存到磁盤的寫入操作就會相對減少,所以能夠一定程度下減少寫入操作的磁盤IO。

但是,如果這個比例值過大,當數據庫Crash之後重啓的時間可能就會很長,因爲會有大量的事務數據需要從日誌文件恢復出來寫入數據文件中。同時,過大的比例值同時可能也會造成在達到比例設定上限後的flush操作“過猛”而導致性能波動很大。

上面這幾個參數是MySQL中爲了減少磁盤物理IO而設計的主要參數,對MySQL的性能起到了至關重要的作用。 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章