【问题标题】:Table per-subclass strategy when populating a large tree from a database using NHibernate使用 NHibernate 从数据库中填充大树时的表每个子类策略
【发布时间】:2010-12-24 12:17:19
【问题描述】:

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

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

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

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

【问题讨论】:

  • +1 一个好问题,我正在设计一个可能有大约 20 个子类型的系统,并且我有同样的顾虑/问题。

标签: inheritance nhibernate table-per-class


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

    您在这里处理两个问题:

    1. 遍历大型层次结构。

    2. 大型对象图。

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

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

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

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

    在系统的性能关键区域,某些类型的操作 (例如大规模更新/删除)可能 受益于直接 ADO.NET。但 请等到你知道一些事情 是一个瓶颈。不要以为 直接 ADO.NET 必然更快。 如果需要直接使用 ADO.NET,它 可能值得打开 NHibernate ISession 并使用该 SQL 联系。这样你仍然可以使用 相同的交易策略和 底层连接提供者。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-09-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-10
      • 2011-01-20
      • 1970-01-01
      相关资源
      最近更新 更多