【问题标题】:Need advice about writing my own eager-load algorithm需要关于编写我自己的急切加载算法的建议
【发布时间】:2009-05-29 14:14:26
【问题描述】:

我正在维护一个用 C# 编写的内部 ORM,它目前没有任何急切加载机制。为了提高性能,我们决定它需要预先加载,因此我们需要编写自己的代码来支持它。 (我和我的同事对任何 ORM 工具都没有任何经验,此外,由于一些遗留原因,我们不允许使用 LinqtoSQL、Entity Framework 或 Nhibernate 等流行工具。)

我的问题是,生成预加载 SQL 语句的公认最佳做法是什么?我想了想,想出了两个办法——

假设 4 个表的经典示例 - 一个 CustomerCategory 有很多 Customer 一个客户有很多订单 一个 Order 有很多 OrderDetail

并假设我想从所有 4 个表中预加载数据,并且我的条件是 - 其中 Order.OrderDate 在 '2008-05-05' 和 '2008-12-31' 之间

方法 1 - 我生成一个 sql 来从所有 4 个表中获取数据,所有表都使用内部连接,以便我为每个表的主键的每个唯一组合获得一行。我会将我的 Where 条件应用于此 sql。

方法 2 - 我生成一个 SQL 以首先仅获取订单数据,并将我的 Where 条件应用于此 sql,因为 Order.OrderDate 来自 Order 表。 然后,根据此查询的结果,我将知道我需要的所有订单 ID 值,因此我将使用这些来检索订单详细信息数据。我还将知道我需要的所有唯一客户 ID 值,因此我还将使用这些值从客户表中检索数据,最后我将对 CustomerCategory 执行相同的操作。这种方法总共需要 4 条 SQL 语句。

我看到第一种方法效率更高,但我的一位同事指出,第二种方法虽然使用了 4 条 SQL 语句,但更易于编写和维护,我同意。

对此的任何想法将不胜感激。 谢谢!

【问题讨论】:

    标签: .net sql


    【解决方案1】:

    首先,您的域模型大错特错。我个人不能证明Customer 对象集合在CustomerCategory 中是合理的,因为从性能的角度来看它没有意义:大多数时候你需要一个客户(加上它的组),而一个充满客户的组将是千呼万唤始出来,但它会一直存在,导致各种问题。这同样适用于拥有许多 Orders 的 Customer

    现在,回答您的问题。通常认为应该尽量减少到数据库的往返次数,即使是以检索到不必要的数据为代价。也就是说,连接两个大表(长表和宽表)以同时从两个关联表中选择数据可能会影响性能,所以要小心。

    我建议你看看它是如何在 NHibernate 中完成的。它允许您为每个关联指定获取策略(加入、选择),无论是一对一关联还是一对多关联。

    如果您使用的是 Microsoft SQL Server 2005 或更高版本,则可以使用 MARS 将多个 selects 填充到一个批次中,然后合并整个对象图,仅发出一个 SQL 命令。

    【讨论】:

    • 感谢您的帮助。我承认我们的模型确实有问题。我们将对其进行调查,并根据您的建议查看 nhibernate。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多