为什么 MongoDB Java API 的 upsert 这么慢?

Why are upserts so slow for MongoDB Java API?

使用 Mongo Java 驱动程序 2.13 和 Mongo 3.0.

我正在尝试从 Spring Data save() 转移到 MongoDB API 的批量写入,因为我 saving/updating 大约有 100K 个对象。我正在尝试编写 Service/Repository 层代码,我可以在其中传递我的特定对象的集合,并且能够创建新记录或更新现有记录,或者换句话说更新插入。当我插入时,性能非常好table.

如果我更新代码来执行更新插入,性能就会太慢。我在下面的代码示例中做错了什么吗(注意它被缩小到只有必要的逻辑,即没有错误处理):

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。这样做吗意思是table扫描每条记录?

我使用 upsert 的方式是否正确?还有其他建议吗?

感谢 ry_donahue 我解决了这个问题。

它没有使用正确的 ID 字段,即索引。在域对象到 DBObject 的转换中,最终得到一个 "id" 和一个“_id”字段。

我还将 updateOne() 更改为 replaceOne()。所以现在代码如下所示:

 public void save(Collection<MyDomainObject> objects) {
     BulkWriteOperation bulkWriter = dbCollection.initializeUnorderedBulkOperation();
    for(MyDomainObject mdo : objects) {
        DBObject dbObject = convert(mdo);
        bulkWriter.find(new BasicDBObject("_id",new ObjectId(mdo.getId()))).upsert().replaceOne(dbObject);
     }
     bulkWriter.execute(writeConcern);
 }   

这现在提供了非常好的性能。