嵌套实体和叶实体属性的计算-SQL或NoSQL方法


10

我正在从事一个名为“菜单/食谱管理”的业余项目。

这就是我的实体及其关系的样子。

A Nutrient具有属性CodeValue

一个Ingredient具有集合Nutrients

一个Recipe具有的收藏,Ingredients有时也可以具有其他的收藏recipes

一个Meal有一个收集RecipesIngredients

一个Menu有集合Meals

关系可以描述为

菜单实体和关系

在其中一个页面中,对于所选菜单,我需要显示根据其成分(膳食,食谱,成分和相应的营养素)计算出的有效营养素信息。

到目前为止,我正在使用SQL Server来存储数据,我正在从C#代码导航链,从菜单的每一餐开始,然后汇总营养值。

我认为这不是一种有效的方法,因为每次请求页面时都会进行此计算,并且成分会偶尔更改。

我在考虑有一个后台服务,该服务维护一个称为MenuNutrients({MenuId, NutrientId, Value})的表,并且在任何成分(餐,菜谱,成分)发生变化时,将使用有效营养素填充/更新该表。

我认为GraphDB非常适合此要求,但是我接触NoSQL的机会有限。

我想知道显示给定菜单营养的这种要求的替代解决方案/方法是什么。

希望我对场景的描述清楚。


我们在说多少个对象?性能真的会成为问题吗?
flup

@flup平均一个菜单可以有8顿饭,每顿饭可以有2个食谱和2种食材,每个食谱可以有6-8种食材。
成都

您的箭头方向不对吗?
Branko Dimitrijevic 2013年

您是否看到过Nerd Dinner Entity Framework示例?
Akash Kava

Answers:


8

根据要求和体系结构,可能会有性能改进选项:

  • 您可以使用索引视图(矩阵化)来提高 RDBMS(SQL服务器)级别的读取性能
    基本上,您需要做的是:
    创建一个常规视图。
    在该视图上创建聚簇索引

  • 在应用程序级别使用兑现机制将提高性能。
    如果有可能并且可行的话,使用现金策略,例如单身懒人现金将对您有所帮助。

NoSql:
有很多关于Sql vs NoSql的好文章,像这样

部分使我感兴趣:

在哪里使用NoSql:

如果您的数据库是3NF, 并且您不执行任何联接(您只是选择一堆表并将所有对象放在一起,这就是大多数人在Web应用程序中所做的事情)。

使用时准备:

  • 您最终要写作业来做一些事情,例如从不同的表/集合中加入数据,而RDBMS会自动为您做这些事情。
  • 您使用NoSQL的查询功能严重受损。MongoDb可能是最接近SQL的东西,但仍然远远落后于SQL。相信我。SQL查询超级直观,灵活而强大。NoSql查询不是。
  • MongoDb查询只能从一个集合中检索数据,并且只能利用一个索引。MongoDb可能是最灵活的NoSQL数据库之一。在许多情况下,这意味着需要更多往返服务器才能找到相关记录。然后开始对数据进行非规范化-这意味着后台作业。
  • 它不是关系数据库这一事实意味着您将没有外键约束(某些人认为它们表现不佳)以确保数据一致。我向您保证,这最终将在数据库中造成数据不一致。做好准备 您很可能会开始编写流程或检查以保持数据库的一致性,这可能不会比让RDBMS为您做的更好。
  • 忘记像休眠这样的成熟框架。

除了决定使用或不使用的NoSql,在一个有用的文章NOSQL数据库管理系统比较他们的意图可以在这里找到一些它们都集中在高读取,低写入,映射简化,HA ......
在看看在它们的排名和受欢迎度上,按类别可能有用。


感谢您的详细信息。将会检查链接并回复您。
成都

3

我实际上您不需要使用图数据库,只需将所需的值存储在一个较高的级别中。就像存储Order和一样OrderItems。您不必每次要显示订单时都计算总计。取而代之的是,您只计算总和,增值税和其他东西,并将它们与一起存储Order

order.Subtotal = order.Items.Sum(item => item.Price);
order.Tax = order.Subtotal * 0.25m; // just a value
order.Total = order.Subtotal + order.Tax;

// fast forward time
var subTotal = order.Items.Sum(item => item.Price);
var tax = subTotal * 0.25m;
var total = subTotal + tax;

if (toal == order.Total) {
   Console.Log("Why the hell I've just re-calculated total?");
}

3

我建议看一下命令查询责任隔离模式

