需要有关编写自己的eager-load算法的建议

时间:2009-05-29 14:14:27

标签: .net sql

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

我的问题是,生成预先加载SQL语句的最佳实践是哪种?我已经考虑过并提出了两种方法 -

假设有4个表的经典例子 - CustomerCategory有许多客户 客户有很多订单 订单有很多OrderDetail

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

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

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

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

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

1 个答案:

答案 0 :(得分:0)

首先,您的域模型严重错误。我个人无法证明CustomerCustomerCategory个对象的集合是正确的,因为从性能的角度来看它只是没有意义:大多数时候你需要一个客户(加上它的组),而一个完整的组顾客将在蓝色的月亮中被要求一次,但它会一直存在,造成各种各样的问题。这同样适用于Customer有很多Order s。

现在,问你的问题。通常认为应该最小化到数据库的往返次数,即使以检索超过必要的数据为代价也是如此。也就是说,连接两个大表(长和宽)同时从两个相关表中选择数据可能是一个性能杀手,所以要小心。

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

如果您使用的是Microsoft SQL Server 2005或更高版本,则可以使用MARS将多个select填充到一个批处理中,然后为只发出一个SQL命令的对象的整个图形进行水合。 / p>