我正在使用mongoDB存储一个querylog并得到一些关于它的统计数据.我存储在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但没办法.哪里我错了?
这里有几个因素会影响速度.有必要收集一些额外的数据来确定原因.
一些潜在的问题:
索引:您使用正确的索引吗?你可能应该索引IsClick/Date
.这使得范围第二是正常的建议.请注意,这与索引不同Date/IsClick
,顺序很重要.尝试.explain()
查询以查看正在使用的索引.
数据大小:在某些情况下,数据过多可能导致速度缓慢.这可能是太多文档或太多大文档.它也可能是因为试图在一个非常大的干草堆里找到太多的针头.你在data(reslen
)和12k文件中带回252k ,所以这可能不是问题所在.
磁盘IO: MongoDB使用内存映射文件,因此使用大量虚拟内存.如果您有比RAM更多的数据,那么获取某些文档需要"转到磁盘".转向磁盘可能是一项非常昂贵的操作.您可以使用iostat
或resmon
(Windows)等工具来识别"转到磁盘" 以监视磁盘活动.
根据个人经验,我强烈怀疑#3,可能会从#1加剧.我会在运行.explain()
查询时开始观察IO .这应该很快缩小可能出现问题的范围.