MySQL 性能優化的那點事兒

1、MySQL的主要適用場景html

一、Web網站系統web

二、日誌記錄系統算法

三、數據倉庫系統數據庫

四、嵌入式系統緩存


2、MySQL架構圖安全


94d17e5cb90b24e91c8c75e67e8877c3.jpeg


3、MySQL存儲引擎概述性能優化


1)MyISAM存儲引擎服務器


MyISAM存儲引擎的表在數據庫中,每個表都被存放爲三個以表名命名的物理文件。首先確定會有任何存儲引擎都不可缺乏的存放表結構定義信息的.frm文件,另外還有.MYD和.MYI文件,分別存放了表的數據(.MYD)和索引數據(.MYI)。每一個表都有且僅有這樣三個文件作爲MyISAM存儲類型的表的存儲,也就是說無論這個表有多少個索引,都是存放在同一個.MYI文件中。網絡


MyISAM支持如下三種類型的索引:數據結構


一、B-Tree索引


B-Tree索引,顧名思義,就是全部的索引節點都按照balancetree的數據結構來存儲,全部的索引數據節點都在葉節點。


二、R-Tree索引


R-Tree索引的存儲方式和b-tree索引有一些區別,主要設計用於爲存儲空間和多維數據的字段作索引,因此目前的MySQL版原本說,也僅支持geometry類型的字段做索引。


三、Full-text索引


Full-text索引就是咱們長說的全文索引,他的存儲結構也是b-tree。主要是爲了解決在咱們須要用like查詢的低效問題。


2)Innodb 存儲引擎


一、支持事務安裝

二、數據多版本讀取

三、鎖定機制的改進

四、實現外鍵


3)NDBCluster存儲引擎


NDB存儲引擎也叫NDBCluster存儲引擎,主要用於MySQLCluster分佈式集羣環境,Cluster是MySQL從5.0版本纔開始提供的新功能。


4)Merge存儲引擎


MERGE存儲引擎,在MySQL用戶手冊中也提到了,也被你們認識爲MRG_MyISAM引擎。Why?由於MERGE存儲引擎能夠簡單的理解爲其功能就是實現了對結構相同的MyISAM表,經過一些特殊的包裝對外提供一個單一的訪問入口,以達到減少應用的複雜度的目的。要建立MERGE表,不只僅基表的結構要徹底一致,包括字段的順序,基表的索引也必須徹底一致。


5)Memory存儲引擎


Memory存儲引擎,經過名字就很容易讓人知道,他是一個將數據存儲在內存中的存儲引擎。Memory存儲引擎不會將任何數據存放到磁盤上,僅僅存放了一個表結構相關信息的.frm文件在磁盤上面。因此一旦MySQLCrash或者主機Crash以後,Memory的表就只剩下一個結構了。Memory表支持索引,而且同時支持Hash和B-Tree兩種格式的索引。因爲是存放在內存中,因此Memory都是按照定長的空間來存儲數據的,並且不支持BLOB和TEXT類型的字段。Memory存儲引擎實現頁級鎖定。


6)BDB存儲引擎


BDB存儲引擎全稱爲BerkeleyDB存儲引擎,和Innodb同樣,也不是MySQL本身開發實現的一個存儲引擎,而是由SleepycatSoftware所提供,固然,也是開源存儲引擎,一樣支持事務安全。


7)FEDERATED存儲引擎


FEDERATED存儲引擎所實現的功能,和Oracle的DBLINK基本類似,主要用來提供對遠程MySQL服務器上面的數據的訪問接口。若是咱們使用源碼編譯來安裝MySQL,那麼必須手工指定啓用FEDERATED存儲引擎才行,由於MySQL默認是不起用該存儲引擎的。


8)ARCHIVE存儲引擎


ARCHIVE存儲引擎主要用於經過較小的存儲空間來存放過時的不多訪問的歷史數據。ARCHIVE表不支持索引,經過一個.frm的結構定義文件,一個.ARZ的數據壓縮文件還有一個.ARM的meta信息文件。因爲其所存放的數據的特殊性,ARCHIVE表不支持刪除,修改操


做,僅支持插入和查詢操做。鎖定機制爲行級鎖定。


9)BLACKHOLE存儲引擎


BLACKHOLE存儲引擎是一個很是有意思的存儲引擎,功能恰如其名,就是一個「黑洞」。就像咱們unix系統下面的「/dev/null」設備同樣,無論咱們寫入任何信息,都是有去無回。


10)CSV存儲引擎


