3

我的理解是查询 null 查找为 null 的字段以及不存在的字段。

mongo 手册还指出“$exists 即使有索引也不是很有效”

查询 null 是否也应该被认为是低效的?

如果您知道您要查找的字段存在但为空,那么编写以下代码是否更有效:

db.foo.find( { "y" : { $type : 10 } } )

比:

db.foo.find( { "y" : null } )

假设该字段已编入索引

编辑:给出一些使用方式的背景信息,以便人们可以提出更好的方法:我正在跟踪文档上发生的处理步骤。我有每个步骤的时间戳,所以我知道它何时发生。定期运行内务处理过程并检查任何尚未发生的任务(即不存在完成的时间戳)以确保没有遗漏任何事情

4

2 回答 2

2

我不能肯定地说哪个更快,但是新闻组中有一个线程,有人对$type-query 的性能有疑问。

撇开这一点不谈,出于三个原因,我不会使用该$type查询:

  1. 它更难阅读和理解。即使是普通的 MongoDB 用户也可能不知道自己脑子里想{type : 10}的是什么。
  2. 正如您已经指出的那样,语义是不同的。该$type查询允许“两种不同的空值”,即字段不存在的文档,以及字段存在但为空的文档。在反序列化时,这可能会在大多数语言中变成相同的对象,但$type-query 会区分它们。
  3. 索引用于索引数据,而不是元信息。即使查询优化器能够映射它,我仍然会坚持更直接的解决方案。

我相信另一个性能风险可能是 null 值的潜在低选择性:如果一半的文档具有某些值y,而一半的文档具有 null y,则查询 null 元素将返回大量文档,并且可以迭代游标昂贵的。但这仅在有很多空值时才成立。

于 2012-06-06T17:44:41.090 回答
1

我在这里做了一个快速测试并运行了几个解释来查看每个查询的样子,第一个是指定类型的查询:

PRIMARY> db.nulltest.find( { "a" : { $type : 10 } } ).explain()
{
    "cursor" : "BtreeCursor a_1",
    "nscanned" : 110011,
    "nscannedObjects" : 110011,
    "n" : 110011,
    "millis" : 121,
    "nYields" : 0,
    "nChunkSkips" : 0,
    "isMultiKey" : false,
    "indexOnly" : false,
    "indexBounds" : {
        "a" : [
            [
                null,
                null
            ]
        ]
    }
}

然后以 null 为标准:

PRIMARY> db.nulltest.find( { "a" : null  } ).explain()
{
    "cursor" : "BtreeCursor a_1",
    "nscanned" : 110011,
    "nscannedObjects" : 110011,
    "n" : 110011,
    "millis" : 122,
    "nYields" : 0,
    "nChunkSkips" : 0,
    "isMultiKey" : false,
    "indexOnly" : false,
    "indexBounds" : {
        "a" : [
            [
                null,
                null
            ]
        ]
    }
}

结果看起来几乎相同(1ms 并不重要),并且在说明中的索引范围相同。因此我怀疑这里根本没有区别,所以坚持使用更易读的语法是个好主意

于 2012-06-08T14:17:56.047 回答