【问题标题】:Passing business logic (c#) to transact (sql) will improve performance?将业务逻辑(c#)传递给事务(sql)会提高性能吗?
【发布时间】:2011-05-26 05:29:19
【问题描述】:

我们正在研究一种算法,计算通过可变路线将资源从多个点移动到点 X 的最佳方式,过程如下:

1) 获取所有可能的路由(数据库命中以获取解决方案中涉及的所有路由)

2) 获取所有可能的起点

3) 构建一个结合所有路线的双向图。

-----foreach 起点----

4) 使用 Hoffman Pavley 算法计算 k 最短路径(我们将其限制为一定数量的路径 ei:前 10 条最短路径)

-----foreach 实际起点的路径-----

5) 评估路由,计算我们可以从每个路由节点到目的地携带多少资源

6) 根据从每个点移动的资源数量以及此可能解决方案中涉及的移动和转运(将资源从一种运输方式移动到另一种运输方式)的数量来分配标点符号。

-----END foreach 实际起点的路径-----

-----END foreach 起点----

7) 返回按标点符号排序的可能解决方案

这个逻辑的第一个版本需要大约 1 分钟来计算解决方案。但在第二次修订中,我们发现我们遇到了很多 Select N+1 问题,因此我们优化了查询(不是全部),现在每次运行大约需要 3-10 秒,具体取决于变量的数量。

但现在有人建议通过所有逻辑来处理 SQL,并让 SQL Server 处理所有计算,他说由于所有数据都已经在 SQL Server 上,数据库完成所有计算所需的时间会更少避免所有选择 N+1 和延迟加载问题。他还担心并发,多个用户运行这个逻辑会导致应用服务器宕机,但他说 sql-server 可以很好地处理这种负载。

我的意见:也许我们应该在尝试将 1500 行 c# 逻辑传递给 Transact SQL 之前尝试优化所有查询。更不用说对于某些计算,我们正在使用第三方库来实现交易中不可用的双向图和霍夫曼帕夫利算法,要么我们需要寻找其他已经在交易中编写的东西,要么我们自己实现所有这些逻辑。

注意:我们使用 Nhibernate 作为 ORM。

【问题讨论】:

    标签: c# algorithm performance tsql


    【解决方案1】:

    我同意“我只会考虑将逻辑移至数据库作为最后的手段”。上面写的。

    如果您使用 CLR 程序集,第三方库可以包含在 Transact SQL 中,所以这不是问题。

    从资源的角度来看,扩展应用程序服务器通常比扩展数据库服务器(复制?)更容易。因此,如果明天这些调用是今天调用的 X 10 或 X 50,我们确定您的数据库服务器仍会在可接受的时间进行计算和其他任何事情吗?

    从性能角度来看,仅优化 SQL 就可以从 1 分钟缩短到 5 秒。显然,如果您在单独的 SQL 引擎中使用未优化的 SQL,那么您仍然与使用优化的 SQL 有所不同——再次在单独的 SQL 引擎中使用。

    我建议专注于优化 SQL 和 c# 引擎。我猜那些 N+1 个案例是主干,在完成前一个案例之前你无法获得记录。您可以提前选择的任何内容都会提高性能 - 您最好获得 10 条记录,其中 3 次选择返回总共 1000 条(过滤 C# 中的 10 条)记录,而不是 10 次选择返回总共 10 条记录。

    【讨论】:

      【解决方案2】:

      这是交易:

      将逻辑转移到数据库通常可以提高复杂报表需求的性能,例如您的需求。这是通过更好的数据索引来实现的,这样索引意味着大部分工作(即:排序)在插入时为您完成。

      由于排序工作是在插入时为您需要的索引完成的,因此您最终会遇到较慢的插入和其他写入操作。这对于需要执行更多操作的系统通常是有害的,而不仅仅是您的报告。

      此外,在某些时候,您需要考虑应用的扩展方式。当您这样做时,请考虑您的数据库服务器可能已经是您最昂贵的服务器,也是最昂贵的升级服务器。仅许可成本就会使升级您的数据库服务器对您的预算经理不太满意。数据库通常也更难在集群中工作。与数据库相比,添加 Web 或应用程序服务器并让它们在农场中工作简直是天方夜谭。由于这些原因,您可以采取任何措施来释放数据库的性能压力,这可能会改善您的应用的扩展方式。

      【讨论】:

        【解决方案3】:

        很难就如此普遍的优化问题提供见解,但声明:

        “由于所有数据都已经在 SQL Server 上,因此数据库完成所有计算所需的时间更少”

        不一定是真的。如果您根本不更改逻辑,将 C# 代码直接移植到 t-sql 仍将运行同样多的查询,这些查询将花费同样长的时间来运行。您将节省在 SQL 服务器和运行应用程序的机器之间传输数据所需的时间,但这是瓶颈,还是 SQL 服务器实际运行所有这些查询所需的时间?每个查询的结果有多大?

        另一个问题是 t-sql 在执行此处涉及的所有计算时是否会更快,以至于它们涉及遍历表中的数据并使用该数据执行某些操作?我对此表示怀疑。根据实际处理的时间(而不是等待数据库),它甚至可能更慢。

        底线是,听起来翻译这将是一项巨大的工作,如果您甚至远程考虑这种方法,您应该进行大量测试以确定时间的确切去向,看看您可以获得什么,如果有的话。

        【讨论】:

          【解决方案4】:

          我只会考虑将逻辑移至数据库作为最后的手段。

          • 一个好的指南是在数据库中保留基于集合的处理,并在应用程序中进行迭代处理。你有许多 foreach 语句,除非它们可以被扁平化为集合操作,否则你在数据库世界中真的会受到影响。

          • 如果这是业务规则的应用,那么它应该在应用层,除非有理由将其放入数据库中。

          • 将 1500 行代码移植到 TSQL 将花费大量时间。如果它是最新版本的 MSSQL,您可以使用 .NET CLR,但根据我的经验,它比 Windows Server 上的 .NET 慢得多

          • 预先提取所有需要的数据以避免 N+1 选择应该相对简单;获取您需要的一切并将其全部加入到适当的对象图中。

          最后,似乎前 4 个步骤已针对所有请求进行了复制。选择所有数据并处理前四个步骤,然后将图形保存在内存中可能是有意义的,这避免了为每个请求检索和预处理所有内容的重大前期打击。这可能是不可能的,但会完全消除数据检索问题。

          【讨论】:

            【解决方案5】:

            将逻辑转移到 SQL 可能会有所帮助,但需要付出代价:

            • 维护执行与 1500 行 C# 代码相同的操作的 SQL 是一个真正的地狱(100 行查询、添加新功能后变得过时的存储过程等)
            • 调试要复杂得多

            所以我的意见是,在将所有逻辑迁移到数据库之前,您应该尝试优化查询。

            【讨论】:

            • 无法 +1 达到限制,但是 -- 同意,将逻辑转移到 sql 会导致真正的维护和性能问题。
            猜你喜欢
            • 2010-11-10
            • 2017-02-15
            • 2019-05-08
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2023-04-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多