2

我正在从网站上抓取一系列产品并将它们存储在数据库中。目前,我正在使用 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 完全不熟悉,所以任何建议都将不胜感激。

4

1 回答 1

2

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

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

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

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

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

  • mongo 文档建议将数据嵌入到数组中“对于某些用例”是有意义的。你的听起来像一个这样的用例,即我不会为每个产品/时间戳创建一个文档。
  • 您也不希望每个产品一个文档,因为 mongo 不擅长增长非常长的数组。
  • 因此,剩下的选项是特定时间段内的每个产品/时间戳一个。和这个一起去。不幸的是,您必须尝试一些事情才能准确确定如何构建此文档。这里有几件事可以尝试:
    • 使用“期间”属性来指示相关期间的开始时间。在产品/期间创建索引。
    • 当您附加到本文档中的数据结构时,您可以使用 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 的产品,那么您可以通过索引快速完成。(不过这里没有什么神奇之处:与任何数据库一样,索引的维护成本可能很高,因此请谨慎创建它们)。

于 2012-02-14T20:36:29.063 回答