CSV存儲引擎實際上操做的就是一個標準的CSV文件,他不支持索引。起主要用途就是你們有些時候可能會須要經過數據庫中的數據導出成一份報表文件,而CSV文件是不少軟件都支持的一種較爲標準的格式,因此咱們能夠經過先在數據庫中創建一張CVS表,而後將生成的報表信息插入到該表,便可獲得一份CSV報表文件了。


4、影響MySQLServer性能的相關因素


1 商業需求對性能的影響


典型需求:一個論壇帖子總量的統計,要求:實時更新。


2 系統架構及實現對性能的影響


如下幾類數據都是不適合在數據庫中存放的:


二進制多媒體數據

流水隊列數據

超大文本數據


經過Cache技術來提升系統性能:


系統各類配置及規則數據;

活躍用戶的基本信息數據;

活躍用戶的個性化定製信息數據;

準實時的統計信息數據;

其餘一些訪問頻繁但變動較少的數據;


3 Query語句對系統性能的影響


需求:取出某個group(假設id爲1)下的用戶編號(id),用戶暱稱(nick_name),並按照加入組的時間(user_group.gmt_create)來進行倒序排列,取出前20個。


解決方案一:


SELECT id,nick_name FROM user,user_group WHERE user_group.group_id=1 and user_group.user_id=user.id ORDER BY user_group.gmt_create desc limit 100,20;


解決方案二:


SELECT user.id,user.nick_name FROM(SELECT user_idFROM user_groupWHERE user_group.group_id=1ORDER BY gmt_create desclimit 100,20)t,userWHERE t.user_id=user.id;


經過比較兩個解決方案的執行計劃,咱們能夠看到第一中解決方案中須要和user表參與Join的記錄數MySQL經過統計數據估算出來是31156,也就是經過user_group表返回的全部知足group_id=1的記錄數(系統中的實際數據是20000)。而第二種解決方案的執行計劃中,user表參與Join的數據就只有20條,二者相差很大,咱們認爲第二中解決方案應該明顯優於第一種解決方案。


4 Schema設計對系統的性能影響


儘可能減小對數據庫訪問的請求。

儘可能減小無用數據的查詢請求。


5 硬件環境對系統性能的影響


一、典型OLTP應用系統


對於各類數據庫系統環境中你們最多見的OLTP系統,其特色是併發量大,總體數據量比較多,但每次訪問的數據比較少,且訪問的數據比較離散,活躍數據佔整體數據的比例不是太大。對於這類系統的數據庫其實是最難維護,最難以優化的,對主機總體性能要求也是最高的。由於不只訪問量很高,數據量也不小。


針對上面的這些特色和分析,咱們能夠對OLTP的得出一個大體的方向。


雖然系統整體數據量較大,可是系統活躍數據在數據總量中所佔的比例不大,那麼咱們能夠經過擴大內存容量來儘量多的將活躍數據cache到內存中;


雖然IO訪問很是頻繁,可是每次訪問的數據量較少且很離散,那麼咱們對磁盤存儲的要求是IOPS表現要很好,吞吐量是次要因素;


併發量很高,CPU每秒所要處理的請求天然也就不少,因此CPU處理能力須要比較強勁;


雖然與客戶端的每次交互的數據量並非特別大,可是網絡交互很是頻繁,因此主機與客戶端交互的網絡設備對流量能力也要求不能太弱。


二、典型OLAP應用系統


用於數據分析的OLAP系統的主要特色就是數據量很是大,併發訪問很少,但每次訪問所須要檢索的數據量都比較多,並且數據訪問相對較爲集中,沒有太明顯的活躍數據概念。


基於OLAP系統的各類特色和相應的分析,針對OLAP系統硬件優化的大體策略以下:


數據量很是大,因此磁盤存儲系統的單位容量須要儘可能大一些;


單次訪問數據量較大,並且訪問數據比較集中,那麼對IO系統的性能要求是須要有儘量大的每秒IO吞吐量,因此應該選用每秒吞吐量儘量大的磁盤;


雖然IO性能要求也比較高,可是併發請求較少,因此CPU處理能力較難成爲性能瓶頸,因此CPU處理能力沒有太苛刻的要求;


雖然每次請求的訪問量很大,可是執行過程當中的數據大都不會返回給客戶端,最終返回給客戶端的數據量都較小,因此和客戶端交互的網絡設備要求並非過高;


此外,因爲OLAP系統因爲其每次運算過程較長,能夠很好的並行化,因此通常的OLAP系統都是由多臺主機構成的一個集羣,而集羣中主機與主機之間的數據交互量通常來講都是很是大的,因此在集羣中主機之間的網絡設備要求很高。


