1. 程式人生 > >MySQL效能優化總結___本文乃《MySQL效能調優與架構設計》讀書筆記!

MySQL效能優化總結___本文乃《MySQL效能調優與架構設計》讀書筆記!

一、MySQL的主要適用場景

1、Web網站系統

2、日誌記錄系統

3、資料倉庫系統

4、嵌入式系統

二、MySQL架構圖:

 

三、MySQL儲存引擎概述

1MyISAM儲存引擎

MyISAM儲存引擎的表在資料庫中,每一個表都被存放為三個以表名命名的物理檔案。首先肯定會有任何儲存引擎都不可缺少的存放表結構定義資訊的.frm檔案,另外還有.MYD和.MYI檔案,分別存放了表的資料(.MYD)和索引資料(.MYI)。每個表都有且僅有這樣三個檔案做為MyISAM儲存型別的表的儲存,也就是說不管這個表有多少個索引,都是存放在同一個.MYI檔案中。

MyISAM支援以下三種類型的索引:

1、B-Tree索引

B-Tree索引,顧名思義,就是所有的索引節點都按照balancetree的資料結構來儲存,所有的索引資料節點都在葉節點。

2、R-Tree索引

R-Tree索引的儲存方式和b-tree索引有一些區別,主要設計用於為儲存空間和多維資料的欄位做索引,所以目前的MySQL版本來說,也僅支援geometry型別的欄位作索引。

3、Full-text索引

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

2Innodb 

儲存引擎

1、支援事務安裝

2、資料多版本讀取

3、鎖定機制的改進

4、實現外來鍵

3NDBCluster儲存引擎

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

4Merge儲存引擎

MERGE儲存引擎,在MySQL使用者手冊中也提到了,也被大家認識為MRG_MyISAM引擎。Why?因為MERGE儲存引擎可以簡單的理解為其功能就是實現了對結構相同的MyISAM表,通過一些特殊的包裝對外提供一個單一的訪問入口,以達到減小應用的複雜度的目的。要建立MERGE表,不僅僅基表的結構要完全一致,包括欄位的順序,基表的索引也必須完全一致。

5Memory儲存引擎

Memory儲存引擎,通過名字就很容易讓人知道,他是一個將資料儲存在記憶體中的儲存引擎。Memory儲存引擎不會將任何資料存放到磁碟上,僅僅存放了一個表結構相關資訊的.frm檔案在磁碟上面。所以一旦MySQLCrash或者主機Crash之後,Memory的表就只剩下一個結構了。Memory表支援索引,並且同時支援Hash和B-Tree兩種格式的索引。由於是存放在記憶體中,所以Memory都是按照定長的空間來儲存資料的,而且不支援BLOB和TEXT型別的欄位。Memory儲存引擎實現頁級鎖定。

6BDB儲存引擎

BDB儲存引擎全稱為BerkeleyDB儲存引擎,和Innodb一樣,也不是MySQL自己開發實現的一個儲存引擎,而是由SleepycatSoftware所提供,當然,也是開源儲存引擎,同樣支援事務安全。

7FEDERATED儲存引擎

FEDERATED儲存引擎所實現的功能,和Oracle的DBLINK基本相似,主要用來提供對遠端MySQL伺服器上面的資料的訪問介面。如果我們使用原始碼編譯來安裝MySQL,那麼必須手工指定啟用FEDERATED儲存引擎才行,因為MySQL預設是不起用該儲存引擎的。

8ARCHIVE儲存引擎

ARCHIVE儲存引擎主要用於通過較小的儲存空間來存放過期的很少訪問的歷史資料。ARCHIVE表不支援索引,通過一個.frm的結構定義檔案,一個.ARZ的資料壓縮檔案還有一個.ARM的meta資訊檔案。由於其所存放的資料的特殊性,ARCHIVE表不支援刪除,修改操

作,僅支援插入和查詢操作。鎖定機制為行級鎖定。

9BLACKHOLE儲存引擎

BLACKHOLE儲存引擎是一個非常有意思的儲存引擎,功能恰如其名,就是一個“黑洞”。就像我們unix系統下面的“/dev/null”裝置一樣,不管我們寫入任何資訊,都是有去無回。

10CSV儲存引擎

CSV儲存引擎實際上操作的就是一個標準的CSV檔案,他不支援索引。起主要用途就是大家有些時候可能會需要通過資料庫中的資料匯出成一份報表檔案,而CSV檔案是很多軟體都支援的一種較為標準的格式,所以我們可以通過先在資料庫中建立一張CVS表,然後將生成的報表資訊插入到該表,即可得到一份CSV報表檔案了。

