这是 db.currentOp() 的输出:
> db.currentOp()
{
"inprog" : [
{
"opid" : 2153,
"active" : false,
"op" : "update",
"ns" : "",
"query" : {
"name" : "Run_KPIS",
"profile" : "totals"
},
"client" : ":34140",
"desc" : "conn127",
"threadId" : "0x7f1d0f03c700",
"connectionId" : 127,
"locks" : {
"^cached_data" : "W"
},
"waitingForLock" : true,
"numYields" : 0,
"lockStats" : {
"timeLockedMicros" : {
},
"timeAcquiringMicros" : {
}
}
},
{
"opid" : 2154,
"active" : false,
"op" : "getmore",
"ns" : "",
"query" : {
},
"client" : ":34129",
"desc" : "conn118",
"threadId" : "0x7f1e32785700",
"connectionId" : 118,
"locks" : {
"^cached_data" : "R"
},
"waitingForLock" : true,
"numYields" : 0,
"lockStats" : {
"timeLockedMicros" : {
},
"timeAcquiringMicros" : {
}
}
},
{
"opid" : 1751,
"active" : true,
"secs_running" : 98,
"op" : "query",
"ns" : "cached_data.webtraffic",
"query" : {
"mapreduce" : "webtraffic",
"map" : function () {
if (this.Pages)
for (var i in this.Pages)
if (i.match(/(\/blogs\/|\/news\/)/))
emit({
'page':i,
'profile':this.Profile
},this.Pages[i]);
},
"reduce" : function (k,vals) {
for(var i=0,sum=0;i<vals.length;sum+=vals[i++]);
return sum;
},
"out" : {
"inline" : 1
},
"query" : {
"$or" : [
{
"Profile" : "MEMBER"
},
{
"Profile" : "WEB"
}
]
}
},
"client" : ":34111",
"desc" : "conn112",
"threadId" : "0x7f1d1768d700",
"connectionId" : 112,
"locks" : {
"^" : "r",
"^cached_data" : "R"
},
"waitingForLock" : false,
"msg" : "m/r: (1/3) emit phase M/R: (1/3) Emit Progress: 801/830 96%",
"progress" : {
"done" : 801,
"total" : 830
},
"numYields" : 148,
"lockStats" : {
"timeLockedMicros" : {
"r" : NumberLong(183690739),
"w" : NumberLong(0)
},
"timeAcquiringMicros" : {
"r" : NumberLong(92296403),
"w" : NumberLong(0)
}
}
}
]
}
我对所有相关集合都有索引,但在运行上述操作时从我们的 MongoDB 读取仍然会出现很大的延迟。
数据库可能需要大约 5 分钟才能再次读取。
上述 map Reduce 函数是否会导致此读取锁定?如果是,我该如何在集合上运行非锁定 map Reduce?
奇怪的是,MongoDB 仍然接受连接,只是不允许我们在上述操作运行时进行查询。
编辑后显示这是 Mongo 版本 2.4.1。
答案1
首先,这里运行的是查询。它对$or
同一字段的两个值使用运算符。如果这是典型的情况,请将其更改为$in
运算符(如这里推荐)。这应该会有很大帮助 - 当您使用 $or 时,您正在并行运行两个查询并合并结果,而当您使用 in 时,您只会执行一个查询。
接下来,由于这是一个排队Map Reduce 作业,我建议在辅助服务器上运行该作业(如果您还没有这样做),并让任何具有更高实时要求的应用程序在其他地方运行。您可以通过多种方式执行此操作,但最灵活的是基于标签的阅读偏好。
在解释currentOp()
输出时,大写字母代表全局锁这可能是导致事情停滞的原因(尽管它会尝试让步),您还可以看到它首先花费了大量时间来尝试获取锁。我认为这表示对相关数据的大型表扫描,并且数据并非全部适合 RAM,而是从磁盘调入。因此,该查询的让步次数(MongoDB 会在发现磁盘故障时尝试让步)。
查看页面错误指标彩信或者蒙哥斯塔特要了解那里的趋势,实际上 MMS 是一个很好的地方,可以总体了解这个实例在一段时间内发生的情况。
上述更改$in
应该会对此有所帮助,但可能只会拖延时间。如果您要对大量数据进行聚合,则要么需要将其放在 RAM 中,因为这种操作速度很快,要么您需要将其放在辅助磁盘上,这样缓慢的磁盘访问就不会拖累一切。