Castle ActiveRecord / NHibernate 优化

发布于 2024-07-10 19:03:16 字数 3160 浏览 3 评论 0原文

我有以下结构:消息(消息表)可能有多个字段(字段表),每个字段可能有多个子字段(存储在同一个“字段”表中,唯一的区别是字段在“ParentField”中没有值柱子)。 子字段可能有子子字段等,但这并不重要。

当我检索 10 条消息,每条消息有 10 个字段,每个字段有 20 个子字段时,我可以从日志文件中看到 NHibernate 生成了 2000 个 SQL 调用。 有没有办法优化它?

谢谢!

这是 NHibernate 生成的 2000 个 SQL 语句之一:

SELECT   fieldresul0_.MessageResults_ID as MessageR6___2_, 
         fieldresul0_.ID as ID2_, 
         fieldresul0_.ID as ID5_1_, 
         fieldresul0_.Field_ID as Field2_5_1_, 
         fieldresul0_.Name as Name5_1_, 
         fieldresul0_.Value as Value5_1_, 
         fieldresul0_.MessagePosition as MessageP5_5_1_, 
         fieldresul0_.MessageResults_ID as MessageR6_5_1_, 
         fieldresul0_.ParentField_ID as ParentFi7_5_1_, 
         fieldresul1_.ID as ID5_0_, 
         fieldresul1_.Field_ID as Field2_5_0_, 
         fieldresul1_.Name as Name5_0_, 
         fieldresul1_.Value as Value5_0_, 
         fieldresul1_.MessagePosition as MessageP5_5_0_, 
         fieldresul1_.MessageResults_ID as MessageR6_5_0_, 
         fieldresul1_.ParentField_ID as ParentFi7_5_0_ 
FROM     FieldResults fieldresul0_ 
         LEFT OUTER JOIN FieldResults fieldresul1_ 
                      ON fieldresul0_.ParentField_ID=fieldresul1_.ID 
WHERE    fieldresul0_.MessageResults_ID=@p0 
ORDER BY fieldresul0_.MessagePosition

这是 ActiveRecord 生成的映射文件:

