Performance MongoDB$或比单个查询慢很多数量级

Performance MongoDB$或比单个查询慢很多数量级,performance,mongodb,logical-operators,Performance,Mongodb,Logical Operators,在查询10K个对象时,使用find_one单独查询每个对象似乎比一起查询要快得多,这没有多大意义。下面的方法会让事情变慢吗?对于前200个左右的对象,查询似乎会挂起一段时间,然后很快找到所有其他对象 import java.util.Date; import java.util.LinkedList; import java.util.List; import com.mongodb.BasicDBObject; import com.mongodb.DBCollection; import

在查询10K个对象时,使用find_one单独查询每个对象似乎比一起查询要快得多,这没有多大意义。下面的方法会让事情变慢吗?对于前200个左右的对象,查询似乎会挂起一段时间,然后很快找到所有其他对象

import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.mongodb.MongoClient;

public class MongoOrVsSingleQuery {

    public static void main(String[] args) throws Exception {
        MongoClient mc = new MongoClient();
        mc.getDB("foo").dropDatabase();
        DBCollection foo = mc.getDB("foo").getCollection("foo");
        DBObject index = new BasicDBObject("a", 1);
        index.put("b", 1);
        foo.ensureIndex(index);
        List<DBObject> lo = new LinkedList<DBObject>();
        for (int i = 1; i < 10001; i++) {
            DBObject o = new BasicDBObject("a", i);
            o.put("b", 1);
            lo.add(o);
        }
        System.out.println("insert: " + new Date());
        foo.insert(lo);
        for (DBObject o: lo) {
            o.removeField("_id");   
        }
        DBObject query = new BasicDBObject("$or", lo);
        System.out.println("find one: " + new Date());
        for (DBObject o: lo) {
            foo.findOne(o).get("a");
        }
        System.out.println("find: " + new Date());
        DBCursor dbc = foo.find(query);
        for (DBObject o: dbc) {
            if ((int) o.get("a") % 100 == 0) {
                System.out.println("find obj: " + o.get("a") + " " + new Date());
            }
        }
        System.out.println("done: " + new Date());
    }
}
在查询过程中,这是currentOp()的典型输出:


当然这是有道理的,一个$or是sperate子句,比如运行两个find_one,但是结果会合并回来,以省略重复项,因此当您在mongodb内部进行度量时,服务器端的每个查询都会被删除faster@Sammaye如果我没看错你的评论,你是说合并时间占了3个月完成1万个findOnes,而5个月完成1万个$or的项目?如果是这样的话,如果有大量查询,那么运行findOne()似乎总是更有效。对于单独的find_查询,没有合并时间,合并是在使用$or时进行的,因为$or的每个子句都是一个新查询,所以MongoDB运行查询并合并重复的查询。可能需要很长时间才能输入10K条目。是的,当有大量用户时,查找一个可能会在90%的时间内更有效queries@Sammaye那么,
$或
有什么意义呢?什么时候应该使用一个
$或
而不是多个查询?嗯,当你有一个复杂的查询不能由两个单独的查询来满足时。例如,您使用它的方式是选择一个数据矩阵,使用的更像是我收集的数据中的$in子句(我不太懂Java),而$or更像是使用两个不同的子句只找到一个结果的能力……嗯,这没有帮助,但是的
insert: Tue Nov 19 07:16:02 PST 2013
find one: Tue Nov 19 07:16:02 PST 2013
find: Tue Nov 19 07:16:05 PST 2013
find obj: 100 Tue Nov 19 07:16:08 PST 2013
find obj: 200 Tue Nov 19 07:21:22 PST 2013
find obj: 300 Tue Nov 19 07:21:22 PST 2013
*snip*
find obj: 9900 Tue Nov 19 07:21:22 PST 2013
find obj: 10000 Tue Nov 19 07:21:22 PST 2013
done: Tue Nov 19 07:21:22 PST 2013
~$ mongo
MongoDB shell version: 2.4.3
connecting to: test
> use foo
> db.currentOp()
{
    "inprog" : [
        {
            "opid" : 40221,
            "active" : true,
            "secs_running" : 241,
            "op" : "getmore",
            "ns" : "foo.foo",
            "query" : {
                "$msg" : "query not recording (too large)"
            },
            "client" : "127.0.0.1:58696",
            "desc" : "conn7",
            "threadId" : "0x7fef961f8700",
            "connectionId" : 7,
            "locks" : {
                "^" : "r",
                "^foo" : "R"
            },
            "waitingForLock" : false,
            "numYields" : 124,
            "lockStats" : {
                "timeLockedMicros" : {
                    "r" : NumberLong(390668733),
                    "w" : NumberLong(0)
                },
                "timeAcquiringMicros" : {
                    "r" : NumberLong(195362976),
                    "w" : NumberLong(0)
                }
            }
        }
    ]
}
> db.version()
2.4.3