背景
昨晚需要跑一批數(shù)據(jù)到mongo中芝此,采用jmeter讀取數(shù)據(jù)文件向服務(wù)端發(fā)送請求的方式馒疹,將數(shù)據(jù)庫跑入數(shù)據(jù)庫橄碾。
數(shù)據(jù)量:200w
mongo與服務(wù)端均部署在同一臺機(jī)器上狡逢。
現(xiàn)象
在服務(wù)器上執(zhí)行jmeter腳本由境,但是數(shù)據(jù)慘不忍睹
看了服務(wù)器的cpu 和內(nèi)存的使用率棚亩,發(fā)現(xiàn)cpu(24核)只有67%,內(nèi)存只有20%(512G)虏杰。并發(fā)量只有200讥蟆,明顯對于服務(wù)端的壓力不大,排除硬件纺阔。
后來將并發(fā)量降低至50瘸彤,數(shù)據(jù)依然慘不忍睹。
猜測
懷疑是數(shù)據(jù)庫的索引沒有加州弟,但是服務(wù)端是會自動建立索引的钧栖,進(jìn)入mongo查看索引,發(fā)現(xiàn)都建立了婆翔。
決定開始mongo 慢查詢拯杠,看看是否是數(shù)據(jù)入庫時過慢造成的, 因為測試前數(shù)據(jù)庫是空的啃奴,隨著數(shù)據(jù)的進(jìn)入潭陪,伴隨著insert及query操作。
慢查詢分析流程
通過慢查詢?nèi)罩咀罾伲ㄎ幻織l語句的執(zhí)行時間依溯,比如超過了200ms的,那么就需要針對這個進(jìn)行優(yōu)化瘟则。
優(yōu)化步驟:
- 用慢查詢?nèi)罩荆╯ystem.profile)找到超過200ms的語句
- 然后再通過.explain()解析影響行數(shù)黎炉,分析為什么超過200ms
- 決定是不是需要添加索引
開啟慢查詢
Profiling級別說明
- 0:關(guān)閉,不收集任何數(shù)據(jù)醋拧。
- 1:采集慢查詢數(shù)據(jù)慷嗜,默認(rèn)是100毫秒淀弹。
- 2:采集所有數(shù)據(jù)
開啟profiling
#查看狀態(tài):級別和時間
> db.getProfilingStatus()
{ "was" : 0, "slowms" : 100 }
#查看級別
> db.getProfilingLevel()
0
#設(shè)置級別
> db.setProfilingLevel(1)
{ "was" : 0, "slowms" : 100, "ok" : 1 }
#設(shè)置級別和時間
> db.setProfilingLevel(1,200)
{ "was" : 2, "slowms" : 100, "ok" : 1 }
需要注意的是,以上操作如果是在collection下操作庆械,只對該collection有效薇溃。如果需要對整個db有效,需要在db下執(zhí)行缭乘。每次執(zhí)行后返回的結(jié)果是修改前的狀態(tài)沐序。
慢查詢分析
{
"op" : "insert", #操作類型,有insert堕绩、query策幼、update、remove逛尚、getmore垄惧、command
"ns" : "fingerprint.T_DEVICE_FP_ANDROID", #操作集合
"query" : {
"insert" : "T_DEVICE_FP_ANDROID",
"ordered" : true,
"documents" : [
{
"_id" : ObjectId("58c143a5d8a7db667f13629b"),
"_class" : "*************",
}
]
},
"ninserted" : 1,
"keyUpdates" : 0, #索引更新的數(shù)量刁愿,改變一個索引鍵帶有一個小的性能開銷绰寞,因為數(shù)據(jù)庫必須刪除舊的key,并插入一個新的key到B-樹索引
"writeConflicts" : 0,
"numYield" : 0, #該操作為了使其他操作完成而放棄的次數(shù)铣口。通常來說滤钱,當(dāng)他們需要訪問還沒有完全讀入內(nèi)存中的數(shù)據(jù)時,操作將放棄脑题。這使得在MongoDB為了放棄操作進(jìn)行數(shù)據(jù)讀取的同時件缸,還有數(shù)據(jù)在內(nèi)存中的其他操作可以完成
"locks" : {
"Global" : {
"acquireCount" : {
"r" : NumberLong(1),
"w" : NumberLong(1)
}
},
"Database" : {
"acquireCount" : {
"w" : NumberLong(1)
}
},
"Collection" : {
"acquireCount" : {
"w" : NumberLong(1)
}
}
},
"responseLength" : 40,
"protocol" : "op_query",
"millis" : 1601, #消耗的時間(毫秒)
"execStats" : {
},
"ts" : ISODate("2017-03-09T11:59:34.972Z"),
"client" : "10.100.1.200",
"allUsers" : [ ],
"user" : ""
}
此處發(fā)現(xiàn)millis 數(shù)據(jù)很大,一個insert操作需要1.6s叔遂。需要進(jìn)行優(yōu)化他炊。
總結(jié)
上面的只是一個例子,實(shí)際中已艰,我當(dāng)時是在query遇到問題痊末,一個query執(zhí)行了2800ms。后來發(fā)現(xiàn)是有兩個字段沒有建索引導(dǎo)致的哩掺。但是依然沒有解決insert性能低下的問題凿叠。
后續(xù)有待繼續(xù)研究。