【问题标题】:Why $in is much faster than $all?为什么 $in 比 $all 快得多?
【发布时间】:2012-09-11 07:01:03
【问题描述】:
db.tablebusiness.find({ "LongitudeLatitude" : { "$nearSphere" : [106.772835, -6.186753], "$maxDistance" : 0.053980478460939611 }, "Prominent" : { "$gte" : 15 }, "indexContents" : { "$all" : [/^soto/, /^nasi/] } }).limit(200);

db.tablebusiness.find({ "LongitudeLatitude" : { "$nearSphere" : [106.772835, -6.186753], "$maxDistance" : 0.053980478460939611 }, "Prominent" : { "$gte" : 15 }, "indexContents" : { "$in" : [/^soto/, /^nasi/] } }).limit(200);

这是结果

/* 88 */
{
  "ts" : ISODate("2012-09-11T06:57:26.801Z"),
  "op" : "query",
  "ns" : "newisikota.tablebusiness",
  "query" : {
    "LongitudeLatitude" : {
      "$nearSphere" : [106.772835, -6.186753],
      "$maxDistance" : 0.053980478460939611
    },
    "Prominent" : {
      "$gte" : 15.0
    },
    "indexContents" : {
      "$all" : [/^soto/, /^nasi/]
    }
  },
  "ntoreturn" : 200,
  "nscanned" : 48,
  "nreturned" : 48,
  "responseLength" : 60002,
  "millis" : 3821,
  "client" : "127.0.0.1",
  "user" : ""
}

/* 89 */
{
  "ts" : ISODate("2012-09-11T06:57:43.147Z"),
  "op" : "query",
  "ns" : "newisikota.tablebusiness",
  "query" : {
    "LongitudeLatitude" : {
      "$nearSphere" : [106.772835, -6.186753],
      "$maxDistance" : 0.053980478460939611
    },
    "Prominent" : {
      "$gte" : 15.0
    },
    "indexContents" : {
      "$in" : [/^soto/, /^nasi/]
    }
  },
  "ntoreturn" : 200,
  "nscanned" : 200,
  "nreturned" : 200,
  "responseLength" : 249598,
  "millis" : 320,
  "client" : "127.0.0.1",
  "user" : ""
}

注意:$all 查询有时会运行 26 秒。

解释结果如下:

db.tablebusiness.find({ "LongitudeLatitude" : { "$nearSphere" : [106.772835, -6.186753], "$maxDistance" : 0.053980478460939611 }, "Prominent" : { "$gte" : 15 }, "indexContents" : { "$all" : [/^soto/, /^nasi/] } }).limit(200).explain();




{
        "cursor" : "GeoSearchCursor",
        "nscanned" : 48,
        **"nscannedObjects" : 48,**
        "n" : 48,
        "millis" : 8563,
        "nYields" : 0,
        "nChunkSkips" : 0,
        "isMultiKey" : false,
        "indexOnly" : false,
        "indexBounds" : {
        }
}
>


db.tablebusiness.find({ "LongitudeLatitude" : { "$nearSphere" : [106.772835, -6.186753], "$maxDistance" : 0.053980478460939611 }, "Prominent" : { "$gte" : 15 }, "indexContents" : { "$in" : [/^soto/, /^nasi/] } }).limit(200).explain();
{
        "cursor" : "GeoSearchCursor",
        "nscanned" : 200,
        **"nscannedObjects" : 200,**
        "n" : 200,
        "millis" : 516,
        "nYields" : 0,
        "nChunkSkips" : 0,
        "isMultiKey" : false,
        "indexOnly" : false,
        "indexBounds" : {
        }
}

注意 $in 搜索会扫描更多对象。

最坏的结果是最坏的,mongdob 可以进行 $in 搜索,然后过滤掉。这个比例应该不会很大。

【问题讨论】:

  • 也许 $in 正在使用索引而 $all 没有。你能用 .explain() 运行查询来找出答案吗?
  • 从解释看来两者都使用相同的索引。
  • 其实这是另一个问题。为什么我看不到所用索引的名称?我是否使用了错误版本的 mongodb?我以为我下载了最新的。

标签: mongodb indexing


【解决方案1】:

您正在将苹果与橙子进行比较。两个查询返回不同的结果。 $all 表示字段值应匹配所有输入,而 $in 表示字段值应匹配任何一个值。 $all 是与,$in 是或。

结合 $limit - $all 查询将需要查看更多文档才能找到匹配项。

【讨论】:

  • 因为 indexContents 是一个数组
  • 我很清楚$all和$in之间的区别,如果时间上的区别不是那么大我可以理解。即使在极限处合并,两者都需要找到最接近的文档。另请注意,说明显示 $in 实际上扫描了更多文档。
  • 是的,匹配 $in 的点数会多于 $all,这实际上表明 $in 应该比 $all 慢。你的推理是无效的。即使 $in 找到更多积分来满足 100 的配额,它也不能只是休息。
  • 当你使用 limit 时,它会在找到所需数量的文档后停止(除非你有排序)。我无法解释扫描的文档数量较少。这个结果是否可重复,可能存在可能导致差异的并发活动 - 例如等待锁定?您可以多次运行查询并记下时间吗?你能按其他顺序运行它们吗 - 首先是 $in,然后是 $all?
  • 这与大多数2个关键字一致。 $in 总是优于 $all。另外,说到排序,$nearSphere 按距离排序吧?
【解决方案2】:

我在Why using $all in mongodb is much slower?问过类似的问题

这次我只用了一个词。因此,$in 和 $all 之间应该没有区别。它们都是等价的。

仍然 $all 慢得多。

事实证明,根据对此的回答,mongodb 本身存在一个错误。

https://jira.mongodb.org/browse/SERVER-1748

我想在问题解决之前我根本不会使用 $all。

对于所有其他答案,您自己尝试过吗?

【讨论】:

    猜你喜欢
    • 2020-01-26
    • 2020-11-22
    • 1970-01-01
    • 2010-11-17
    • 2023-03-29
    • 2022-06-12
    • 1970-01-01
    • 2014-04-21
    • 2015-02-09
    相关资源
    最近更新 更多