我们正在研究一种算法,通过可变路径计算将资源从多个点移动到X点的最佳方法,过程如下:
1)获取所有可能的路线(DB命中以获得解决方案中涉及的所有路线)
2)获取所有可能的起点
3)构建一个组合所有路由的双向图。
----- foreach起点----
4)使用Hoffman Pavley算法计算k最短路径(我们将其限制为一定数量的路径ei:前10个短路径)
-----实际起点的前进路径-----
5)评估计算我们可以从每个路径节点到目的地的资源量的路线
6)根据每个点移动的资源数量以及此可能解决方案中涉及的移动和转运数量(将资源从一个运输转移到另一个运输)分配标点符号。
----- END foreach路径为实际起点-----
----- END foreach起点----
7)返回由标点符号排序的正确解决方案
这个逻辑的第一个版本花了大约1分钟来计算解决方案。但是在第二次修订时,我们发现我们遇到了很多Select N + 1问题,因此我们对查询进行了优化(并非所有问题),现在每次运行需要大约3-10秒,具体取决于变量的数量。
但现在有人建议通过所有逻辑来处理SQL,并让SQL服务器处理所有计算,他说因为所有数据已经在SQL Server上,所以数据库进行所有计算所需的时间更少避免所有选择的N + 1和延迟加载问题。他还关注并发性,运行这种逻辑的多个用户会打倒app服务器,但他说sql-server可以很好地处理这种负载。
我的观点:也许我们应该尝试在尝试将1500行c#逻辑传递给Transact SQL之前优化所有查询。更不用说,对于某些计算,我们使用第三方库来进行双向图和Hoffman Pavley算法,而这些算法在交易中是不可用的,要么我们需要查找已经在transact中编写的其他东西,要么自己实现所有逻辑。
注意:我们使用Nhibernate作为ORM。
答案 0 :(得分:2)
将逻辑移动到SQL可能有所帮助,但它有成本:
所以我的观点是,在将所有逻辑迁移到数据库之前,您应该尝试优化查询。
答案 1 :(得分:2)
我只会考虑将逻辑移到数据库作为最后的手段。
一个很好的指南是在数据库中保持基于集合的处理,并在应用程序中进行迭代处理。你已经获得了许多foreach语句,除非它们可以扁平化为集合操作,否则你真的会在数据库世界中受到影响。
如果这是业务规则的应用,那么它应该在应用层中,除非有理由将其放入数据库。
将1500行移植到TSQL代码需要花费大量时间。如果它是最新版本的MSSQL,您可以使用.NET CLR,但根据我的经验,它比Windows上的.NET慢得多
预先提取所有需要的数据以避免N + 1选择应该相对简单;获取您需要的所有内容并将其全部加入到适当的对象图中。
最后,似乎为所有请求复制了前4个步骤。选择所有数据并处理前四个步骤然后将图形保留在内存中可能是有意义的,从而避免了为每个请求检索和预处理所有内容的显着前期命中。这可能是不可能的,但会完全消除数据检索问题。
答案 2 :(得分:1)
这是交易:
将逻辑转移到数据库通常可以提高复杂报表要求(如您的)的性能。这是通过更好地索引数据来实现的,这样索引就意味着大部分工作(即:排序)都是在插入时完成的。
由于排序工作是在插入时为您需要的索引完成的,因此最终会导致插入速度较慢和其他写入操作。对于需要做的不仅仅是报告的系统而言,这通常是有害的。
此外,在某些时候,您还需要考虑应用扩展的方式。当您这样做时,请考虑您的数据库服务器可能已经是最昂贵的服务器,以及升级最昂贵的服务器。仅许可成本将使您的数据库服务器升级不太适合您的预算经理。数据库通常也很难在集群中工作。与数据库相比,添加Web或应用程序服务器并让它们在农场中工作是在公园散步。出于这些原因,您可以采取的任何措施来释放数据库中的性能压力,这可能会改善您的应用扩展方式。
答案 3 :(得分:1)
很难提供有关如此通用的优化问题的见解,但声明:
“由于所有数据已经在SQL Server上,因此数据库进行所有计算所需的时间更短”
不一定是真的。如果您根本不更改逻辑,那么您的C#代码到t-sql的直接端口仍将运行尽可能多的查询。您将节省在SQL服务器和运行应用程序的计算机之间传输数据所需的时间,但这是瓶颈,还是SQL服务器实际运行所有这些查询所需的时间?每个查询的结果有多大?
另一个问题是t-sql在执行此处涉及的所有计算时会更快,因为它们涉及迭代表中的数据并使用该数据执行某些操作吗?我对此表示怀疑。根据实际处理的时间(而不是等待数据库),它甚至可能会变慢。
最重要的是,这听起来像翻译它将是一项巨大的努力,如果你甚至远程考虑这种方法,你应该做很多测试,以确定时间的确切位置,看看你可以获得什么,如果有的话。
答案 4 :(得分:0)
我同意“我只会考虑将逻辑移至数据库作为最后的选择。”上面写过。
如果使用CLR程序集,则第三方库可以包含在Transact SQL中,所以这不是问题。
从资源角度看,扩展应用程序服务器通常比扩展数据库服务器更容易(复制吗?)。因此,如果明天这些呼叫达到今天的10倍或50倍,我们确定您的数据库服务器仍会在可接受的时间进行计算以及其他任何事情吗?
从性能的角度来看,仅需优化SQL即可将时间从1分钟缩短至5秒。显然,如果您在单独的SQL引擎中使用了非优化的SQL,则与使用优化的SQL仍会有不同-再次在仅SQL的引擎中使用。
我建议专注于优化SQL和C#引擎。我想这N + 1个案例是中坚力量,在定稿前一个案例之前您将无法获得记录。仍然可以提前选择任何一项,以提高性能-与选择10条选择返回总共10条记录相比,使用3条选择返回总共1000条记录更好地获得10条记录。