关于标题的简短问题:我使用我的mongo Shell默认处于安全模式,我希望通过停用此行为来获得更好的性能。
对于那些愿意了解背景的人来说,很长的问题: 我正在处理大量数据,如
{
_id:ObjectId("azertyuiopqsdfghjkl"),
stringdate:"2008-03-08 06:36:00"
}
和其他一些字段有大约250M这样的文档(整个数据库的索引权重为36Go)。我想在真正的ISODATE字段中转换日期。我搜索了一下如何进行像
这样的更新查询db.data.update({},{$set:{date:new Date("$stringdate")}},{multi:true})
但没有找到如何完成这项工作并解决自己制作一个脚本,一个接一个地取文件,并进行更新以设置一个新的字段,以新的日期(stringdate)为其值。查询使用_id,因此使用默认索引。
问题是它需要很长时间。我已经发现,如果我在创建数据库时只插入了空日期对象,我现在可以获得更好的性能,因为添加新字段时存在数据重定位问题。我还在相关字段上设置索引以按块处理数据库块。最后,我在服务器和工作站上运行了几个并发的mongo客户端,以确保限制因素是数据库锁可用性,而不是任何其他因素,如cpu或网络成本。
我使用mongotop,mongostats和web监控接口监控整个事情,确认写锁定占70%的时间。我有点失望mongodb的写锁没有更精确的粒度,为什么不在同一个集合上允许并发写操作,只要没有干扰的风险?现在我考虑一下,即使在同一台服务器上,我也应该在十几个分片上对分片进行分片,因为每个分片上会有单独的锁定。
但由于我现在无法对当前的数据库结构做任何事情,我搜索了如何提高性能至少花费90%的时间用mongo编写(目前从70%),我发现了因为我在默认的mongo shell中运行我的脚本,所以每次进行更新时,都会有一个getLastError(),之后调用它,我不想要它,因为有99.99%的成功几率,即使是失败我仍然可以在大进程结束后发出聚合请求来检索单个异常。
我认为通过停用getLastError调用我不会获得如此多的性能,但我认为值得尝试。
我查看了文档并找到了默认行为的确认,但没有找到更改它的过程。有什么建议吗?
答案 0 :(得分:1)
我使用我的mongo Shell默认情况下处于安全模式,我希望通过停用此行为来获得更好的性能。
您可以使用db.getLastError({w:0})
(http://docs.mongodb.org/manual/reference/method/db.getLastError/)做您想做的事情但不会有帮助。
这是因为一个人:
创建一个脚本,一个接一个地获取文档并进行更新以设置一个新的字段,该字段将新的日期(stringdate)作为其值。
当在非交互模式下使用shell时,就像在循环中一样,它实际上不会调用getLastError()
。因此,对0
的写作关注将无效。
我已经发现,如果我在创建数据库时只插入了空日期对象,那么现在可以获得更好的性能,因为添加新字段时会出现数据重定位问题。
我确实告诉别人,当他们询问这些东西时,可以添加这些字段,但是他们听了那个说“把它们留下来!他们使用空间!”的人。
我不应该感到自鸣得意,但我这样做。当你被告知错了时,这是一个不幸的副作用。
mongostats和Web监控接口确认70%的时间都采用写锁定
那是因为你的文件中的所有动作,有点难以解决。
我有点失望mongodb的写锁定没有更精确的粒度
写入锁实际上并不表示MongoDB的并发性,这是源于事务性SQL技术的另一种常见错误概念。
MongoDB中的写锁是一个互斥锁。
不仅如此,还有许多规则规定在某些情况下操作将平息到排队操作,一个是等待多少操作,另一个是数据是否在RAM中,等等。
不幸的是,我相信你已经陷入了摇滚和艰难的地方,并没有简单的方法。这确实发生了。