首页 > 解决方案 > 当存在大量字段时,在 MongoDB 中建立索引的正确方法是什么

问题描述

考虑到我有包含多个选项的搜索面板,如下图所示: 在此处输入图像描述

我正在使用 mongo 并以特定顺序在 3-4 个属性上创建复合索引。但是当我运行不同的搜索组合时,我每次都会在执行计划中看到不同的顺序(解释())。有时我在 Collection scan (bad) 上看到它,有时它正好适合索引 (IXSCAN)。

应该由 mongo 索引处理的选择性字段是:(brand,Types,Status,Warehouse,Carries ,Search - only by id)

我的问题是:

我是否必须创建具有不同顺序的所有字段的所有组合,它可以是 10-20 个复合索引。或 1-3 big Compound Index ,但同样无法解决订单。

处理各种字段组合的最佳策略是什么。

我使用具有不同对组合的相同结构查询

// Example Query. 
// fields could be different every time according to user select (and order) !!

 db.getCollection("orders").find({
  '$and': [
    {
      'status': {
        '$in': [
          'XXX',
          'YYY'
        ]
      }
    },
    {
      'searchId': {
        '$in': [
          '3859447'
        ]
      }
    },
    {
      'origin.brand': {
        '$in': [
          'aaaa',
          'bbbb',
          'cccc',
          'ddd',
          'eee',
          'bundle'
        ]
      }
    },
    {
      '$or': [
        {
          'origin.carries': 'YYY'
        },
        {
          'origin.carries': 'ZZZ'
        },
        {
          'origin.carries': 'WWWW'
        }
      ]
    }
  ]
}).sort({"timestamp":1})
// My compound index is:
{status:1 ,searchId:-1,origin.brand:1, origin.carries:1 , timestamp:1}

但它只有一种组合......它可能很像

a. {status:1} {b.status:1 ,searchId:-1} {c. status:1 ,searchId:-1,origin.brand:1} {d.status:1 ,searchId:-1,origin.brand:1, origin.carries:1} ........

此外,性能写入/读取会发生什么?,我认为写入会比读取减少...

查询模式是:

1. find(...) with '$and'/'$or'+sort

2.Aggregation with Match/sort

谢谢

标签: mongodbmongodb-querymongodb-indexes

解决方案


通常,索引仅在它们位于选择性字段上时才有用。这意味着具有特定值的文档数量相对于文档总数而言很小。

“小”的含义因数据集和查询而异。在确定索引是否有意义时,1% 的选择性是相当安全的。如果某个特定值存在于例如 10% 的文档中,则执行表扫描可能比在相应字段上使用索引更有效。

考虑到这一点,您的某些领域将是选择性的,而有些则不会。例如,我怀疑通过“OK”进行过滤不会很有选择性。您可以从索引考虑中消除非选择性字段 - 如果有人想要所有“OK”且没有其他条件的订单,他们最终会进行表扫描。如果有人想要“OK”且有其他条件的订单,则将使用适用于其他条件的任何索引。

既然您只剩下选择性(或至少有些选择性)字段,请考虑哪些查询既流行又具有选择性。例如,也许品牌+类型就是这样的组合。您可以添加与您希望具有选择性的流行查询匹配的复合索引。

现在,如果有人只按品牌过滤会发生什么?这可能是选择性的,也可能不是选择性的,具体取决于数据。如果您已经有关于品牌+类型的复合索引,则将其留给数据库来确定仅品牌查询是否更有效地通过品牌+类型索引或通过集合扫描来完成。

以这种方式继续处理其他流行的查询和字段。


推荐阅读