四、影響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_id
FROM user_group
WHERE user_group.group_id=1
ORDER BY gmt_create desc
limit 100,20)t,user
WHERE t.user_id=user.id;
複製程式碼

通過比較兩個解決方案的執行計劃,我們可以看到第一中解決方案中需要和user表參與Join的記錄數MySQL通過統計資料估算出來是31156,也就是通過user_group表返回的所有滿足group_id=1的記錄數(系統中的實際資料是20000)。而第二種解決方案的執行計劃中,user表參與Join的資料就只有20條,兩者相差很大,我們認為第二中解決方案應該明顯優於第一種解決方案。

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

儘量減少對資料庫訪問的請求。

儘量減少無用資料的查詢請求。

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

1、典型OLTP應用系統

對於各種資料庫系統環境中大家最常見的OLTP系統,其特點是併發量大,整體資料量比較多,但每次訪問的資料比較少,且訪問的資料比較離散,活躍資料佔總體資料的比例不是太大。對於這類系統的資料庫實際上是最難維護,最難以優化的,對主機整體效能要求也是最高的。因為不僅訪問量很高,資料量也不小。

針對上面的這些特點和分析,我們可以對OLTP的得出一個大致的方向。

雖然系統總體資料量較大,但是系統活躍資料在資料總量中所佔的比例不大,那麼我們可以通過擴大記憶體容量來儘可能多的將活躍資料cache到記憶體中;

雖然IO訪問非常頻繁,但是每次訪問的資料量較少且很離散,那麼我們對磁碟儲存的要求是IOPS表現要很好,吞吐量是次要因素;

併發量很高,CPU每秒所要處理的請求自然也就很多,所以CPU處理能力需要比較強勁;

雖然與客戶端的每次互動的資料量並不是特別大,但是網路互動非常頻繁,所以主機與客戶端互動的網路裝置對流量能力也要求不能太弱。

2、典型OLAP應用系統

用於資料分析的OLAP系統的主要特點就是資料量非常大,併發訪問不多,但每次訪問所需要檢索的資料量都比較多,而且資料訪問相對較為集中,沒有太明顯的活躍資料概念。

基於OLAP系統的各種特點和相應的分析,針對OLAP系統硬體優化的大致策略如下:

資料量非常大,所以磁碟儲存系統的單位容量需要儘量大一些;

單次訪問資料量較大,而且訪問資料比較集中,那麼對IO系統的效能要求是需要有儘可能大的每秒IO吞吐量,所以應該選用每秒吞吐量儘可能大的磁碟;

雖然IO效能要求也比較高,但是併發請求較少,所以CPU處理能力較難成為效能瓶頸,所以CPU處理能力沒有太苛刻的要求;

雖然每次請求的訪問量很大,但是執行過程中的資料大都不會返回給客戶端,最終返回給客戶端的資料量都較小,所以和客戶端互動的網路裝置要求並不是太高;

此外,由於OLAP系統由於其每次運算過程較長,可以很好的並行化,所以一般的OLAP系統都是由多臺主機構成的一個叢集,而叢集中主機與主機之間的資料互動量一般來說都是非常大的,所以在叢集中主機之間的網路裝置要求很高。

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

雖然資料量小,但是訪問極其頻繁,所以可以通過較大的記憶體來cache住大部分的資料,這能夠保證非常高的命中率,磁碟IO量比較小,所以磁碟也不需要特別高效能的;

併發請求非常頻繁,比需要較強的CPU處理能力才能處理;

雖然應用與資料庫互動量非常大,但是每次互動資料較少,總體流量雖然也會較大,但是一般來說普通的千兆網絡卡已經足夠了。

五、MySQL 鎖定機制簡介

行級鎖定(row-level)

表級鎖定(table-level)

頁級鎖定(page-level)

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

六、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 BYGROUP BYDISTINCT優化

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操作。

七、MySQL資料庫Schema設計的效能優化

高效的模型設計

適度冗餘-讓Query盡兩減少Join

大欄位垂直分拆-summary表優化

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

統計表-準實時優化

合適的資料型別

時間儲存格式總類並不是太多,我們常用的主要就是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也不會出現。

八、可擴充套件性設計之資料切分

資料的垂直切分

資料的垂直切分,也可以稱之為縱向切分。將資料庫想象成為由很多個一大塊一大塊的“資料塊”(表)組成,我們垂直的將這些“資料塊”切開,然後將他們分散到多臺資料庫主機上面。這樣的切分方法就是一個垂直(縱向)的資料切分。

