MongoDB中的索引应保持在最低限度。或者我在阅读this之后尝试。 ..我还提到了这个nice preso的一些很好的提示。
我有一个问题,让我设计一个例子:
我需要存储 中存储的商品的数据,这些数据由目录编制索引。
我有几个地点。在每个地方我都可以买到很多商品。每种商品都可以有货或不有。每个三元组都在给定的目录中找到。
CATALOG_X: { { location: "...", good: "...", stock_or_not: 0|1 },
{ location: "...", good: "...", stock_or_not: 0|1 },
...
}
e.g:
CATALOG1: NEWYORK - BREAD - 0 // 0 is out of stock
CATALOG2: LOSANGELES - WATER - 1 // 1 is in stock
一个复杂因素:我通过仅通过目录的查询获取这些的状态。喜欢:
getMeStatusOfCatalog("CATALOG1") -> { "NEWYORK - BREAD" : 0 } // location - good : instock
然而:重点,getMeStatusOfCatalog
可能只是停止给我一个特定商品的答案,所以如果我再也看不到BREAD
,我仍然需要设置{{1}该特定目录的0
。这意味着在我的#34;写"操作我需要得到所有过去"活跃"基于目录的商品(BREAD
以下)。
我的应用程序中的主要业务目标是我需要显示每个位置的细分,例如:
in_catalog
如果我将Location 1 (New York) has: bread which is out of stock, etc
Location 2 (Los Angeles) has: water which is fine, etc
设置为_id
,那么我可以查询"LOCATION:GOOD"
并获取我需要的所有内容*。总体:
/^LOCATION/
但是,我对基于{
_id: "LOCATION:GOOD"
catalog: "..."
in_stock: 0|1
in_catalog: 0|1
}
的数据插入/更新感到困扰。我如何获取所有需要更新的文件?
我无法将其添加到之前讨论过的getMeStatusOfCatalog
,因为我再也无法使用left-anchored-regex了。我需要将_id
作为索引(复合,唯一)吗?像:
catalog
通过这种方式,我牺牲空间(双索引)来获得更快的查询。
您如何将其设计为具有高性能读写?
答案 0 :(得分:2)
在插入和查询性能之间总是需要权衡。在添加索引以优化查询时,会影响插入速率。
但是,除非您的用例是Web规模事务或事件处理系统(每秒数千个事务),否则您不太可能注意到由于一个或两个复合索引导致的插入性能问题。您可能会使解决方案变得更加复杂,以解决您不具备的问题。
事实上,您提出的解决方案无意中更有可能导致插入问题!
如果可能,您应该使用_id字段。但是,如实现的那样,默认的_id字段有两个重要的属性:
当MongoDB执行插入或更新时,它会根据_id的值将文档放在磁盘上(此行为因存储引擎而异 - MMapv1特别容易受到影响)。在您的实现中,您正在丢失第二个属性,因此完全有可能在大规模时,单个插入或更新可能会强制MongoDB重新组织磁盘上的数据,这将非常慢。
如果您仔细阅读了您引用的演示文稿,您将看到他们为_id选择的密钥保留了这两个属性!
对于您的应用程序,我将单独留下_id,而是在复合索引中包含catalog,location和good作为文档属性。是的,它会略微增加存储要求并且会在不知不觉中影响插入性能,但在发现性能问题之前,您的数据集会非常大。
我还认为您通过使用正则表达式搜索来人为地影响查询性能。虽然有这个功能,但MongoDB并不是一个全文搜索引擎。如果您需要类似的东西(类似Google的查询),请考虑使用ElasticSearch或相关技术。
最后,如果您确实需要在保持查询性能的同时进行Web规模插入性能,您可能会发现自己在其他地方进行权衡。例如,您可以插入或更新没有索引的文档,然后使用oplog保持"只读"索引版本同步。有一些真正创新的架构以这种方式与MongoDB和ElasticSearch结合,提供了出色的性能(例如:http://blog.mpayetta.com/elasticsearch/mongodb/2016/08/04/full-text-indexing-with-elastic-search-and-mongodb/