【问题标题】:Cascading a Multi-Level Delete and N+1级联多级删除和 N+1
【发布时间】:2014-09-28 00:03:18
【问题描述】:

我发现级联删除正在发送带有许多单独删除的 SQL,即 N+1 问题。

我有三个表:User、UserAttribute 和 Attribute。每个 User 有多个 UserAttribute,每个 UserAttribute 有一个 Attribute - 由以下 Maps 表示:

public UserMap() {
  Id(x => x.Id);

  Map(x => x.Description);

  HasMany(x => x.Attributes)
    .Inverse()
    .Cascade.AllDeleteOrphan();
}

public UserAttributeMap() {
  Id(x => x.Id);

  References(x => x.User)
    .Not.Nullable();

  References(x => x.Attribute)
    .Not.Nullable()
    .Cascade.All();
}

public AttributeMap() {
  Id(x => x.Id);

  Map(x => x.Name)
    .Unique();
}

在上面的测试场景中,我的架构是使用 FluentNH 生成的。

我遇到的问题是,当我删除一个用户实体时,级联会为每个用户属性和每个属性生成一个单独的删除;这是一个潜在的大性能问题(一个用户通常可能有数百个属性)。

映射是否有明显的问题会在这里触发 N+1 问题?我能做些什么来阻止它吗?这是疯话吗?


附带说明一下,我的 NHibernate 配置已经包含大批量大小,但据我所知,批处理不会像这样结束?当我对它们进行分析时,它们肯定不会被批量处理。

NHibernate v3.3.1.4000
FluentNHibernate v 1.4.0.0

UserTable: 
    Id
    Description

UserAttributeTable: 
    Id
    User_id (FK)
    Attribute_id (FK)

AttributeTable: 
    Id
    Name

【问题讨论】:

    标签: nhibernate fluent-nhibernate cascade fluent fluent-nhibernate-mapping


    【解决方案1】:

    您正在体验的删除过程是按步骤执行的,一个一个是经过设计的。原因是:

    删除操作比任何读取操作都少见。因此,对读取实现的批处理支持 - 不存在用于删除。

    查看对读取操作的强大批处理支持:

    如果我们真的想提高删除过程的性能,我们可以使用:

    ...如前所述,自动和透明的对象/关系映射与对象状态的管理有关。这意味着对象状态在内存中可用,因此直接在数据库中操作(使用 SQL 数据操作语言 (DML) 语句:INSERT, UPDATE, DELETE)数据不会影响内存中的状态。然而,NHibernate 提供了用于批量 SQL 样式 DML 语句执行的方法,这些语句通过 Hibernate 查询语言 (HQL) 执行...

    来自该资源的代码示例:

    ISession session = sessionFactory.OpenSession();
    ITransaction tx = session.BeginTransaction();
    
    String hqlDelete = "delete Customer c where c.name = :oldName";
    // or String hqlDelete = "delete Customer where name = :oldName";
    int deletedEntities = s.CreateQuery( hqlDelete )
            .SetString( "oldName", oldName )
            .ExecuteUpdate();
    tx.Commit();
    session.Close();
    

    我们可以看到,在 DB 端执行的 SQL 语句没有将任何实体加载到应用层。这意味着,我们根本不会从级联中获利,但我们可以提高性能。

    总结:NHibernate 支持对读取操作进行批处理。级联是一一触发的。我们可以跳过级联并在实体之上使用 HQL 优化 DELETE

    【讨论】:

    • 拉迪姆;感谢您的意见 - 您能找到您的第一个报价的来源吗?我意识到 HQL 是一种选择,但如果可能的话,我现在宁愿避免使用它。当然,允许删除通过级联链接在一起,批量删除的能力会是一个明显的遗漏吗?这确实感觉像是一个错误 - 这不是一个相当普遍的情况吗..?
    • @Stevie:我在删除级联时遇到了同样的问题,其中 NHibernate 正在一个一个地删除子集合。除了 HQL 或不进行批量删除的理由之外,您是否找到了针对这种情况的任何解决方案?
    • @SarabjeetSingh - 恐怕不是。 HQL 是我在这个特定实例中选择的解决方案,但现在我倾向于将 EF 和原始 SQL 结合起来。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-24
    • 1970-01-01
    • 2015-10-06
    • 1970-01-01
    相关资源
    最近更新 更多