<?xml version="1.0" encoding="utf-16"?> 
    <hibernate-mapping  auto-import="true" default-lazy="false" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:nhibernate-mapping-2.2">  
      <class name="FieldResult, Data" table="FieldResults"> 
        <id name="ID" access="property" column="ID" type="Int32" unsaved-value="0"> 
          <generator class="native">    
            <param name="sequence">FieldResults_ID</param>  
          </generator>  
        </id>   
        <property name="FieldID" access="property" type="String">   
          <column name="Field_ID"/> 
        </property> 
        <property name="Name" access="property" type="String">  
          <column name="Name"/> 
        </property> 
        <property name="DisplayValue" access="property" type="String">  
          <column name="Value"/>    
        </property> 
        <property name="MessagePosition" access="property" type="Int32">    
          <column name="MessagePosition"/>  
        </property> 
        <many-to-one name="ParentMessage" access="property" class="MessageResult, Data" column="MessageResults_ID" />   
        <many-to-one name="ParentField" access="property" class="FieldResult, Data" column="ParentField_ID" />  
        <bag name="Children" access="property" table="FieldResults" lazy="false" cascade="all" order-by="Field_ID"> 
          <key column="ParentField_ID" />   
          <one-to-many class="FieldResult, Data" /> 
        </bag>  
      </class>  
    </hibernate-mapping>`   

I have the following structure: message (message table) may have multiple fields (fields table), and each field may have multiple subfields (stored in the same "fields" table with the only difference that fields dont have values in the "ParentField" column). Subfields may have subsubfields, etc., but this is not important.

When I retrieve 10 messages that have 10 field each, and each field has 20 subfields, I can see from the log file that NHibernate generates 2000 SQL calls.
Is there a way to optimize that?

Thanks!

Here is one of 2000 SQL statements generated by NHibernate:

SELECT   fieldresul0_.MessageResults_ID as MessageR6___2_, 
         fieldresul0_.ID as ID2_, 
         fieldresul0_.ID as ID5_1_, 
         fieldresul0_.Field_ID as Field2_5_1_, 
         fieldresul0_.Name as Name5_1_, 
         fieldresul0_.Value as Value5_1_, 
         fieldresul0_.MessagePosition as MessageP5_5_1_, 
         fieldresul0_.MessageResults_ID as MessageR6_5_1_, 
         fieldresul0_.ParentField_ID as ParentFi7_5_1_, 
         fieldresul1_.ID as ID5_0_, 
         fieldresul1_.Field_ID as Field2_5_0_, 
         fieldresul1_.Name as Name5_0_, 
         fieldresul1_.Value as Value5_0_, 
         fieldresul1_.MessagePosition as MessageP5_5_0_, 
         fieldresul1_.MessageResults_ID as MessageR6_5_0_, 
         fieldresul1_.ParentField_ID as ParentFi7_5_0_ 
FROM     FieldResults fieldresul0_ 
         LEFT OUTER JOIN FieldResults fieldresul1_ 
                      ON fieldresul0_.ParentField_ID=fieldresul1_.ID 
WHERE    fieldresul0_.MessageResults_ID=@p0 
ORDER BY fieldresul0_.MessagePosition

Here is mapping file that ActiveRecord generates:

<?xml version="1.0" encoding="utf-16"?> 
    <hibernate-mapping  auto-import="true" default-lazy="false" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:nhibernate-mapping-2.2">  
      <class name="FieldResult, Data" table="FieldResults"> 
        <id name="ID" access="property" column="ID" type="Int32" unsaved-value="0"> 
          <generator class="native">    
            <param name="sequence">FieldResults_ID</param>  
          </generator>  
        </id>   
        <property name="FieldID" access="property" type="String">   
          <column name="Field_ID"/> 
        </property> 
        <property name="Name" access="property" type="String">  
          <column name="Name"/> 
        </property> 
        <property name="DisplayValue" access="property" type="String">  
          <column name="Value"/>    
        </property> 
        <property name="MessagePosition" access="property" type="Int32">    
          <column name="MessagePosition"/>  
        </property> 
        <many-to-one name="ParentMessage" access="property" class="MessageResult, Data" column="MessageResults_ID" />   
        <many-to-one name="ParentField" access="property" class="FieldResult, Data" column="ParentField_ID" />  
        <bag name="Children" access="property" table="FieldResults" lazy="false" cascade="all" order-by="Field_ID"> 
          <key column="ParentField_ID" />   
          <one-to-many class="FieldResult, Data" /> 
        </bag>  
      </class>  
    </hibernate-mapping>`   

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

桃酥萝莉 2024-07-17 19:03:16

我猜这是一个 select n+1 问题。 您是否尝试过急切加载或自定义 HQL 查询? 如果您还没有,我将发布一些示例 HQL 来解决这个问题

I'd guess this was a select n+1 issue. Have you tried eager loading, or a custom HQL query? I'll post some example HQL to get around this if you haven't

伊面 2024-07-17 19:03:16

有一种方法可以帮助 nhibernate 执行一些更有效的连接。 明确告诉查询处理器包含带有“join fetch”的查找表,并通过 HQL 和 Session.CreateQuery()

from FieldRestults fr 
left join fetch fr.ParentMessage 
left join fetch fr.ParentField

优化我当前正在调查的另一个问题中的包来获取结果。

there is a way to help nhibernate perform some more efficient joins. explicitly tell the query processor to include lookup tables with a "join fetch" and get your results via HQL and Session.CreateQuery()

from FieldRestults fr 
left join fetch fr.ParentMessage 
left join fetch fr.ParentField

optimizing a bag in another issue that i'm currently investigating.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文