三、除了以上兩個典型應用以外,還有一類比較特殊的應用系統,他們的數據量不是特別大,可是訪問請求及其頻繁,並且大部分是讀請求。可能每秒須要提供上萬甚至幾萬次請求,每次請求都很是簡單,可能大部分都只有一條或者幾條比較小的記錄返回,就好比基於數據庫的DNS服務就是這樣類型的服務。

雖然數據量小,可是訪問極其頻繁,因此能夠經過較大的內存來cache住大部分的數據,這可以保證很是高的命中率,磁盤IO量比較小,因此磁盤也不須要特別高性能的;


併發請求很是頻繁,比須要較強的CPU處理能力才能處理;


雖然應用與數據庫交互量很是大,可是每次交互數據較少,整體流量雖然也會較大,可是通常來講普通的千兆網卡已經足夠了。


5、MySQL 鎖定機制簡介


行級鎖定(row-level)

表級鎖定(table-level)

頁級鎖定(page-level)


在MySQL數據庫中,使用表級鎖定的主要是MyISAM,Memory,CSV等一些非事務性存儲引擎,而使用行級鎖定的主要是Innodb存儲引擎和NDBCluster存儲引擎,頁級鎖定主要是BerkeleyDB存儲引擎的鎖定方式。


6、MySQL Query的優化


Query語句的優化思路和原則主要提如今如下幾個方面:


1. 優化更須要優化的Query;

2. 定位優化對象的性能瓶頸;

3. 明確的優化目標;

4. 從Explain入手;

5. 多使用profile

6. 永遠用小結果集驅動大的結果集;

7. 儘量在索引中完成排序;

8. 只取出本身須要的Columns;

9. 僅僅使用最有效的過濾條件;

10.儘量避免複雜的Join和子查詢;


合理設計並利用索引


1)B-Tree索引


通常來講,MySQL中的B-Tree索引的物理文件大多都是以BalanceTree的結構來存儲的,也就是全部實際須要的數據都存放於Tree的LeafNode,並且到任何一個LeafNode的最短路徑的長度都是徹底相同的,因此咱們你們都稱之爲B-Tree索引固然,可能各類數據庫(或MySQL的各類存儲引擎)在存放本身的B-Tree索引的時候會對存儲結構稍做改造。如Innodb存儲引擎的B-Tree索引實際使用的存儲結構其實是B+Tree,也就是在B-Tree數據結構的基礎上作了很小的改造,在每個LeafNode上面出了存放索引鍵的相關信息以外,還存儲了指向與該LeafNode相鄰的後一個LeafNode的指針信息,這主要是爲了加快檢索多個相鄰LeafNode的效率考慮。


2)Hash索引


Hash索引在MySQL中使用的並非不少,目前主要是Memory存儲引擎使用,並且在Memory存儲引擎中將Hash索引做爲默認的索引類型。所謂Hash索引,實際上就是經過必定的Hash算法,將須要索引的鍵值進行Hash運算,而後將獲得的Hash值存入一個Hash表中。而後每次須要檢索的時候,都會將檢索條件進行相同算法的Hash運算,而後再和Hash表中的Hash值進行比較並得出相應的信息。


Hash索引僅僅只能知足「=」,「IN」和「<=>」查詢,不能使用範圍查詢;


Hash索引沒法被利用來避免數據的排序操做;


Hash索引不能利用部分索引鍵查詢;


Hash索引在任什麼時候候都不能避免表掃面;


Hash索引遇到大量Hash值相等的狀況後性能並不必定就會比B-Tree索引高;


3)Full-text索引


Full-text索引也就是咱們常說的全文索引,目前在MySQL中僅有MyISAM存儲引擎支持,並且也並非全部的數據類型都支持全文索引。目前來講,僅有CHAR,VARCHAR和TEXT這三種數據類型的列能夠建Full-text索引。


索引可以極大的提升數據檢索效率,也可以改善排序分組操做的性能,可是咱們不能忽略的一個問題就是索引是徹底獨立於基礎數據以外的一部分數據,更新數據會帶來的IO量和調整索引所致的計算量的資源消耗。


是否須要建立索引,幾點原則:較頻繁的做爲查詢條件的字段應該建立索引;惟一性太差的字段不適合單首創建索引,即便頻繁做爲查詢條件;更新很是頻繁的字段不適合建立索引;


不會出如今WHERE子句中的字段不應建立索引;


Join語句的優化


儘量減小Join語句中的NestedLoop的循環總次數;「永遠用小結果集驅動大的結果集」。


優先優化NestedLoop的內層循環;


保證Join語句中被驅動表上Join條件字段已經被索引;