垂直切分的優點

◆資料庫的拆分簡單明瞭,拆分規則明確;

◆應用程式模組清晰明確,整合容易;

◆資料維護方便易行,容易定位;

垂直切分的缺點

◆部分表關聯無法在資料庫級別完成,需要在程式中完成;

◆對於訪問極其頻繁且資料量超大的表仍然存在效能平靜,不一定能滿足要求;

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

◆切分達到一定程度之後,擴充套件性會遇到限制;

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

資料的水平切分

資料的垂直切分基本上可以簡單的理解為按照表按照模組來切分資料,而水平切分就不再是按照表或者是功能模組來切分了。一般來說,簡單的水平切分主要是將某個訪問極其平凡的表再按照某個欄位的某種規則來分散到多個表之中,每個表中包含一部分資料。

水平切分的優點

◆表關聯基本能夠在資料庫端全部完成;

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

◆應用程式端整體架構改動相對較少;

◆事務處理相對簡單;

◆只要切分規則能夠定義好,基本上較難遇到擴充套件性限制;

水平切分的缺點

◆切分規則相對更為複雜,很難抽象出一個能夠滿足整個資料庫的切分規則;

◆後期資料的維護難度有所增加,人為手工定位資料更困難;

◆應用系統各模組耦合度較高,可能會對後面資料的遷移拆分造成一定的困難。

資料切分與整合中可能存在的問題

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

完全可以將一個跨多個數據庫的分散式事務分拆成多個僅處於單個數據庫上面的小事務,並通過應用程式來總控各個小事務。當然,這樣作的要求就是我們的俄應用程式必須要有足夠的健壯性,當然也會給應用程式帶來一些技術難度。

2.跨節點Join的問題

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

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

從多個數據源並行的取資料,然後應用程式彙總處理。

九、可擴充套件性設計之CacheSearch的利用

通過引入Cache(Redis、Memcached),減少資料庫的訪問,增加效能。

通過引入Search(Lucene、Solr、ElasticSearch),利用搜索引擎高效的全文索引和分詞演算法,以及高效的資料檢索實現,來解決資料庫和傳統的Cache軟體完全無法解決的全文模糊搜尋、分類統計查詢等功能。

 

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

《MySQL效能優化的最佳20+條經驗》 http://coolshell.cn/articles/1846.html

1、Web網站系統

2、日誌記錄系統

3、資料倉庫系統

4、嵌入式系統

二、MySQL架構圖:

 

三、MySQL儲存引擎概述

1MyISAM儲存引擎

MyISAM儲存引擎的表在資料庫中,每一個表都被存放為三個以表名命名的物理檔案。首先肯定會有任何儲存引擎都不可缺少的存放表結構定義資訊的.frm檔案,另外還有.MYD和.MYI檔案,分別存放了表的資料(.MYD)和索引資料(.MYI)。每個表都有且僅有這樣三個檔案做為MyISAM儲存型別的表的儲存,也就是說不管這個表有多少個索引,都是存放在同一個.MYI檔案中。

MyISAM支援以下三種類型的索引:

1、B-Tree索引

B-Tree索引,顧名思義,就是所有的索引節點都按照balancetree的資料結構來儲存,所有的索引資料節點都在葉節點。

2、R-Tree索引

R-Tree索引的儲存方式和b-tree索引有一些區別,主要設計用於為儲存空間和多維資料的欄位做索引,所以目前的MySQL版本來說,也僅支援geometry型別的欄位作索引。

3、Full-text索引

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

2Innodb 儲存引擎

1、支援事務安裝

2、資料多版本讀取

3、鎖定機制的改進

4、實現外來鍵

3NDBCluster儲存引擎

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

4Merge儲存引擎

MERGE儲存引擎,在MySQL使用者手冊中也提到了,也被大家認識為MRG_MyISAM引擎。Why?因為MERGE儲存引擎可以簡單的理解為其功能就是實現了對結構相同的MyISAM表,通過一些特殊的包裝對外提供一個單一的訪問入口,以達到減小應用的複雜度的目的。要建立MERGE表,不僅僅基表的結構要完全一致,包括欄位的順序,基表的索引也必須完全一致。

5Memory儲存引擎

