MongoDB - find()调用有时会卡住 - 超时

时间:2016-05-18 06:17:38

标签: java mongodb mongodb-query

我们正在使用MongoDb来保存和获取数据。

将数据放入集合的所有调用都运行正常,并且通过常用方法。

从集合中获取数据的所有调用有时都能正常工作,并且通过常用方法。

但有时候,只针对其中一个我会让我的电话永久停滞,消耗CPU使用率。我必须手动杀死线程,否则它会消耗我的整个CPU。

Mongo Connection

MongoClient mongo = new MongoClient(hostName , Integer.valueOf(port));
DB mongoDb = mongo.getDB(dbName);

要提取的代码

DBCollection collection = mongoDb.getCollection(collectionName);
DBObject dbObject = new BasicDBObject("_id" , key);
DBCursor cursor = collection.find(dbObject);

虽然我已经找到了它导致问题的集合,但是我怎样才能改进这一点,因为它发生在这个特定的集合中,有时候。

修改

保存代码

DBCollection collection = mongoDb.getCollection(collectionName);
DBObject query = new BasicDBObject("_id" , key);
DBObject update = new BasicDBObject();
update.put("$set" , JSON.parse(value));
collection.update(query , update , true , false);

批量撰写/收藏

DB mongoDb = controllerFactory.getMongoDB();
        DBCollection collection = mongoDb.getCollection(collectionName);

        BulkWriteOperation bulkWriteOperation = collection.initializeUnorderedBulkOperation();

        Map<String, Object> dataMap = (Map<String, Object>) JSON.parse(value);

        for (Entry<String, Object> entrySet : dataMap.entrySet()) {
            BulkWriteRequestBuilder bulkWriteRequestBuilder = bulkWriteOperation.find(new BasicDBObject("_id" ,
                    entrySet.getKey()));

            DBObject update = new BasicDBObject();
            update.put("$set" , entrySet.getValue());

            bulkWriteRequestBuilder.upsert().update(update);
        }

如何为fetch调用设置超时.. ??

3 个答案:

答案 0 :(得分:1)

只是一些可能的解释/想法

一般&#34;按id&#34;查询必须要快,因为_id应该被索引。总是。 代码片段看起来是正确的,所以可能原因在于mongo本身。 这引出了一些建议:

尝试直接从命令行连接到mongo并运行&#34; find&#34;从那里。很有可能你仍然能够偶尔看到缓慢的情况。

在这种情况下:

  • 也许是关于磁盘的(也许这个特定的服务器部署在慢速磁盘上,或者至少存在与访问磁盘有些缓慢的关联)。

  • 也许你的配置是分片的,一个分片比其他分片慢

  • 可能是零星发生的网络问题。如果你在本地/在staging env上运行mongo。与此相同的集合是否会重现?

  • 也许(虽然我几乎不相信),但查询以次优的方式运行。在这种情况下,您可以使用&#34; explain()&#34;正如有人已经在这里建议的那样。

  • 如果您碰巧有副本集,请弄清楚[Read Preference]是什么。谁知道,也许您更喜欢从次优服务器获取此ID

我可能错过了一些东西,但这些应该是好方向,我相信

希望,这有帮助

答案 1 :(得分:1)

另一种方法是使用MongoDB 3.2 Driver提出的方法。请注意,您必须将.jar库(如果您还没有)更新到最新版本。

public final MongoClient connectToClient(String hostName, String port) {
    try {
        MongoClient client = new MongoClient(hostName, Integer.valueOf(port));
        return client;
    } catch(MongoClientException e) {
        System.err.println("Cannot connect to Client.");
        return null;
    }
}

public final MongoDatabase connectToDB(String databaseName) {
    try {
        MongoDatabase db = client.getDatabase(databaseName);
        return db;
    } catch(Exception e) {
        System.err.println("Error in connecting to database " + databaseName);
        return null;
    }

public final void closeConnection(MongoClient client) {
    client.close();
}

public final void findDoc(MongoDatabase db, String collectionName) {
    MongoCollection<Document> collection = db.getCollection(collectionName);
    try {
        FindIterable<Document> iterable = collection
                .find(new Document("_id", key));
        Document doc = iterable.first();
        //For an Int64 field named 'special_id'
        long specialId = doc.getLong("special_id");
    } catch(MongoException e) {
        System.err.println("Error in retrieving document.");
    } catch(NullPointerException e) {
        System.err.println("Document with _id " + key + " does not exist.");
    }
}

public final void insertToDB(MongoDatabase db, String collectioName) {
    try {
        db.getCollection(collectionName).insertOne(new Document()
            .append("special_id", 5)
            //Append anything
        );
    catch(MongoException e) {
        System.err.println("Error in inserting new document.");
    }
}

public final void updateDoc(MongoDatabase db, String collectionName, long id) {
    MongoCollection<Document> collection = db.getCollection(collectionName);
    try {
        collection.updateOne(new Document("_id", id),
                             new Document("$set", 
                                     new Document("special_id", 
                                             7)));
    catch(MongoException e) {
        System.err.println("Error in updating new document.");
    }
}

public static void main(String[] args) {
    String hostName = "myHost";
    String port = "myPort";
    String databaseName = "myDB";
    String collectionName = "myCollection";
    MongoClient client = connectToClient(hostName, port);
    if(client != null) {
        MongoDatabase db = connectToDB(databaseName);
        if(db != null) {
            findDoc(db, collectionName);
        }
        client.closeConnection();
    }
}

编辑:正如其他人建议的那样,从命令行检查是否通过其ID查找文档的过程也很慢。那么这可能是你的硬盘问题。 _id应该被编入索引,但无论好坏,都要在_id字段上重新创建索引。

答案 2 :(得分:0)

其他人发布的答案很棒,但并没有解决我的目的。 实际上问题在于我现有的代码本身,我的cursor正在等待循环无限时间。

我错过了几张现已解决的支票。