索引具有用户定义模式的无模式dbs?

时间:2011-02-23 20:10:44

标签: mongodb indexing database-design nosql

任何数据库最重要的功能之一是查询速度。我们存储数据并希望快速访问符合我们标准的数据。然而,最近,无模式数据库变得流行。如果我们有一个无架构的数据库但实际上有一个推断的(在头部/在应用程序中)架构,这是一回事;它刚刚没有被数据库正式声明。

另一方面,假设我们确实需要一个开放式数据库,其中有几个用户拥有自己的模式来处理各自的问题区域。用户将定义他自己的“域”。该域(RDBMS服务器上的数据库)将具有其类型(RDBMS中的表),并且这些类型将具有其自身的特性(RDBMS中的列)。如何创建复合索引以从给定域中提取特定对象/文档/记录(您有什么用途)?我的查询应该选择一个或多个域(一个IN子句),只针对某些列选择一个主题类型(例如CalendarEvent)(start_date> =今天,start_date< =今天+ 1周,open_for_registration = true,calendar_name ='上市')。在具有固定模式的数据库中(即使未声明也隐含),这很简单:您可以针对列创建复合索引。

复杂性在于我们基本上只创建了一个实例,即MongoDB就像一个RDBMS服务器,它有许多数据库,每个数据库及其相关模式都是我们的“域”。

在将这个问题破坏了一个星期并查看各种数据库(MongoDB,Neo4j,MySQL,PostgreSQL)后,我发现了一些可能的解决方案:

  • 索引所有属性。属性可以在Properties表中表示,也可以在MongoDB中表示为嵌入式文档。在RDBMS中,属性值必须序列化为字符串。缺点:a)一次只能搜索一个属性(没有复合索引),b)所有内容都有索引,所以我们会产生不必要的开销。
  • 索引选择属性。在PostgreSQL中,可以使用Filtered Index完成。基本上,属性记录会有一个我需要维护的“索引”。无论过滤的索引是否使用该特定属性,此位都将驱动。缺点:a)我们仍然只能一次搜索一个属性。这消除了使用“复合索引”。我可以想象模仿复合索引的唯一方法是搜索每个索引属性并返回PK的交集。
  • 创建/维护数据库构造以反映工作索引。在MongoDB中,我可以创建一个“indexables”集合。此集合中的文档可能如下所示:{domain_id:ObjectId(..),type_id:ObjectId(..),fields:{field1:“some int value”,field2:“some date value”,field3:“some位值“}}。然后我在{domain_id:1,type_id:1,“fields.field1”:1,“fields:field2”:1,“fields:field3”,1}上索引“indexables”集合。然后,每次我在“things”集合中创建/更新文档时,我都必须将其值插入indexables的field1,field2,field3插槽中。 (这与MongoDB很好地配合,因为我可以将任何数据类型的值插入到这些占位符中。在MySQL中,使用相同的模式我必须将值序列化为字符串。)我还必须维护domain_id和type_id。基本上,它是一个建立在数据库处理的索引之上的索引层(我自己管理)。缺点:还有额外的开销。虽然数据库通常会代表我管理索引,但我现在必须小心这样做。由于MongoDB没有事务概念,因此无法保证文档及其各种索引只需一步即可完成。 PROS:我有复合索引。索引在域级别维护。
  • 我考虑过允许用户拥有自己的数据库X实例。或者在MongoDB中拥有自己的集合。但我想知道这是否会产生更多问题,特别是当我们遇到实际限制(允许数据库或集合的数量)时。在没有太多考虑之后我把这个想法抛弃了。

其他想法?其他类型的数据库可能更好地处理这个问题?

同样,这个想法是这样的:不同的用户管理他们自己的域。域内可以是任何“类型”的项目。对于每个打字的项目,我们都有属性。我希望允许用户针对其域运行查询,以获取具有与其条件匹配的属性的类型的项。 (因此复合指数)

最后一个想法。域名本身并不是非常有意义的。它可能有10-20“类型”。在每种类型中,它们可能多达5000条记录(在大多数情况下),在极端情况下可以说20000条记录。

不幸的是,尽管Joel Spolsky's advice我尝试过宇航员架构,但这是其中一种情况。

1 个答案:

答案 0 :(得分:1)

  

可能更好地处理此问题的其他类型的数据库?

你考虑过Excel吗?也许只是索引平面文件:)

看,你在这里遇到的基本问题是没有银弹。你的想法很好,但在某些时候你必须接受一些权衡。

您无法索引所有内容。在某些时候,您将不得不识别“常用”查询并为这些事物构建一些索引。除非你计划将所有内容保存在内存中,否则你最终会在某些时候创建索引。

  

在每种类型中,它们可能多达5000条记录(在大多数情况下),在极端情况下可以说20000条记录。

嘿,这是一个真正的限制。你可以在5k记录中投入多少硬件? 200k记录怎么样?是否足以将其全部保存在RAM中?把它的一部分放在RAM里?只保留RAM中的索引?

如果你想让用户只使用他们自己的“动态”模式,我个人觉得 MongoDB 很自然。特别是对于您指示的这些小数据集。

但它无论如何都不是银弹。这些解决方案中的每一个都有各自的问题。如果有一个实际的数据库可以处理你提出的所有要求,让我们面对它,我们都将使用该数据库:)