7

我即将开始一个非常超出我正常职责范围的工作项目。作为一名 SQL DBA,我最初的想法是使用 SQL 数据库来处理项目,但我对 NoSQL 了解得越多,我就越相信它可能是更好的选择。我希望我可以使用这个问题来从高层次上描述这个项目,以获得关于使用每个选项的利弊的一些反馈。

该项目相对简单。我有一组具有各种属性的对象。其中一些属性对所有对象都是通用的,而一些属性只对对象的子集通用。我的任务是构建一个服务,用户根据对象的属性选择一系列过滤器,然后返回与所有过滤器匹配的对象列表。当用户选择过滤器时,他或她可能正在过滤公共或子集属性,但这是在前端抽象的。

^ 根据用户反馈,对象列表可能仅匹配某些过滤器,并且匹配的质量将通过分数显示给用户,该分数表明有多少条件匹配。

在观看了 Martin Folwler ( http://www.youtube.com/watch?v=qI_g07C_Q5I ) 的演讲后,文档样式的 NoSQL 数据库似乎应该满足我的需求,但鉴于我没有使用这种方法的经验,我也有可能遗漏了一些明显的东西。

一些附加信息 - 数据库最初将有大约 5,000 个对象,每个对象包含 10 到 50 个属性,但对象的数量肯定会随着时间的推移而增长,并且属性的数量可能会根据用户反馈而增长。此外,我希望能够在收到用户反馈时对产品进行快速更改,因此灵活性非常重要。

任何反馈都将不胜感激,如果我在讨论中遗漏了任何重要内容,我很乐意提供更多信息。谢谢。

4

3 回答 3

3

这个问题可以通过使用两种不同的技术来解决。第一个是使用设计相对良好的数据库模式和现代 RDBMS。通过使用通常的规范化原则对应用程序进行建模,您将从存储中获得非常好的单个 CRUD 语句响应。

正如您所猜测的那样,搜索此模式将是一场大规模的噩梦。不要这样做。而是考虑使用Solr/Lucene作为您的全文搜索引擎。Solr 对动态字段的支持意味着您可以动态地向文档/对象添加新属性,并且如果您正确设计了 Solr 模式,则可以立即在数据中进行搜索。

于 2013-10-22T15:42:07.200 回答
2

我不是 NoSQL 方面的专家,所以我不会提倡它。但是,我有几点可以帮助您解决有关关系数据库结构的问题。

我马上看到的第一件事是,您正在谈论继承(至少在概念上)。您的对象相互继承,因此您具有派生对象的附加属性。假设您要添加一种新类型的对象,您需要做的第一件事(概念上)是为其找到一个基本/超级(父)对象类型,它具有属性的子集,并且您正在添加它们(扩展基础对象类型)。

一旦你习惯了像上面所说的那样思考,接下来就是关系数据库的继承映射模式。我会从 Martin Fowler那里窃取术语来描述它。

您可以通过以下三种方式之一在数据库中保存继承链:

1 -单表继承:整个继承链在一张表中。因此,所有新类型的对象都进入同一个表。

优点:您的搜索查询只有一个表要搜索,并且它必须比例如连接更快。

缺点:例如,表的增长速度比选项 2 快;您必须添加一type列,说明该行是什么类型的对象;有些行有空列,因为它们属于其他类型的对象。

2 -具体表继承:为每种新类型的对象单独的表。

优点:如果搜索只影响一种类型,你一次只搜索一张表;例如,每个表的增长速度都比选项 1 慢。

缺点:如果同时搜索多个类型,则需要使用查询联合。

3 -类表继承:基本类型对象的一个​​表仅具有其属性,附加表具有每个子对象类型的附加属性。因此,子表是指具有 PK/FK 关系的基表。

优点:所有类型都存在于一个表中,因此使用公共属性很容易一起搜索。

缺点:基表增长很快,因为它也包含部分子表;您需要使用 join 来搜索具有所有属性的所有类型的对象。

选择哪一个?

这显然是一种权衡。如果您希望添加多种类型的对象,我会选择提供合理查询和缩放选项的具体表继承。类表继承似乎对快速查询和可扩展性不太友好。单表继承似乎更适用于少量类型。

你的电话,我的朋友!

于 2013-10-25T22:46:05.433 回答
1

不妨把这个作为答案。我应该评论说我不擅长 NoSQL,所以我倾向于倾向于 SQL。

我会这样做作为一个三表集。您将在网络上看到它被称为实体值对逻辑......这是一种处理项目的多个动态属性的方法。假设您有一堆产品,每个产品都有一些属性。

Prd 1 - a,b,c
Prd 2 - a,d,e,f
Prd 3 - a,b,d,g
Prd 4 - a,c,d,e,f

所以这里有 4 种产品和 6 种属性……同样的理论适用于数百种产品和数千种属性。将其保存在一个表中的标准方法需要产品信息以及 6 列来存储数据(在此设置中,至少有三分之一为空)。添加的新属性意味着更改表以向其中添加另一列,并提出一个脚本来填充现有的,或者将所有现有的都保留为空。不是最好玩的,会很头疼。

对此的替代方法是名称值对设置。您想要一个“标题”表来保存您的产品之间的共同值(例如名称或价格……所有产品始终具有的东西)。在上面的示例中,您会注意到每个记录都使用了属性“a”……这确实意味着属性 a 也可以是标题表的一部分。我们将这里的关键列称为“header_id”。

第二个表是一个参考表,它只是存储可以分配给每个产品的属性并为其分配一个 ID。我们将使用 atrr_id 作为键调用 table 属性。直截了当,上面的每个属性都是一行。

快速示例:

attr_id, attribute_name, notes
1,b, the length of time the product takes to install
2,c, spare part required
etc...

它只是您所有属性的列表以及该属性的含义。将来,您将在此表中添加一行,以便为每个标题打开一个新属性。

最终表是实际保存信息的映射表。您将获得产品 ID、属性 ID,然后是值。通常称为明细表:

prd1, b, 5 mins
prd1, c, needs spare jack
prd2, d, 'misc text'
prd3, b, 15 mins

查看数据如何存储为产品键、值标签、值?任何未来添加的产品都可以具有存储在此表中的任何属性的任意组合。添加新属性是在属性表中添加新行,然后根据需要填充详细信息表。

我相信也有一个 wiki ...... http://en.wikipedia.org/wiki/Entity-attribute-value_model

在此之后,它只是找出最好的方法来转出你的数据(我推荐 Postgres 作为开源数据库选项)

于 2013-10-22T17:57:25.113 回答