`

n+1问题

 
阅读更多
  • http://hi.baidu.com/victorlin23/blog/item/8b7a3382670cd9b16d811963.html

Find()方法下FetchType.LAZY、FetchType.EAGER、@Fetch(FetchMode.JOIN)的区别2010-08-27 16:13结论:1.使用
例如:@ManyToOne(fetch = FetchType.LAZY)将会产生N+1的问题。
      2.使用:@ManyToOne(fetch = FetchType.EAGER)将会使用join查询,推断hibernate对eaer进行了优化并不会产生N+1的问题。 
      3.使用:@Fetch(FetchMode.JOIN)将和第2项描述的执行效果和步骤是一样的,都是使用join 可以得出官方文档:Hibernate_Annotations.pdf第62页描述的Table 2.3. Lazy and fetch options equivalent是正确的。完全等价。hibernate重载了EJG的Fetch注解                                      
一、@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "SERVICE_ID", referencedColumnName = "ID")
public SystemServiceInfo getSysService() {
   return sysService;
}
使用Lazy查询,由于需要立即访问触发了数据库查询。这个时候出现了N+1的问题:
    select
        count(*) as y0_ 
    from
        at_t_client_and_service this_ 
    inner join
        AT_T_CLIENT_INFO clientinfo1_ 
            on this_.CLIENT_ID=clientinfo1_.id 
    where
        (
            1=1
        ) 
        and (
            clientinfo1_.id = ?
        )
Hibernate: 
    select
        * 
    from
        ( select
            this_.id as id56_1_,
            this_.URL as URL56_1_,
            this_.CLIENT_ID as CLIENT15_56_1_,
            this_.CREATE_DATE as CREATE3_56_1_,
            this_.SERVICE_ID as SERVICE16_56_1_,
            this_.NAME_SPACE_URL as NAME4_56_1_,
            this_.LOCAL_PART_SERVICE as LOCAL5_56_1_,
            this_.LOCAL_PART_PORT as LOCAL6_56_1_,
            this_.PERIOD_BEGIN_DATE as PERIOD7_56_1_,
            this_.PERIOD_END_DATE as PERIOD8_56_1_,
            this_.FTP_FLAG as FTP9_56_1_,
            this_.FTP_RELATIVE_FLAG as FTP10_56_1_,
            this_.FTP_PATH as FTP11_56_1_,
            this_.FTP_PORT as FTP12_56_1_,
            this_.FTP_USER as FTP13_56_1_,
            this_.FTP_PASSWORD as FTP14_56_1_,
            clientinfo1_.id as id63_0_,
            clientinfo1_.CLIENT_ID as CLIENT2_63_0_,
            clientinfo1_.CLIENT_IP as CLIENT3_63_0_,
            clientinfo1_.CLIENT_NAME as CLIENT4_63_0_,
            clientinfo1_.REGEST_TIME as REGEST5_63_0_,
            clientinfo1_.REMARK as REMARK63_0_ 
        from
            at_t_client_and_service this_ 
        inner join
            AT_T_CLIENT_INFO clientinfo1_ 
                on this_.CLIENT_ID=clientinfo1_.id 
        where
            (
                1=1
            ) 
            and (
                clientinfo1_.id = ?
            ) ) 
    where
        rownum <= ?
Hibernate: 
    select
        systemserv0_.id as id28_0_,
        systemserv0_.COMM as COMM28_0_,
        systemserv0_.SERVICE_NAME as SERVICE3_28_0_,
        systemserv0_.CREATE_DATE as CREATE4_28_0_ 
    from
        AT_T_SERVICE systemserv0_ 
    where
        systemserv0_.id=?
Hibernate: 
    select
        systemserv0_.id as id28_0_,
        systemserv0_.COMM as COMM28_0_,
        systemserv0_.SERVICE_NAME as SERVICE3_28_0_,
        systemserv0_.CREATE_DATE as CREATE4_28_0_ 
    from
        AT_T_SERVICE systemserv0_ 
    where
        systemserv0_.id=?


二、@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "SERVICE_ID", referencedColumnName = "ID")
public SystemServiceInfo getSysService() {
   return sysService;
}
并未出现N+1的问题
Hibernate: 
    select
        count(*) as y0_ 
    from
        at_t_client_and_service this_ 
    inner join
        AT_T_CLIENT_INFO clientinfo1_ 
            on this_.CLIENT_ID=clientinfo1_.id 
    where
        (
            1=1
        ) 
        and (
            clientinfo1_.id = ?
        )
Hibernate: 
    select
        * 
    from
        ( select
            this_.id as id61_2_,
            this_.URL as URL61_2_,
            this_.CLIENT_ID as CLIENT15_61_2_,
            this_.CREATE_DATE as CREATE3_61_2_,
            this_.SERVICE_ID as SERVICE16_61_2_,
            this_.NAME_SPACE_URL as NAME4_61_2_,
            this_.LOCAL_PART_SERVICE as LOCAL5_61_2_,
            this_.LOCAL_PART_PORT as LOCAL6_61_2_,
            this_.PERIOD_BEGIN_DATE as PERIOD7_61_2_,
            this_.PERIOD_END_DATE as PERIOD8_61_2_,
            this_.FTP_FLAG as FTP9_61_2_,
            this_.FTP_RELATIVE_FLAG as FTP10_61_2_,
            this_.FTP_PATH as FTP11_61_2_,
            this_.FTP_PORT as FTP12_61_2_,
            this_.FTP_USER as FTP13_61_2_,
            this_.FTP_PASSWORD as FTP14_61_2_,
            clientinfo1_.id as id63_0_,
            clientinfo1_.CLIENT_ID as CLIENT2_63_0_,
            clientinfo1_.CLIENT_IP as CLIENT3_63_0_,
            clientinfo1_.CLIENT_NAME as CLIENT4_63_0_,
            clientinfo1_.REGEST_TIME as REGEST5_63_0_,
            clientinfo1_.REMARK as REMARK63_0_,
            systemserv4_.id as id29_1_,
            systemserv4_.COMM as COMM29_1_,
            systemserv4_.SERVICE_NAME as SERVICE3_29_1_,
            systemserv4_.CREATE_DATE as CREATE4_29_1_ 
        from
            at_t_client_and_service this_ 
        inner join
            AT_T_CLIENT_INFO clientinfo1_ 
                on this_.CLIENT_ID=clientinfo1_.id 
        left outer join
            AT_T_SERVICE systemserv4_ 
                on this_.SERVICE_ID=systemserv4_.id 
        where
            (
                1=1
            ) 
            and (
                clientinfo1_.id = ?
            ) ) 
    where
        rownum <= ?


三、 @ManyToOne
@Fetch(FetchMode.JOIN)
@JoinColumn(name = "CLIENT_ID", referencedColumnName = "ID")
public ClientInfo getClientInfo() {
   return clientInfo;
}

未出现N+1的问题。而且和第二种配置的效果完全一样,证实了hibernate做eager时进行了优化,使用了ourtjoin,并不会产生N+1问题。
Hibernate: 
    select
        count(*) as y0_ 
    from
        at_t_client_and_service this_ 
    inner join
        AT_T_CLIENT_INFO clientinfo1_ 
            on this_.CLIENT_ID=clientinfo1_.id 
    where
        (
            1=1
        ) 
        and (
            clientinfo1_.id = ?
        )
Hibernate: 
    select
        * 
    from
        ( select
            this_.id as id35_2_,
            this_.URL as URL35_2_,
            this_.CLIENT_ID as CLIENT15_35_2_,
            this_.CREATE_DATE as CREATE3_35_2_,
            this_.SERVICE_ID as SERVICE16_35_2_,
            this_.NAME_SPACE_URL as NAME4_35_2_,
            this_.LOCAL_PART_SERVICE as LOCAL5_35_2_,
            this_.LOCAL_PART_PORT as LOCAL6_35_2_,
            this_.PERIOD_BEGIN_DATE as PERIOD7_35_2_,
            this_.PERIOD_END_DATE as PERIOD8_35_2_,
            this_.FTP_FLAG as FTP9_35_2_,
            this_.FTP_RELATIVE_FLAG as FTP10_35_2_,
            this_.FTP_PATH as FTP11_35_2_,
            this_.FTP_PORT as FTP12_35_2_,
            this_.FTP_USER as FTP13_35_2_,
            this_.FTP_PASSWORD as FTP14_35_2_,
            clientinfo1_.id as id47_0_,
            clientinfo1_.CLIENT_ID as CLIENT2_47_0_,
            clientinfo1_.CLIENT_IP as CLIENT3_47_0_,
            clientinfo1_.CLIENT_NAME as CLIENT4_47_0_,
            clientinfo1_.REGEST_TIME as REGEST5_47_0_,
            clientinfo1_.REMARK as REMARK47_0_,
            systemserv4_.id as id58_1_,
            systemserv4_.COMM as COMM58_1_,
            systemserv4_.SERVICE_NAME as SERVICE3_58_1_,
            systemserv4_.CREATE_DATE as CREATE4_58_1_ 
        from
            at_t_client_and_service this_ 
        inner join
            AT_T_CLIENT_INFO clientinfo1_ 
                on this_.CLIENT_ID=clientinfo1_.id 
        left outer join
            AT_T_SERVICE systemserv4_ 
                on this_.SERVICE_ID=systemserv4_.id 
        where
            (
                1=1
            ) 
            and (
                clientinfo1_.id = ?
            ) ) 
    where
        rownum <= ?

参考官方文档:Hibernate_Annotations.pdf   P62。The Hibernate annotations overrides the EJB3 fetching options



 



分享到:
评论

相关推荐

    ibatis N+1问题

    在IT行业中,数据库查询优化是提升系统性能的关键环节之一,而"Ibatis N+1问题"是使用MyBatis框架时常见的性能瓶颈。这个问题通常出现在一对多或者多对多的关联查询中,导致了大量的数据库交互,严重影响了应用的...

    浅谈Hibernate n+1问题

    浅谈Hibernate n+1问题 Hibernate 是一个基于Java的持久层框架,它提供了对数据库的访问和管理功能。在使用 Hibernate 进行数据访问时,经常会遇到一个问题,即 n+1 问题。该问题是指在一次数据库查询中,需要执行...

    hibernate n+1查询

    HIBERNATE的N+1查询问题 关联查询时

    Ruby On Rails中如何避免N+1问题

    N+1问题 N+1问题是数据库访问中最常见的一个性能问题,首先介绍一下什么是N+1问题: 举个例子,我们数据库中有两张表,一个是Customers,一个是Orders。Orders中含有一个外键customer_id,指向了Customers的主键id。...

    n-plus-one:Prisma如何解决N + 1问题-2020年Prisma日

    Prisma如何解决N + 1问题-2020年Prisma日 该存储库包含2020年Prisma Day演讲“ Prisma如何解决N + 1问题”的相应代码。 结果 名称 要求/秒 字节/序列 阿波罗PG 2.6 625 kB 阿波罗棱镜发现 7.8 1.87兆字节 ...

    3n+1问题 C语言实现

    1. **3N+1问题**: 一种简单的数学游戏,对于任何正整数n,通过特定规则操作,最终会收敛至1。 2. **循环结构**: 使用`for`和`while`循环来遍历指定范围内的整数并计算每个数的数列长度。 3. **条件判断**: 利用`if-...

    具有递推关系S_{n+2}=pS_{n+1}+qS_n的数列的通项公式1

    这里讨论的是一个具有特定形式的递推关系:\( S_{n+2} = pS_{n+1} + qS_n \),其中 \( n \geq 1 \),\( S_1 \) 和 \( S_2 \) 是数列的初始项,而 \( p \) 和 \( q \) 是常数。这个递推关系可以用来找到数列的一般项 ...

    Mysql解决数据库N+1查询问题

    简介 在orm框架中,比如hibernate和mybatis都可以设置关联对象,比如user对象关联dept ...dept,是n次,所以是n+1问题,其实叫1+n更为合理一些。 mybatis配置 UserMapper.xml &lt;result column

    n_plus_one_control:RSpec和Minitest匹配器,以防止N + 1查询问题

    我发现自己无法通过测试来验证另一个N + 1问题后,这个宝石诞生了。 安装将此行添加到您的应用程序的Gemfile中: group :test do gem "n_plus_one_control"end 然后执行: $ bundle用法规范首先,将NPl

    spring-hibernate-query-utils:库提供工具来检测N + 1查询并计算使用Spring和Hibernate生成的查询

    关于该项目在调查SpringBoot应用程序中的性能问题时,我发现了臭名昭著的N + 1查询问题,该问题使我的服务性能丧失了。 有关更多详细信息,请查看文章消除Spring Hibernate N + 1查询。 在设法解决了这个问题之后,...

    Factorization of the Cyclotomic Polynomials Q2^(n+1)(x)

    割圆多项式Q2^(n+1)(x)的分解,武跟强,李研超,本文研究了割圆多项式Q2^(n+1)(x)的分解问题。解决问题用到的方法为数论中的理论。最后给出了Qp^(n+1)(x)的分解及计数定理,并且得到了q�

    求1+1/2+1/3+1/4+…….+1/100的值

    尽管1到100的项之和可以精确计算,但当n变得非常大时,计算结果会非常接近自然对数ln(n),具体公式为Hn ≈ ln(n) + γ,其中γ是欧拉-马斯cheroni常数,大约等于0.5772156649。 在C#中,可以使用`Math.Log`函数来...

    C++式子n^1+n^2+n^3+……+n^10计算

    \[ S_n = n^1 + n^2 + n^3 + \ldots + n^k = \frac{n^{k+1} - 1}{n - 1} \] 当 \( n = 1 \) 时,由于 \( 1^k = 1 \) 对所有正整数 \( k \) 成立,所以 \( n^1 + n^2 + \ldots + n^k \) 的和为 \( k \)。根据题目,\...

    例1 设n为大于1的正整数,证明n^5+n^4+1不是素数(小蓝本P004)B.pdf

    6. 逻辑推理和错误证明:文档中通过假设n^5+n^4+1不是素数,然后通过推理发现这个假设会导致矛盾(n^3-n+1=1或n^2+n+1=1,但n=0或n=-1与n大于1矛盾),从而证明了原假设是错误的,即n^5+n^4+1实际上是素数。...

    RSpec和Minitest匹配器可防止N + 1查询问题-Ruby开发

    与其他库(例如db-query-matchers,rspec-sqlimit等)不同,使用n_plus_one_cont N +1 Control RSpec和Minitest匹配器可以防止N + 1查询问题。 为什么还有另一个断言来声明数据库查询呢? 与其他库(例如db-query-...

    5_3.rar_n平方+n+41

    1. 接受用户输入的正整数`n`。 2. 使用公式`p = n^2 + n + 41`计算`p`的值。 3. 检查`p`是否为素数。这可以通过试除法实现,即从2到`sqrt(p)`遍历所有可能的因子,如果找到任何因子能整除`p`,则`p`不是素数。 下面...

    整数划分问题 将正整数n表示成一系列正整数之和:n=n1+n2+…+nk,其中n1≥n2≥…≥nk≥1,k≥1。

    其中满足\( n_1 \geq n_2 \geq \ldots \geq n_k \geq 1 \),且\( k \geq 1 \)。每个满足条件的表达式都称为\( n \)的一个划分。 #### 示例解释 以正整数6为例,它具有以下11种不同的划分方式: - 6 - 5 + 1 - 4 + 2...

    C 代码 通过考虑 简单的 Collatz 3n+1 问题.rar

    在这个Collatz问题的实现中,函数会根据Collatz规则对给定的n进行处理,如果n为偶数,则调用自身传入n/2,若为奇数,则传入3*n+1。这个过程一直持续到n等于1为止,从而形成一个递归链。 C++源代码可能如下: ```...

Global site tag (gtag.js) - Google Analytics