Mongodb億級(jí)數(shù)據(jù)量的性能測(cè)試
進(jìn)行了一下Mongodb億級(jí)數(shù)據(jù)量的性能測(cè)試,分別測(cè)試如下幾個(gè)項(xiàng)目:
(所有插入都是單線程進(jìn)行,所有讀取都是多線程進(jìn)行)
1) 普通插入性能 (插入的數(shù)據(jù)每條大約在1KB左右)
2) 批量插入性能 (使用的是官方C#客戶端的InsertBatch),這個(gè)測(cè)的是批量插入性能能有多少提高
3) 安全插入功能 (確保插入成功,使用的是SafeMode.True開關(guān)),這個(gè)測(cè)的是安全插入性能會(huì)差多少
4) 查詢一個(gè)索引后的數(shù)字列,返回10條記錄(也就是10KB)的性能,這個(gè)測(cè)的是索引查詢的性能
5) 查詢兩個(gè)索引后的數(shù)字列,返回10條記錄(每條記錄只返回20字節(jié)左右的2個(gè)小字段)的性能,這個(gè)測(cè)的是返回小數(shù)據(jù)量以及多一個(gè)查詢條件對(duì)性能的影響
6) 查詢一個(gè)索引后的數(shù)字列,按照另一個(gè)索引的日期字段排序(索引建立的時(shí)候是倒序,排序也是倒序),并且Skip100條記錄后返回10條記錄的性能,這個(gè)測(cè)的是Skip和Order對(duì)性能的影響
7) 查詢100條記錄(也就是100KB)的性能(沒(méi)有排序,沒(méi)有條件),這個(gè)測(cè)的是大數(shù)據(jù)量的查詢結(jié)果對(duì)性能的影響
8) 統(tǒng)計(jì)隨著測(cè)試的進(jìn)行,總磁盤占用,索引磁盤占用以及數(shù)據(jù)磁盤占用的數(shù)量
并且每一種測(cè)試都使用單進(jìn)程的Mongodb和同一臺(tái)服務(wù)器開三個(gè)Mongodb進(jìn)程作為Sharding(每一個(gè)進(jìn)程大概只能用7GB左右的內(nèi)存)兩種方案
其實(shí)對(duì)于Sharding,雖然是一臺(tái)機(jī)器放3個(gè)進(jìn)程,但是在查詢的時(shí)候每一個(gè)并行進(jìn)程查詢部分?jǐn)?shù)據(jù),再有運(yùn)行于另外一個(gè)機(jī)器的mongos來(lái)匯總數(shù)據(jù),理論上來(lái)說(shuō)在某些情況下性能會(huì)有點(diǎn)提高
基于以上的種種假設(shè),猜測(cè)某些情況性能會(huì)下降,某些情況性能會(huì)提高,那么來(lái)看一下***的測(cè)試結(jié)果怎么樣?
備注:測(cè)試的存儲(chǔ)服務(wù)器是 E5620 @ 2.40GHz,24GB內(nèi)存,CentOs操作系統(tǒng),打壓機(jī)器是E5504 @ 2.0GHz,4GB內(nèi)存,Windows Server 2003操作系統(tǒng),兩者千兆網(wǎng)卡直連。
從這個(gè)測(cè)試可以看出,對(duì)于單進(jìn)程的方式:
1) Mongodb的非安全插入方式,在一開始插入性能是非常高的,但是在達(dá)到了兩千萬(wàn)條數(shù)據(jù)之后性能驟減,這個(gè)時(shí)候恰巧是服務(wù)器24G內(nèi)存基本占滿的時(shí)候(隨著測(cè)試的進(jìn)行mongodb不斷占據(jù)內(nèi)存,一直到操作系統(tǒng)的內(nèi)存全部占滿),也就是說(shuō)Mongodb的內(nèi)存映射方式,使得數(shù)據(jù)全部在內(nèi)存中的時(shí)候速度飛快,當(dāng)部分?jǐn)?shù)據(jù)需要換出到磁盤上之后,性能下降很厲害。(這個(gè)性能其實(shí)也不算太差,因?yàn)槲覀儗?duì)三個(gè)列的數(shù)據(jù)做了索引,即使在內(nèi)存滿了之后每秒也能插入2MB的數(shù)據(jù),在一開始更是每秒插入25MB數(shù)據(jù))
2) 對(duì)于批量插入功能,其實(shí)是一次提交一批數(shù)據(jù),但是相比一次一條插入性能并沒(méi)有提高多少,一來(lái)是因?yàn)榫W(wǎng)絡(luò)帶寬已經(jīng)成為了瓶頸,二來(lái)我想寫鎖也會(huì)是一個(gè)原因。
3) 對(duì)于安全插入功能,相對(duì)來(lái)說(shuō)比較穩(wěn)定,不會(huì)波動(dòng)很大,我想可能是因?yàn)榘踩迦胧谴_保數(shù)據(jù)直接持久化到磁盤的,而不是插入內(nèi)存就完事。
4) 對(duì)于一列條件的查詢,性能一直比較穩(wěn)定,別小看,每秒能有8000-9000的查詢次數(shù),每次返回10KB,相當(dāng)于每秒查詢80MB數(shù)據(jù),而且數(shù)據(jù)庫(kù)記錄是2億之后還能維持這個(gè)水平,性能驚人。
5) 對(duì)于二列條件返回小數(shù)據(jù)的查詢,總體上性能會(huì)比4)好一點(diǎn),可能返回的數(shù)據(jù)量小對(duì)性能提高比較大,但是相對(duì)來(lái)說(shuō)性能波動(dòng)也厲害一點(diǎn),可能多了一個(gè)條件就多了一個(gè)從磁盤換頁(yè)的機(jī)會(huì)。
6) 對(duì)于一列數(shù)據(jù)外加Sort和Skip的查詢,在數(shù)據(jù)量大了之后性能明顯就變差了(此時(shí)是索引數(shù)據(jù)量超過(guò)內(nèi)存大小的時(shí)候,不知道是否有聯(lián)系),我猜想是Skip比較消耗性能,不過(guò)和4)相比性能也不是差距特別大。
7) 對(duì)于返回大數(shù)據(jù)的查詢,一秒瓶頸也有800次左右,也就是80M數(shù)據(jù),這就進(jìn)一步說(shuō)明了在有索引的情況下,順序查詢和按條件搜索性能是相差無(wú)幾的,這個(gè)時(shí)候是IO和網(wǎng)絡(luò)的瓶頸。
8) 在整個(gè)過(guò)程中索引占的數(shù)據(jù)量已經(jīng)占到了總數(shù)據(jù)量的相當(dāng)大比例,在達(dá)到1億4千萬(wàn)數(shù)據(jù)量的時(shí)候,光索引就可以占據(jù)整個(gè)內(nèi)存,此時(shí)查詢性能還是非常高,插入性能也不算太差,mongodb的性能確實(shí)很牛。
那么在來(lái)看看Sharding模式有什么亮點(diǎn):
1) 非安全插入和單進(jìn)程的配置一樣,在內(nèi)存滿了之后性能急劇下降。安全插入性能和單進(jìn)程相比慢不少,但是非常穩(wěn)定。
2) 對(duì)于一個(gè)條件和兩個(gè)條件的查詢,性能都比較穩(wěn)定,但條件查詢性能相當(dāng)于單進(jìn)程的一半,但是在多條件下有的時(shí)候甚至?xí)葐芜M(jìn)程高一點(diǎn)。我想這可能是某些時(shí)候數(shù)據(jù)塊位于兩個(gè)Sharding,這樣Mongos會(huì)并行在兩個(gè)Sharding查詢,然后在把數(shù)據(jù)進(jìn)行合并匯總,由于查詢返回的數(shù)據(jù)量小,網(wǎng)絡(luò)不太可能成為瓶頸了,使得Sharding才有出頭的機(jī)會(huì)。
3) 對(duì)于Order和Skip的查詢,Sharding方式的差距就出來(lái)了,我想主要性能損失可能在Order,因?yàn)槲覀儾](méi)有按照排序字段作為Sharding的Key,使用的是_id作為Key,這樣排序就比較難進(jìn)行。
4) 對(duì)于返回大數(shù)據(jù)量的查詢,Sharding方式其實(shí)和單進(jìn)程差距不是很大,我想數(shù)據(jù)的轉(zhuǎn)發(fā)可能是一個(gè)性能損耗的原因(雖然mongos位于打壓機(jī)本機(jī),但是數(shù)據(jù)始終是轉(zhuǎn)手了一次)。
5) 對(duì)于磁盤空間的占用,兩者其實(shí)是差不多的,其中的一些差距可能是因?yàn)槎鄠€(gè)進(jìn)程都會(huì)多分配一點(diǎn)空間,加起來(lái)有的時(shí)候會(huì)比單進(jìn)程多占用點(diǎn)磁盤(而那些占用比單進(jìn)程少的地方其實(shí)是開始的編碼錯(cuò)誤,把實(shí)際數(shù)據(jù)大小和磁盤文件占用大小搞錯(cuò)了)。
雖然在***由于時(shí)間的關(guān)系,沒(méi)有測(cè)到10億級(jí)別的數(shù)據(jù)量,但是通過(guò)這些數(shù)據(jù)已經(jīng)可以證明Mongodb的性能是多么強(qiáng)勁了。另外一個(gè)原因是,在很多時(shí)候可能數(shù)據(jù)只達(dá)到千萬(wàn)我們就會(huì)對(duì)庫(kù)進(jìn)行拆分,不會(huì)讓一個(gè)庫(kù)的索引非常龐大。在測(cè)試的過(guò)程中還發(fā)現(xiàn)幾個(gè)問(wèn)題需要值得注意:
1) 在數(shù)據(jù)量很大的情況下,對(duì)服務(wù)進(jìn)行重啟,那么服務(wù)啟動(dòng)的初始化階段,雖然可以接受數(shù)據(jù)的查詢和修改,但是此時(shí)性能很差,因?yàn)閙ongodb會(huì)不斷把數(shù)據(jù)從磁盤換入內(nèi)存,此時(shí)的IO壓力非常大。
2) 在數(shù)據(jù)量很大的情況下,如果服務(wù)沒(méi)有正常關(guān)閉,那么Mongodb啟動(dòng)修復(fù)數(shù)據(jù)庫(kù)的時(shí)間非??捎^,在1.8中退出的-dur貌似可以解決這個(gè)問(wèn)題,我簡(jiǎn)單測(cè)試了一下,開啟dur對(duì)插入和查詢性能影響都不是很大。
3) 在使用Sharding的時(shí)候,Mongodb時(shí)不時(shí)會(huì)對(duì)數(shù)據(jù)拆分搬遷,這個(gè)時(shí)候性能下降很厲害,雖然從測(cè)試圖中看不出(因?yàn)槲颐恳淮螠y(cè)試都會(huì)測(cè)試比較多的迭代次數(shù)),但是我在實(shí)際觀察中可以發(fā)現(xiàn),在搬遷數(shù)據(jù)的時(shí)候每秒插入性能可能會(huì)低到幾百條。
4) 對(duì)于數(shù)據(jù)的插入,如果使用多線程并不會(huì)帶來(lái)性能的提高,反而還會(huì)下降一點(diǎn)性能(并且可以在http接口上看到,有大量的線程處于等待)。
5) 在整個(gè)測(cè)試過(guò)程中,批量插入的時(shí)候遇到過(guò)幾次連接被遠(yuǎn)程計(jì)算機(jī)關(guān)閉的錯(cuò)誤,懷疑是有的時(shí)候Mongodb不穩(wěn)定關(guān)閉了連接,或是官方的C#客戶端有BUG,但是也僅僅是在數(shù)據(jù)量特別大的時(shí)候遇到幾次。
原文鏈接:http://www.cnblogs.com/lovecindywang/archive/2011/03/02/1969324.html
【編輯推薦】