确定MongoDB索引以最大化性能并最小化索引

确定MongoDB索引以最大化性能并最小化索引,mongodb,Mongodb,MongoDB中的索引应保持在最小值。或者我在阅读后试着。。我还用一些很好的技巧来处理这个问题 我有一个问题,让我举个例子: 我需要存储有关存储在位置的商品的数据,这些位置由目录索引 我有几个地方。在每个地方我都可以有很多货物。每种商品都可以有库存,也可以没有库存。每个三元组都可以在给定的目录中找到 CATALOG_X: { { location: "...", good: "...", stock_or_not: 0|1 }, { location: "...", g

MongoDB中的索引应保持在最小值。或者我在阅读后试着。。我还用一些很好的技巧来处理这个问题

我有一个问题,让我举个例子:

我需要存储有关存储在位置的商品的数据,这些位置由目录索引

我有几个地方。在每个地方我都可以有很多货物。每种商品都可以有库存,也可以没有库存。每个三元组都可以在给定的目录中找到

CATALOG_X: { { location: "...", good: "...", stock_or_not: 0|1 },
             { location: "...", good: "...", stock_or_not: 0|1 },
             ...
           }
e、 g:

一个复杂的问题是:我通过一个仅按目录的查询来获取它们的状态。比如:

getMeStatusOfCatalog("CATALOG1") -> { "NEWYORK - BREAD" : 0 } // location - good : instock
然而:重要的一点是,
getMeStatusOfCatalog
可能会停止给我一个特定商品的答案,因此如果我再也看不到
BREAD
,我仍然需要为该特定目录将
BREAD
设置为
0
。这意味着在我的“写入”操作中,我需要根据目录获取所有过去的“活动”商品(在目录下
中)

我在应用程序中的主要业务目标是,我需要显示每个位置的明细,如:

Location 1 (New York) has: bread which is out of stock, etc
Location 2 (Los Angeles) has: water which is fine, etc
如果我将我的
\u id
设置为
“LOCATION:GOOD”
,那么我可以作为
/^LOCATION/
进行查询,并获得我需要的所有东西。总体而言:

{ 
  _id: "LOCATION:GOOD"
  catalog: "..." 
  in_stock: 0|1
  in_catalog: 0|1
}
但是,基于
getMeStatusOfCatalog
的数据插入/更新让我感到困扰。我将如何获取所有需要更新的文档

我无法将其添加到前面讨论的
\u id
,因为我将无法再使用左锚定正则表达式。我是否需要制作
目录
索引(复合、唯一)?比如:

通过这种方式,我牺牲了空间(双索引)以获得更快的查询


如何将其设计为同时具有性能读取和写入功能?

在插入和查询性能之间总是有一个折衷。在添加索引以优化查询时,会影响插入率

但是,除非您的用例是web级事务或事件处理系统(每秒数千个事务),否则您不太可能注意到由于一个或两个复合索引而导致的插入性能问题。为了解决一个你没有的问题,你可能会使你的解决方案更复杂

事实上,您提出的解决方案无意中增加了插入问题的可能性

确实,如果可能,您应该使用_id字段。但是,在实现时,默认的_id字段有两个重要属性:

  • 独特性
  • 它随时间而增加
  • 当MongoDB执行插入或更新时,它会根据_id的值将文档放在磁盘上(此行为因存储引擎而异,特别容易受影响的是MMapv1)。在您的实现中,您将丢失第二个属性,因此完全有可能在大规模情况下,一次插入或更新可能会迫使MongoDB重新组织磁盘上的数据,这将非常缓慢

    如果您仔细阅读您引用的演示文稿,您将看到他们为_id选择的键维护了这两个属性

    对于您的应用程序,我将不使用_id,而是在复合索引中包含目录、位置和与文档一样好的属性。是的,它将略微增加存储需求,并在不知不觉中影响插入性能,但在您注意到性能问题之前,您的数据集将非常大

    我还认为,通过使用正则表达式搜索,您人为地影响了查询性能。尽管有这项功能,MongoDB并不是为了成为一个全文搜索引擎而构建的。如果你需要类似的东西(谷歌式查询),那么考虑使用弹性搜索或相关技术。
    最后,如果在维护查询性能的同时确实需要web级插入性能,您可能会发现自己在其他地方做出了权衡。例如,您可以插入或更新没有索引的文档,然后使用oplog保持“只读”索引版本的同步。有一些真正创新的体系结构将MongoDB和ElasticSearch结合在一起,提供了优异的性能(例如:

    覆盖_id不是一个好的做法,就像您在这里所做的那样。只需在您的集合中提供至少两个示例数据即可。getMeStatusOfCatalog(“CATALOG1”)->{“NEWYORK-BREAD”:0}你能提供这段代码的描述吗?纽约-面包是一个正确的值。你从哪个键得到这个值?嗯..OVERriding the id似乎是优化id的最佳方法,正如上面链接的preso I中所解释的(这是有意义的)如果你知道你在做什么,并且你让它变得独一无二,那为什么会不好呢?我试着编辑一下上面的数据。谢谢!!你提供了一些有价值的建议!那么,你提出的解决方案是这样的吗?(只是为了确保我没有误解)。顺便说一句,我永远不会质疑“好”,仅目录或位置,所以我想我只需要这两个作为_id。此外:我将有一组有限的记录,比如1000条,但读/写速度应该很快(这是我的目标)。PS:u位置和_目录的组合不必是唯一的。谢谢!有1000条记录也让我想知道“根据_id的值将文档放在磁盘上”适用。我有两个集合:一个集合只有1000个条目,总是以读取方式访问;另一个集合有无数条条目,如果它们根据id随时间增加而发送到磁盘上,这是可以的。只有1000条记录,我可以避免“过度优化”的诱惑"。不要过载_id,只需像您的pastebin示例中那样在位置和目录上使用索引。在1000条记录中,您担心的问题都不会被察觉。换句话说,优化插入性能可能会使插入时间提高亚毫秒,但这几乎不值得增加复杂性u将添加到optimi中
    { 
      _id: "LOCATION:GOOD"
      catalog: "..." 
      in_stock: 0|1
      in_catalog: 0|1
    }
    
    { 
      _id: "LOCATION:GOOD:CATALOG" // unique by itself, repeating catalog to ensure unique, used for fast reads
      _catalog: "..." // unique by itself, used for fast writes
      in_stock: 0|1
      in_catalog: 0|1
    }
    
    createIndex( { "_id": 1, "_catalog": 1 }, { unique: true } )