當沒法保證被驅動表的Join條件字段被索引且內存資源充足的前提下,不要太吝惜JoinBuffer的設置;


ORDER BY,GROUP BY和DISTINCT優化


1)ORDER BY的實現與優化


優化Query語句中的ORDER BY的時候,儘量利用已有的索引來避免實際的排序計算,能夠很大幅度的提高ORDER BY操做的性能。


優化排序:


1.加大max_length_for_sort_data參數的設置;

2.去掉沒必要要的返回字段;

3.增大sort_buffer_size參數設置;


2)GROUP BY的實現與優化


因爲GROUP BY實際上也一樣須要進行排序操做,並且與ORDER BY相比,GROUP BY主要只是多了排序以後的分組操做。固然,若是在分組的時候還使用了其餘的一些聚合函數,那麼還須要一些聚合函數的計算。因此,在GROUP BY的實現過程當中,與ORDER BY同樣也能夠利用到索引。


3)DISTINCT的實現與優化


DISTINCT實際上和GROUP BY的操做很是類似,只不過是在GROUP BY以後的每組中只取出一條記錄而已。因此,DISTINCT的實現和GROUP BY的實現也基本差很少,沒有太大的區別。一樣能夠經過鬆散索引掃描或者是緊湊索引掃描來實現,固然,在沒法僅僅使用索引即能完成DISTINCT的時候,MySQL只能經過臨時表來完成。可是,和GROUP BY有一點差異的是,DISTINCT並不須要進行排序。也就是說,在僅僅只是DISTINCT操做的Query若是沒法僅僅利用索引完成操做的時候,MySQL會利用臨時表來作一次數據的「緩存」,可是不會對臨時表中的數據進行filesort操做。


7、MySQL數據庫Schema設計的性能優化


高效的模型設計


適度冗餘-讓Query儘可能減小Join


大字段垂直分拆-summary表優化


大表水平分拆-基於類型的分拆優化


統計表-準實時優化


合適的數據類型


75d91a6f0f8712294ed731bc1cef8649.webp


時間存儲格式總類並非太多,咱們經常使用的主要就是DATETIME,DATE和TIMESTAMP這三種了。從存儲空間來看TIMESTAMP最少,四個字節,而其餘兩種數據類型都是八個字節,多了一倍。而TIMESTAMP的缺點在於他只能存儲從1970年以後的時間,而另外兩種時間類型能夠存放最先從1001年開始的時間。若是有須要存放早於1970年以前的時間的需求,咱們必須放棄TIMESTAMP類型,可是隻要咱們不須要使用1970年以前的時間,最好儘可能使用TIMESTAMP來減小存儲空間的佔用。


字符存儲類型


CHAR[(M)]類型屬於靜態長度類型,存放長度徹底以字符數來計算,因此最終的存儲長度是基於字符集的,如latin1則最大存儲長度爲255字節,可是若是使用gbk則最大存儲長度爲510字節。CHAR類型的存儲特色是無論咱們實際存放多長數據,在數據庫中都會存放M個字符,不夠的經過空格補上,M默認爲1。雖然CHAR會經過空格補齊存放的空間,可是在訪問數據的時候,MySQL會忽略最後的全部空格,因此若是咱們的實際數據中若是在最後確實須要空格,則不能使用CHAR類型來存放。


VARCHAR[(M)]屬於動態存儲長度類型,僅存佔用實際存儲數據的長度。TINYTEXT,TEXT,MEDIUMTEXT和LONGTEXT這四種類型同屬於一種存儲方式,都是動態存儲長度類型,不一樣的僅僅是最大長度的限制。


事務優化


1. 髒讀:髒讀就是指當一個事務正在訪問數據,而且對數據進行了修改,而這種修改尚未提交到數據庫中,這時,另一個事務也訪問這個數據,而後使用了這個數據。


2. 不可重複讀:是指在一個事務內,屢次讀同一數據。在這個事務尚未結束時,另一個事務也訪問該同一數據。那麼,在第一個事務中的兩次讀數據之間,因爲第二個事務的修改,那麼第一個事務兩次讀到的的數據多是不同的。這樣就發生了在一個事務內兩次讀到的數據是不同的,所以稱爲是不可重複讀。


3. 幻讀:是指當事務不是獨立執行時發生的一種現象,例如第一個事務對一個表中的數據進行了修改,這種修改涉及到表中的所有數據行。同時,第二個事務也修改這個表中的數據,這種修改是向表中插入一行新數據。那麼,之後就會發生操做第一個事務的用戶發現表中還有沒有修改的數據行,就好象發生了幻覺同樣。


