NoSQL (MongoDB/ DynamoDB) Schema



我正在从网站上抓取一系列产品并将它们存储在数据库中。目前,我使用MySQL,有两个表:

products (product_id, site, product_description, etc)
e.g. (1234, "xyz.com", "nice product", etc)
product_history (product_id, scrape_timestamp)
e.g. (1234, 2012-01-02 10:53:09)
(1234, 2012-01-03 11:02:09)

此模式意味着我可以获得过去任何时间列出的产品的快照。

我正在考虑迁移到NoSQL,因为(I)我经常从不同的站点获得不同的领域,(ii)每年的数据量将在5- 1000万个产品之间。我可以看到两种构造模式

的方法选项1:"嵌入式列表">

product_id,  site,      product_description, scrape_timestamp
1234,        "xyz.com", "test product",      {2012-01-02 10:53:09, 2012-01-03 11:02:09}

选项2:"二级索引">

keep both tables as above with the relational schema

我认为选项1将在像MongoDB这样的东西中工作,允许二级索引,而选项2将在MongoDB或DynamoDB中工作。(我正在考虑这两个,因为我想在云中托管一些东西,对我来说零维护开销)。

我的这些方法是正确的吗?哪一种效果最好?我完全不熟悉nosql,所以任何建议都会很感激。

您说您正在尝试解决以下数据存储问题:

  1. 每年1000万左右的历史数据点
  2. 异构数据点

每年1000万左右的历史数据点

正如评论中所指出的,每年1000万个数据点并不是一个大数据集。包括MySQL在内的大多数数据库都能够支持这一点,只要您知道如何对它们进行调优,所以不要仅仅为了解决这个问题而切换技术。如果你有关于如何调优MySQL的具体问题,那么我建议你单独发布一个问题。

关于基于mongodb的历史数据问题解决方案,您可能有一个product_history数据集合,您只需要决定在每个文档中放入多少条目。一些选项:每个产品一个;每个产品/时间戳一个;在特定时间段内,例如一天或一个月,每个产品/时间戳一个。更多细节:

  • mongo文档建议将数据嵌入到数组中"对于某些用例"是有意义的。你的用例听起来就是这样一个用例,即我不会为每个产品/时间戳创建一个文档。
  • 你也不希望每个产品一个文档,因为mongo不擅长增长很长的数组。
  • 所以,剩下的选项是在特定时间段内每个产品/时间戳一个。就选这个吧。不幸的是,您将不得不尝试一些事情,以确定如何准确地构建这个文档。这里有一些可以尝试的方法:
    • 使用"period"属性来指示所讨论的时间段的开始时间。创建产品/周期索引
    • 当你在本文档中添加数据结构时,你可以使用mongo的upsert功能来简化代码。
    • 根据新数据点出现的频率选择周期的持续时间(每小时、每天、每月等)。您可能需要根据负载测试调整此持续时间。
    • 按周期构造文档的最简单方法是使用一个数组来保存数据。但是,mongo不擅长向非常长的数组追加内容,因此有些人通过在文档中创建一个简单的树来提高性能。例如,如果您有一个每日文档,那么您可以在一天中每小时使用一个单独的数组:
{
"0" : [ 123, 456 ],
"1" : [ 789 ]
}

如果你有大量的数据不适合一个服务器的内存,你需要能够非常快速地读取历史数据,那么你可能从MongoDB对分片的支持中获得一些好处。基本上,您将能够拆分数据,这样读取就不必碰到磁盘。但是从你的问题中不清楚读取性能是否重要以及你做什么类型的读取,所以如果你想要更多信息,请发布一个新的问题。

异构数据点

关于您的问题的RDBMS解决方案,以下是我见过的最常见的方法:

  • 反规范化数据。你说每个产品有85个属性?然后创建一个有85列的表!你说另一种产品有20种不同的属性?然后在表中再添加20列!这个解决方案:
    • 很简单。
    • 表现良好,因为所有通常的非规范化的好处。
    • 破坏了使用关系数据库的一些好处。例如,大多数列不能有"非空"约束。
  • 数据归一化。创建一个表来捕获类型X的属性,创建另一个表来捕获类型Y,等等。如果您有一个新产品类型,那么添加一个新表。这个解决方案:
    • 可能很复杂。例如,如何决定将某些公共属性放在哪个表中?
    • 可能表现不佳。例如,如果您必须连接10个表才能从数据库中获得任何有用的信息,那么您就有问题了。
    • 将使数据库纯粹主义者高兴。
  • 使用行代替列。这个解决方案:
    • 操作复杂,难于维护。
    • 表现糟糕。
    • 破坏了使用关系数据库的一些好处。

(注意,还有其他基于rdbms的解决方案。例如,有些人喜欢将XML文档放入DB2中。

你在尝试最后一种方法,所以难怪你不开心!如果您打算坚持使用RDBMS,那么我建议您切换到我列出的其他方法之一。

现在,回到你关于NoSQL的问题。基于文档的NoSQL数据库(如MongoDB)是解决"异构数据点"问题的有吸引力的解决方案,因为它没有模式。您可以在一个文档中列出产品的规格,当您想要添加新属性时,只需这样做即可。MongoDB允许您对属性进行索引,因此,如果您想找到具有属性a的产品,那么您可以通过索引快速完成此操作。(这里没有什么神奇的:与任何数据库一样,索引的维护成本很高,所以要谨慎创建它们)。

最新更新