【发布时间】:2015-10-23 07:14:41
【问题描述】:
使用 Mongo Java 驱动程序 2.13 和 Mongo 3.0。
我正在尝试从 Spring Data save() 转移到 MongoDB API 的 Bulk Writing,因为我正在保存/更新大约 100K 对象。我正在尝试编写服务/存储库层代码,我可以在其中传递我的特定对象的集合,并能够创建新记录或更新现有记录,或者换句话说。当我进行插入时,性能非常可接受。
如果我更新代码来做 upserts,性能太慢了。我在下面的代码示例中做错了吗(注意它被缩小到只是必要的逻辑,即没有错误处理):
public void save(Collection<MyDomainObject> objects) {
BulkWriteOperation bulkWriter = dbCollection.initializeUnorderedBulkOperation();
for(MyDomainObject mdo : objects) {
DBObject dbObject = convert(mdo);
bulkWriter.find(new BasicDBObject("id",mdo.getId()))
.upsert().updateOne(new BasicDBObject("$set",dbObject));
}
bulkWriter.execute(writeConcern);
}
请注意,我也尝试了 replaceOne() 而不是 updateOne() ,结果相同。
我在 Mongo 日志中也注意到“nscannedObjects”不断增加,而“nMatched”、“nModified”和“upsert”从不大于 1。这是否意味着它是针对每条记录进行表扫描?
我是否以正确的方式使用 upsert?还有其他建议吗?
【问题讨论】:
-
是的,关于完整收藏扫描的问题。如果您使用“解释”功能,您可以查看索引是否被命中及其名称。您是否检查过与查找和更新相关的索引?它应该在“indexFilterSet”字段中。
-
你说“java这么慢”,你是在对比什么?或者它对你来说只是“慢”?为什么需要替换整个文档?如果一切都在变化,那是没有效率的。文档是否“增长”?如果是,MongoDB 需要在磁盘上分配另一个空间。有哪些指标?您只匹配
_id,但编写其他索引需要时间。这里有很多可能性,但信息很少。 -
为什么我们需要替换整个文档?如果我们不这样做,我们可能就不需要 Mongo。 Mongo 应该是基于文档的,对吧?跟踪哪些字段已更新或未更新的逻辑很复杂。
-
@wxkevin 您需要了解Update Operators,这是真正将 MongoDB 与基本键/值或文档存储区分开来的特性之一。这是关于只改变你需要改变的东西。您不会仅仅因为更改了一列或添加了相关行而更新关系数据库或多个连接表中的表的整行。这里也是如此。
标签: java mongodb mongodb-java