Innodb在事務隔離級別方面支持的信息以下:


1.READ UNCOMMITTED


常被成爲Dirty Reads(髒讀),能夠說是事務上的最低隔離級別:在普通的非鎖定模式下SELECT的執行使咱們看到的數據可能並非查詢發起時間點的數據,於是在這個隔離度下是非Consistent Reads(一致性讀);


2.READ COMMITTED


這一隔離級別下,不會出現DirtyRead,可是可能出現Non-RepeatableReads(不可重複讀)和PhantomReads(幻讀)。


3. REPEATABLE READ


REPEATABLE READ隔離級別是InnoDB默認的事務隔離級。在REPEATABLE READ隔離級別下,不會出現DirtyReads,也不會出現Non-Repeatable Read,可是仍然存在PhantomReads的可能性。


4.SERIALIZABLE


SERIALIZABLE隔離級別是標準事務隔離級別中的最高級別。設置爲SERIALIZABLE隔離級別以後,在事務中的任什麼時候候所看到的數據都是事務啓動時刻的狀態,不論在這期間有沒有其餘事務已經修改了某些數據並提交。因此,SERIALIZABLE事務隔離級別下,PhantomReads也不會出現。


8、可擴展性設計之數據切分


數據的垂直切分


數據的垂直切分,也能夠稱之爲縱向切分。將數據庫想象成爲由不少個一大塊一大塊的「數據塊」(表)組成,咱們垂直的將這些「數據塊」切開,而後將他們分散到多臺數據庫主機上面。這樣的切分方法就是一個垂直(縱向)的數據切分。


垂直切分的優勢


◆數據庫的拆分簡單明瞭,拆分規則明確;


◆應用程序模塊清晰明確,整合容易;


◆數據維護方便易行,容易定位;


垂直切分的缺點


◆部分表關聯沒法在數據庫級別完成,須要在程序中完成;


◆對於訪問極其頻繁且數據量超大的表仍然存在性能平靜,不必定能知足要求;


◆事務處理相對更爲複雜;


◆切分達到必定程度以後,擴展性會遇到限制;


◆過讀切分可能會帶來系統過渡複雜而難以維護。


數據的水平切分


數據的垂直切分基本上能夠簡單的理解爲按照表按照模塊來切分數據,而水平切分就再也不是按照表或者是功能模塊來切分了。通常來講,簡單的水平切分主要是將某個訪問極其平凡的表再按照某個字段的某種規則來分散到多個表之中,每一個表中包含一部分數據。


水平切分的優勢


◆表關聯基本可以在數據庫端所有完成;


◆不會存在某些超大型數據量和高負載的表遇到瓶頸的問題;


◆應用程序端總體架構改動相對較少;


◆事務處理相對簡單;


◆只要切分規則可以定義好,基本上較難遇到擴展性限制;


水平切分的缺點


◆切分規則相對更爲複雜,很難抽象出一個可以知足整個數據庫的切分規則;


◆後期數據的維護難度有所增長,人爲手工定位數據更困難;


◆應用系統各模塊耦合度較高,可能會對後面數據的遷移拆分形成必定的困難。


數據切分與整合中可能存在的問題


1.引入分佈式事務的問題


徹底能夠將一個跨多個數據庫的分佈式事務分拆成多個僅處於單個數據庫上面的小事務,並經過應用程序來總控各個小事務。固然,這樣做的要求就是咱們的俄應用程序必需要有足夠的健壯性,固然也會給應用程序帶來一些技術難度。


2.跨節點Join的問題


推薦經過應用程序來進行處理,先在驅動表所在的MySQLServer中取出相應的驅動結果集,而後根據驅動結果集再到被驅動表所在的MySQL Server中取出相應的數據。


3.跨節點合併排序分頁問題


從多個數據源並行的取數據,而後應用程序彙總處理。


9、可擴展性設計之Cache與Search的利用


經過引入Cache(Redis、Memcached),減小數據庫的訪問,增長性能。

經過引入Search(Lucene、Solr、ElasticSearch),利用搜索引擎高效的全文索引和分詞算法,以及高效的數據檢索實現,來解決數據庫和傳統的Cache軟件徹底沒法解決的全文模糊搜索、分類統計查詢等功能。


69798b8be115860bdb467b712ee00d2a.jpeg

本文乃《MySQL性能調優與架構設計》讀書筆記!


連接:http://www.cnblogs.com/luxiaoxun/p/4694144.html

做者:阿凡盧

出處:http://www.cnblogs.com/luxiaoxun/

相關文章
相關標籤/搜索