4

我正在使用 NHibernate 加载不同类型的对象的大树。映射是使用 table-per-subclass 策略实现的。我定义了一个基类“Node”,它只有几个字段(NodeId、ParentId、NodeType)和几个从 Node 继承并添加自己的字段的子类。

这种方法的实现很简单,我不能抱怨性能。一棵由 10 000 个不同类型对象组成的大树在几百毫秒内使用单次往返填充到我的旧机器上。然而,有一件事情让我担心:这种策略会导致生成一个复杂的查询,其中节点表与对应于已定义子类的所有其他表进行外部连接。虽然当不同子类的数量很少时这很好,但如果数量增加,OUTER JOIN 复杂度也会增加。

为每个类定义表似乎不是一个优雅的选择,当从基类中选择数据时它会运行缓慢(因为 UNION)。其他选项似乎增加了到数据库服务器的往返次数。

那么,当填充由不同类型的实体组成的大树时,您认为最佳实践是什么?有什么比每个子类的表更好的吗?

4

2 回答 2

2

为了防止连接,您可以使用 table-per-classhirarchy 策略。然后每个子类都驻留在同一个表中,并用一个鉴别器列进行鉴别。

我已经将这种方法用于 15 个子类。

唯一的缺点是你不能在子类的属性上定义非空约束,你必须在代码中处理这个。

于 2011-05-17T16:37:40.807 回答
2

您在这里处理两个问题:

  1. 遍历一个大的层次结构。

  2. 大对象图。

两者都是 ORM 会遇到麻烦的领域。ORM 将成为这里的瓶颈,因此当您遇到瓶颈时,您可能需要避开标准的 ORM 功能并使用存储过程来处理繁重的工作。

使用存储过程,您可以利用 SQL 的执行计划来解决问题、识别查询慢点并识别索引机会。

来自Nhibernate 文档(这是一个缓存 Nhibernate Forge 已关闭)

在瓶颈中使用手工编码的 ADO.NET。

在系统的性能关键区域中,某些类型的操作(例如,批量更新/删除)可能会受益于直接 ADO.NET。但是,请等到您知道某些东西是瓶颈。并且不要假设直接 ADO.NET 一定更快。如果需要直接使用 ADO.NET,可能值得打开 NHibernate ISession 并使用该 SQL 连接。这样您仍然可以使用相同的事务策略和底层连接提供程序。

于 2011-04-11T19:11:06.163 回答