0

简短的问题是标题:我使用我的 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})

但没有找到如何使这项工作,并决定自己制作一个脚本,一个接一个地获取文档并进行更新以设置一个以新日期(字符串日期)作为其值的新字段。查询使用 _id,因此使用默认索引。

问题是它需要很长时间。我已经发现,如果我在创建数据库时插入了空日期对象,我现在将获得更好的性能,因为添加新字段时会出现数据重定位问题。我还在相关字段上设置了一个索引,以逐块处理数据库。最后,我在服务器和我的工作站上运行了几个并发的 mongo 客户端,以确保限制因素是数据库锁的可用性,而不是任何其他因素,如 cpu 或网络成本。

我用 mongotop、mongostats 和 web 监控界面监控了整个事情,确认写锁占用了 70% 的时间。我有点失望 mongodb 没有更精确的写锁粒度,为什么不允许在同一个集合上进行并发写操作,只要不存在干扰风险?现在我想起来了,即使在同一台服务器上,我也应该将集合分片到十几个分片上,因为每个分片上都会有单独的锁。

但是由于我现在无法对当前的数据库结构做任何事情,所以我搜索了如何提高性能以至少花费我 90% 的时间在 mongo 中编写(目前是 70%),我发现自从我运行我的脚本在默认的 mongo shell 中,每次我进行更新时,还有一个 getLastError() 之后会调用它,我不想要它,因为有 99.99% 的成功机会,即使在失败的情况下我也可以在大流程结束后仍然发出聚合请求以检索单个异常。

我认为通过停用 getLastError 调用不会获得如此多的性能,但我认为值得一试。

我查看了文档并找到了默认行为的确认,但没有找到更改它的过程。有什么建议吗?

4

1 回答 1

1

我使用的是默认情况下处于安全模式的 mongo Shell,我希望通过停用此行为来获得更好的性能。

您可以使用db.getLastError({w:0})http://docs.mongodb.org/manual/reference/method/db.getLastError/)做您想做的事,但这无济于事。

这是因为对于一个:

制作一个脚本,一个接一个地获取文档并进行更新以设置一个新字段,该字段将新日期(字符串日期)作为其值。

当在非交互模式下使用 shell 时,比如在循环中,它实际上并没有调用getLastError(). 因此,降低您的写入关注0将无济于事。

我已经发现,如果我在创建数据库时插入了空日期对象,我现在将获得更好的性能,因为添加新字段时会出现数据重定位问题。

当他们询问这些东西以添加这些字段以防移动时,我确实告诉人们,但他们却听了那个说“把它们排除在外!他们使用空间!”的人。

我不应该感到自鸣得意,但我确实如此。不幸的是,当你被告知错误时,这是​​正确的副作用。

mongostats 和 web 监控界面,确认写锁占用了 70% 的时间

那是因为您的文档中的所有移动,有点难以修复。

我有点失望 mongodb 在其写锁上没有更精确的粒度

写锁实际上并不表示 MongoDB 的并发性,这是另一个源自事务 SQL 技术的常见误解。

MongoDB 中的写锁是一个互斥锁。

不仅如此,还有许多规则规定在某些情况下操作将消退到排队操作,一个是等待多少操作,另一个是数据是否在 RAM 中,等等。

不幸的是,我相信你让自己陷入了困境和艰难的境地,没有简单的出路。这确实发生了。

于 2014-01-03T14:32:17.157 回答