Memory儲存引擎,通過名字就很容易讓人知道,他是一個將資料儲存在記憶體中的儲存引擎。Memory儲存引擎不會將任何資料存放到磁碟上,僅僅存放了一個表結構相關資訊的.frm檔案在磁碟上面。所以一旦MySQLCrash或者主機Crash之後,Memory的表就只剩下一個結構了。Memory表支援索引,並且同時支援Hash和B-Tree兩種格式的索引。由於是存放在記憶體中,所以Memory都是按照定長的空間來儲存資料的,而且不支援BLOB和TEXT型別的欄位。Memory儲存引擎實現頁級鎖定。

6BDB儲存引擎

BDB儲存引擎全稱為BerkeleyDB儲存引擎,和Innodb一樣,也不是MySQL自己開發實現的一個儲存引擎,而是由SleepycatSoftware所提供,當然,也是開源儲存引擎,同樣支援事務安全。

7FEDERATED儲存引擎

FEDERATED儲存引擎所實現的功能,和Oracle的DBLINK基本相似,主要用來提供對遠端MySQL伺服器上面的資料的訪問介面。如果我們使用原始碼編譯來安裝MySQL,那麼必須手工指定啟用FEDERATED儲存引擎才行,因為MySQL預設是不起用該儲存引擎的。

8ARCHIVE儲存引擎

ARCHIVE儲存引擎主要用於通過較小的儲存空間來存放過期的很少訪問的歷史資料。ARCHIVE表不支援索引,通過一個.frm的結構定義檔案,一個.ARZ的資料壓縮檔案還有一個.ARM的meta資訊檔案。由於其所存放的資料的特殊性,ARCHIVE表不支援刪除,修改操

作,僅支援插入和查詢操作。鎖定機制為行級鎖定。

9BLACKHOLE儲存引擎

BLACKHOLE儲存引擎是一個非常有意思的儲存引擎,功能恰如其名,就是一個“黑洞”。就像我們unix系統下面的“/dev/null”裝置一樣,不管我們寫入任何資訊,都是有去無回。

10CSV儲存引擎

CSV儲存引擎實際上操作的就是一個標準的CSV檔案,他不支援索引。起主要用途就是大家有些時候可能會需要通過資料庫中的資料匯出成一份報表檔案,而CSV檔案是很多軟體都支援的一種較為標準的格式,所以我們可以通過先在資料庫中建立一張CVS表,然後將生成的報表資訊插入到該表,即可得到一份CSV報表檔案了。

四、影響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_id
FROM user_group
WHERE user_group.group_id=1
ORDER BY gmt_create desc
limit 100,20)t,user
WHERE t.user_id=user.id;
複製程式碼

通過比較兩個解決方案的執行計劃,我們可以看到第一中解決方案中需要和user表參與Join的記錄數MySQL通過統計資料估算出來是31156,也就是通過user_group表返回的所有滿足group_id=1的記錄數(系統中的實際資料是20000)。而第二種解決方案的執行計劃中,user表參與Join的資料就只有20條,兩者相差很大,我們認為第二中解決方案應該明顯優於第一種解決方案。

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

儘量減少對資料庫訪問的請求。

儘量減少無用資料的查詢請求。

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

1、典型OLTP應用系統

對於各種資料庫系統環境中大家最常見的OLTP系統,其特點是併發量大,整體資料量比較多,但每次訪問的資料比較少,且訪問的資料比較離散,活躍資料佔總體資料的比例不是太大。對於這類系統的資料庫實際上是最難維護,最難以優化的,對主機整體效能要求也是最高的。因為不僅訪問量很高,資料量也不小。

針對上面的這些特點和分析,我們可以對OLTP的得出一個大致的方向。

雖然系統總體資料量較大,但是系統活躍資料在資料總量中所佔的比例不大,那麼我們可以通過擴大記憶體容量來儘可能多的將活躍資料cache到記憶體中;

雖然IO訪問非常頻繁,但是每次訪問的資料量較少且很離散,那麼我們對磁碟儲存的要求是IOPS表現要很好,吞吐量是次要因素;

併發量很高,CPU每秒所要處理的請求自然也就很多,所以CPU處理能力需要比較強勁;

雖然與客戶端的每次互動的資料量並不是特別大,但是網路互動非常頻繁,所以主機與客戶端互動的網路裝置對流量能力也要求不能太弱。

2、典型OLAP應用系統

用於資料分析的OLAP系統的主要特點就是資料量非常大,併發訪問不多,但每次訪問所需要檢索的資料量都比較多,而且資料訪問相對較為集中,沒有太明顯的活躍資料概念。

基於OLAP系統的各種特點和相應的分析,針對OLAP系統硬體優化的大致策略如下:

資料量非常大,所以磁碟儲存系統的單位容量需要儘量大一些;

