MongoDB入庫、更新、查詢效率簡單測試
單mongod測試(即只有一個mongod程序實例)
所有測試機均為4g內存雙核cpu(64位系統)
測試所用文檔為簡單的三個字段的文檔:
DBObject doc = newBasicDBObject();
doc.put("test","test"+insertNum);
doc.put("no", insertNum);
doc.put("time",swapWords(sld.format(new Date())));
一、入庫效率:
1、普通集合入庫,
每10萬條數據平均2~3秒
入庫一億條數據大概45分鍾
2、四個索引的普通集合
初始每10萬條5~6秒,時間逐漸增長,到千萬級別時每10萬條入庫時間60~80秒
入庫一千萬數據一小時多一點
3、一個索引的普通集合
初始入庫每10萬條3秒左右,耗時逐漸增長,到四千萬左右時每10萬條入庫時間15~20秒
入庫一千萬數據7、8分鍾
入庫四千萬數據大概一個半小時
4、固定集合
初始入庫每10萬條數據平均2~2.5秒
5、一個索引的固定集合
初始入庫每10萬條數據平均3~4秒
二、查詢效率:
沒有索引會進行表掃描(大表會極慢)
無論有沒有索引,大批量插入時查詢效率極慢
三、插入時機器負載:
沒索引時:cpu不到20%
有索引時,初始插入cpu 20,30~40,后期比較慢不到5~15% 猜測原因內存已經用滿,磁盤io比較多
mongos測試(三台機器的簡單無備份mongod分片群)
一、簡單入庫
1、test集合,分片,無索引,文檔結構大小同上例
每10萬條記錄 3~3.5秒
從sqlserver測試表導數據至mongos(三台)測試
一、第一種入庫策略:
先入庫,再建索引及分片,按索引分片
1、測試表Test共20列1.5億數據
2、導到mongos時表不設索引,不分片,等到入庫完畢后再進行這些操作
3、導出時所有列都用的string
4、1億5千萬入庫6個半小時 10萬/10~20秒(從遠程的sqlserver數據庫導入,一邊遍歷結果集一邊插入,所以實際入庫速度應該比這個快)
5、建userid,city的二級索引大概用了半個小時(從日志中查看)
6、按索引中(userid,city)的一個鍵分片(而不是用objectid);
操作是阻塞式的,吃完飯回來就完成了。。應該是在一個半小時內
7、在有分片及索引的情況下,追加插入效率較差,每1000條 20~30秒
8、所以考慮:撤銷索引,查看集合行數(看是否有影響),追加插入數據,建立索引,測試查詢。但是剛剛撤銷索集群就無法訪問了(因為分片是按索引userid分的).
二、查詢:
建立索引后:
幾次測試,同一個程序10000條數據連續查詢,平均11~13毫秒
並發測試,3個程序同時分別連續查詢10000條數據,平均14毫秒
三、刪除集合不會釋放硬盤空間
1、刪除后的表不會釋放硬盤空間而是內部標記為空閑,需要注意
2、可以用db.repairDatabase()整理磁盤文件:
mongos會分mongod分別處理,每個mongod處理自己的
程序首先會將所有有效數據寫入臨時文件(在他的文件系統中發現諸如_tmp等文件中數據文件增加很多,而且其中文件格式和源數據文件格式相似),所以硬盤占用率會很明顯的上升,完成整理后硬盤占用減少。
3、所以如果使用此方法:
應該保證磁盤剩余空間容量>mongodb數據文件中有效數據量,
保險方法是磁盤剩余空間>mongodb數據文件
4、時間
比較慢,不到180g有效數據分在三台機器,用了1~3個小時
4、在此過程中查詢:
在此過程中讀寫幾乎不能用
四、第二種入庫策略:
按objectid分片,索引及入庫策略不變
1、 初始入庫時間大致和之前相同(1.5億條數據)
2、 追加存入重復數據
20萬條10分鍾(先遍歷sqlserver結果集存入內存中再一次性入庫mongodb)
3、 追加新數據入庫
20萬條2分半鍾(先遍歷sqlserver結果集存入內存中再一次性入庫mongodb)
4、 根據非objectid鍵更新插入(upsert)
很慢,1000條需要6~8分鍾(實際上操作失敗,因為upsert操作需要指定分片鍵objectid)
5、 查詢
速度比之前方案稍慢,35~40毫秒平均(連續查詢20000次)
其他
1、 windows,linux混合集群測試
可行,效率沒大規模用過,不知道是否穩定。Linux方面程序不會主動釋放內存,windows程序據觀察在入庫時內存占用量增大,但是入庫完后會釋放。
2、 32位windows系統程序確實只能存2g數據,大於2g數據后程序報錯退出。
MongoDB索引管理-索引的創建、查看、刪除
http://itbilu.com/database/mongo/E1tWQz4_e.html
索引是提高查詢查詢效率最有效的手段。索引是一種特殊的數據結構,索引以易於遍歷的形式存儲了數據的部分內容(如:一個特定的字段或一組字段值),索引會按一定規則對存儲值進行排序,而且索引的存儲位置在內存中,所在從索引中檢索數據會非常快。如果沒有索引,MongoDB必須掃描集合中的每一個文檔,這種掃描的效率非常低,尤其是在數據量較大時。
1. 創建/重建索引
MongoDB全新創建索引使用ensureIndex()
方法,對於已存在的索引可以使用reIndex()
進行重建。
1.1 創建索引ensureIndex()
MongoDB創建索引使用ensureIndex()
方法。
語法結構
db.COLLECTION_NAME.ensureIndex(keys[,options])
keys
,要建立索引的參數列表。如:{KEY:1}
,其中key
表示字段名,1
表示升序排序,也可使用使用數字-1
降序。options
,可選參數,表示建立索引的設置。可選值如下:background
,Boolean,在后台建立索引,以便建立索引時不阻止其他數據庫活動。默認值 false。unique
,Boolean,創建唯一索引。默認值 false。name
,String,指定索引的名稱。如果未指定,MongoDB會生成一個索引字段的名稱和排序順序串聯。dropDups
,Boolean,創建唯一索引時,如果出現重復刪除后續出現的相同索引,只保留第一個。sparse
,Boolean,對文檔中不存在的字段數據不啟用索引。默認值是 false。v
,index version,索引的版本號。weights
,document,索引權重值,數值在 1 到 99,999 之間,表示該索引相對於其他索引字段的得分權重。
如,為集合sites
建立索引:
> db.sites.ensureIndex({name: 1, domain: -1}) { "createdCollectionAutomatically" : false, "numIndexesBefore" : 1, "numIndexesAfter" : 2, "ok" : 1 }
注意:1.8
版本之前創建索引使用createIndex()
,1.8
版本之后已移除該方法
1.2 重建索引reIndex()
db.COLLECTION_NAME.reIndex()
如,重建集合sites
的所有索引:
> db.sites.reIndex() { "nIndexesWas" : 2, "nIndexes" : 2, "indexes" : [ { "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "newDB.sites" }, { "key" : { "name" : 1, "domain" : -1 }, "name" : "name_1_domain_-1", "ns" : "newDB.sites" } ], "ok" : 1 }
2. 查看索引
MongoDB提供了查看索引信息的方法:getIndexes()
方法可以用來查看集合的所有索引,totalIndexSize()
查看集合索引的總大小,db.system.indexes.find()
查看數據庫中所有索引信息。
2.1 查看集合中的索引getIndexes()
db.COLLECTION_NAME.getIndexes()
如,查看集合sites
中的索引:
>db.sites.getIndexes() [ { "v" : 1, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "newDB.sites" }, { "v" : 1, "key" : { "name" : 1, "domain" : -1 }, "name" : "name_1_domain_-1", "ns" : "newDB.sites" } ]
2.2 查看集合中的索引大小totalIndexSize()
db.COLLECTION_NAME.totalIndexSize()
如,查看集合sites
索引大小:
> db.sites.totalIndexSize() 16352
2.3 查看數據庫中所有索引db.system.indexes.find()
db.system.indexes.find()
如,當前數據庫的所有索引:
> db.system.indexes.find()
3. 刪除索引
不在需要的索引,我們可以將其刪除。刪除索引時,可以刪除集合中的某一索引,可以刪除全部索引。
3.1 刪除指定的索引dropIndex()
db.COLLECTION_NAME.dropIndex("INDEX-NAME")
如,刪除集合sites
中名為"name_1_domain_-1"的索引:
> db.sites.dropIndex("name_1_domain_-1") { "nIndexesWas" : 2, "ok" : 1 }
3.3 刪除所有索引dropIndexes()
db.COLLECTION_NAME.dropIndexes()
如,刪除集合sites
中所有的索引:
> db.sites.dropIndexes() { "nIndexesWas" : 1, "msg" : "non-_id indexes dropped for collection", "ok" : 1 }