基本上,可以创建2个不同的模型,而不必创建单个模型进行读写。一种针对更新进行了优化,另一种针对查询(了读取,报告等)进行了优化。这两个模型使用域事件(请参见DDD)进行同步(通常具有最终一致性)。

几个月前,我开始研究这种模式,它确实改变了我建模软件的方式。这并不容易,因为这是一个很大的转变,尤其是与其他技术(如DDD和事件源)一起使用时。但是值得。

网上有很多可用资源,搜索CQRS和DDD(并最终搜索事件源)。

此模式可以在SQL和noSql上使用。

在您的情况下,每次更换营养素时都会触发一个事件,以更新为读取而优化的读取模型。读取模型可以是例如菜单营养素的非规范化视图(为什么不使用nosql db进行有效读取)。您可以根据需要执行的查询拥有多个读取模型。

使用这种方法有一些含义,但是它具有很好的可扩展性和可扩展性。


这是我正在考虑的方法,但是不确定如何获取读取模型的数据(基本上有些过程应该为我获取读取模型的数据)。
成都

通常,读取模型在每次更改时都会更新。您应该使用命令(基于任务)而不是使用crud操作来实现ui。这样,每个命令都会反映到读取模型中。您不需要执行其他查询。设计命令使系统能够捕获用户的真实意图。

2

这很大程度上取决于您最初如何获得菜单和营养。您为什么认为效率不高?

据我了解,您进入数据库,获取菜单,然后再次获取每个食谱,然后再次获取每种成分,依此类推。这确实是效率低下的,因为有很多查询和到服务器的往返,这是造成延迟的主要原因。这称为SELECT N + 1问题。

您应该做的是通过JOIN对菜单中的所有表使用s直至营养素来获取单个查询中的所有数据,因此DB服务器可以使用所有关系和索引来一次获取所有数据。客户端C#应用仅处理并显示最终结果。这样做比一个接一个地效率更高。

通常,使用适当的查询技术和正确的索引进行关键查询,关系数据库可以在负载较大的大型表上很好地执行。


谢谢,我知道这取决于联接。由于菜单的成分有时会更改,因此我不想每次有人点击页面时都进行计算。相反,我希望后台服务进行计算,并且可以在需要时从表中简单地读取它。计算的问题是,当组成部分之一发生更改时,将确定整个链。
昌都

仅搜索几个关系就根本不会进行任何计算,即使有5或6 JOIN秒钟不应该对服务器造成负担(除非我们要获取数百或数千行)(如果正确地建立索引)到位。即使有大数据集,如果性能成为问题,您也始终可以基于整个结果构建视图,甚至可以索引视图以预先计算结果。

2

您似乎已经花了一些时间思考如何最好地对数据建模,以便可以轻松地更新和查询数据。但是,现在您需要提供对数据的访问权限。这两件事是分开考虑的。

您提到重新加载页面导致对数据库的新查询。您还提到数据库偶尔会被更新,并且当您希望这些更新及时显示在页面上时。减少查询开销的最佳方法是不执行查询。如果您一遍又一遍地运行相同的查询并获得相同的结果,为什么不暂时缓存它们呢?您应该能够在不修改项目其余部分的情况下在上游实现一些缓存。我建议阅读有关休息的信息。无论您是在rdbms还是nosql中实施项目,都可以通过减少访问数据库的次数来最好地解决此类性能问题。假设您在60秒内有100个要求相同的食谱。如果您缓存60秒,则只需访问数据库一次,因此性能提高了100倍。要看到通过切换到nosql达到相同的改进水平,将需要做更多的工作。

当您有大量数据或极高的读写速度要求时,Nosql类型的系统可能是一个很好的解决方案。但是,这种额外的性能是以扔掉参照完整性之类的东西为代价的。


1

出于实验或知识目的,您似乎想尝试Graph-DB,但您的示例显然是分层数据的示例,可以在其中通过节点进行向下/向上钻取。我不是Graph / Neo DB的专家,但我可以看到用户/您可以从此架构中请求数据的方式并没有太多复杂性。我看到数据库/架构设计的选择非常取决于要针对其查询方式和数据类型。从我的角度来看,当您使用SQLSERVER时,“ HierarchyI” D是将此节点作为Tree的一部分的最佳选择。


1

我的建议是像机器一样思考而不是像人一样思考。似乎是重复的,但是那台机器擅长。您必须问自己的一件事是“无论如何,我是否必须检索每个对象才能显示在页面上?” 如果是,请继续执行操作,与数据检索相比,执行简单数学运算时的CPU周期可以忽略不计。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.