單次訪問資料量較大,而且訪問資料比較集中,那麼對IO系統的效能要求是需要有儘可能大的每秒IO吞吐量,所以應該選用每秒吞吐量儘可能大的磁碟;

雖然IO效能要求也比較高,但是併發請求較少,所以CPU處理能力較難成為效能瓶頸,所以CPU處理能力沒有太苛刻的要求;

雖然每次請求的訪問量很大,但是執行過程中的資料大都不會返回給客戶端,最終返回給客戶端的資料量都較小,所以和客戶端互動的網路裝置要求並不是太高;

此外,由於OLAP系統由於其每次運算過程較長,可以很好的並行化,所以一般的OLAP系統都是由多臺主機構成的一個叢集,而叢集中主機與主機之間的資料互動量一般來說都是非常大的,所以在叢集中主機之間的網路裝置要求很高。

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

雖然資料量小,但是訪問極其頻繁,所以可以通過較大的記憶體來cache住大部分的資料,這能夠保證非常高的命中率,磁碟IO量比較小,所以磁碟也不需要特別高效能的;

併發請求非常頻繁,比需要較強的CPU處理能力才能處理;

雖然應用與資料庫互動量非常大,但是每次互動資料較少,總體流量雖然也會較大,但是一般來說普通的千兆網絡卡已經足夠了。

五、MySQL 鎖定機制簡介

行級鎖定(row-level)

表級鎖定(table-level)

頁級鎖定(page-level)

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

六、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 BYGROUP BYDISTINCT優化

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操作。

七、MySQL資料庫Schema設計的效能優化

高效的模型設計

適度冗餘-讓Query盡兩減少Join

大欄位垂直分拆-summary表優化

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

統計表-準實時優化

合適的資料型別

時間儲存格式總類並不是太多,我們常用的主要就是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也不會出現。

八、可擴充套件性設計之資料切分

資料的垂直切分

資料的垂直切分,也可以稱之為縱向切分。將資料庫想象成為由很多個一大塊一大塊的“資料塊”(表)組成,我們垂直的將這些“資料塊”切開,然後將他們分散到多臺資料庫主機上面。這樣的切分方法就是一個垂直(縱向)的資料切分。

垂直切分的優點

◆資料庫的拆分簡單明瞭,拆分規則明確;

◆應用程式模組清晰明確,整合容易;

◆資料維護方便易行,容易定位;

垂直切分的缺點

◆部分表關聯無法在資料庫級別完成,需要在程式中完成;

◆對於訪問極其頻繁且資料量超大的表仍然存在效能平靜,不一定能滿足要求;

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

◆切分達到一定程度之後,擴充套件性會遇到限制;

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

資料的水平切分

資料的垂直切分基本上可以簡單的理解為按照表按照模組來切分資料,而水平切分就不再是按照表或者是功能模組來切分了。一般來說,簡單的水平切分主要是將某個訪問極其平凡的表再按照某個欄位的某種規則來分散到多個表之中,每個表中包含一部分資料。

水平切分的優點

◆表關聯基本能夠在資料庫端全部完成;

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

◆應用程式端整體架構改動相對較少;

◆事務處理相對簡單;

◆只要切分規則能夠定義好,基本上較難遇到擴充套件性限制;

水平切分的缺點

◆切分規則相對更為複雜,很難抽象出一個能夠滿足整個資料庫的切分規則;

◆後期資料的維護難度有所增加,人為手工定位資料更困難;

◆應用系統各模組耦合度較高,可能會對後面資料的遷移拆分造成一定的困難。

資料切分與整合中可能存在的問題

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

完全可以將一個跨多個數據庫的分散式事務分拆成多個僅處於單個數據庫上面的小事務,並通過應用程式來總控各個小事務。當然,這樣作的要求就是我們的俄應用程式必須要有足夠的健壯性,當然也會給應用程式帶來一些技術難度。

2.跨節點Join的問題

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

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

從多個數據源並行的取資料,然後應用程式彙總處理。

九、可擴充套件性設計之CacheSearch的利用

通過引入Cache(Redis、Memcached),減少資料庫的訪問,增加效能。

通過引入Search(Lucene、Solr、ElasticSearch),利用搜索引擎高效的全文索引和分詞演算法,以及高效的資料檢索實現,來解決資料庫和傳統的Cache軟體完全無法解決的全文模糊搜尋、分類統計查詢等功能。

 

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

《MySQL效能優化的最佳20+條經驗》 http://coolshell.cn/articles/1846.html