【问题标题】:retrieve large number of records with mongoDB in a reasonable time在合理的时间内使用 mongoDB 检索大量记录
【发布时间】:2011-11-16 15:56:57
【问题描述】:

我正在使用 mongoDB 来存储查询日志并获取有关它的一些统计信息。 我存储在 mongoDB 中的对象包含查询文本、日期、 用户,如果用户点击了一些结果等等等等。

现在我正在尝试检索用户在某一天未点击的所有查询 用java。我的代码大概是这样的:

    DBObject query = new BasicDBObject();
    BasicDBObject keys = new BasicDBObject();
    keys.put("Query", 1);
    query.put("Date", new BasicDBObject("$gte", beginning.getTime()).append("$lte", end.getTime()));
    query.put("IsClick", false);
    ...
    DBCursor cur = mongoCollection.find(query, keys).batchSize(5000);

查询的输出包含我需要迭代的大约 20k 条记录。 问题是它需要几分钟:(。我认为不正常。 从服务器日志我看到:

Wed Nov 16 16:28:40 query db.QueryLogRecordImpl ntoreturn:5000 reslen:252403 nscanned:59260 { Date: { $gte: 1283292000000, $lte: 1283378399999 }, IsClick: false }  nreturned:5000 2055ms
Wed Nov 16 16:28:40 getmore db.QueryLogRecordImpl cid:4312057226672898459 ntoreturn:5000 query: { Date: { $gte: 1283292000000, $lte: 1283378399999 }, IsClick: false }  bytes:232421 nreturned:5000 170ms
Wed Nov 16 16:30:27 getmore db.QueryLogRecordImpl cid:4312057226672898459 ntoreturn:5000 query: { Date: { $gte: 1283292000000, $lte: 1283378399999 }, IsClick: false }  bytes:128015 nreturned:2661 --> 106059ms

所以检索第一个块需要 2 秒,第二个 0.1 秒,第三个 106 秒!!!奇怪的.. 我尝试更改批处理大小,在 Date 和 IsClick 上创建索引,重新启动机器:P 但没办法。我哪里错了?

【问题讨论】:

  • 您是否正确地迭代所有项目然后关闭迭代器?

标签: mongodb performance mongodb-java database-cursor


【解决方案1】:

这里有几个因素会影响速度。有必要收集一些额外的数据来确定这里的原因。

一些潜在问题:

  1. 索引:您是否使用了正确的索引?您可能应该在IsClick/Date 上建立索引。这将范围放在第二位,这是正常的建议。请注意,这与 Date/IsClick 上的索引不同,顺序很重要。在您的查询中尝试使用 .explain() 以查看正在使用的索引。
  2. 数据大小:在某些情况下,数据过多可能会导致速度变慢。这可能是太多的文档或太多的大文档。它也可能是由于试图在一个非常大的大海捞针中找到太多的针头造成的。您要带回 252k 数据 (reslen) 和 12k 文档,所以这可能不是问题。
  3. 磁盘 IO: MongoDB 使用内存映射文件,因此使用大量虚拟内存。如果您的数据多于 RAM,则获取某些文档需要“转到磁盘”。转到磁盘可能是一项非常昂贵的操作。您可以使用 iostatresmon (Windows) 等工具来监控磁盘活动,从而识别“正在进入磁盘”。

根据个人经验,我强烈怀疑#3,而#1 可能会加剧。我将从在运行.explain() 查询时观察 IO 开始。这应该会迅速缩小可能出现的问题的范围。

【讨论】:

  • 谢谢,我才意识到几个月前我的笔记本电脑发生了一次小跌倒:P 磁盘可能有问题。我正在另一台机器上尝试。
  • 不,同样的行为也在另一台机器上,有趣的是完全相同的查询需要更多时间(又是几秒钟..)。我知道在磁盘上运行会影响性能,但是几秒钟的延迟是不可接受的。如果我将记录存储在一个普通文件中,我可以更快地计算我的统计数据! :) 我会尝试使用索引。
  • 除了iostat,Mongo还提供mongostat进程,它显示(1)Mongo使用了多少RAM - resident(2)页面错误,以及其他信息 - docs.mongodb.org/manual/reference/program/mongostat
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-30
  • 2012-10-29
相关资源
最近更新 更多