`

什么叫n+1次select查询问题?

sql 
阅读更多

什么叫n+1次select查询问题?

 

在Session的缓存中存放的是相互关联的对象图。默认情况下,当Hibernate从数据库中加载Customer对象时,会同时加载所有关联的Order对象。以Customer和Order类为例,假定ORDERS表的CUSTOMER_ID外键允许为null,图1列出了CUSTOMERS表和ORDERS表中的记录。



以下Session的find()方法用于到数据库中检索所有的Customer对象:

List customerLists=session.find("from Customer as c");

运行以上find()方法时,Hibernate将先查询CUSTOMERS表中所有的记录,然后根据每条记录的ID,到ORDERS表中查询有参照关系的记录,Hibernate将依次执行以下select语句:

select * from CUSTOMERS;
select * from ORDERS where CUSTOMER_ID=1;
select * from ORDERS where CUSTOMER_ID=2;
select * from ORDERS where CUSTOMER_ID=3;
select * from ORDERS where CUSTOMER_ID=4;

通过以上5条select语句,Hibernate最后加载了4个Customer对象和5个Order对象,在内存中形成了一幅关联的对象图,参见图2。



Hibernate在检索与Customer关联的Order对象时,使用了默认的立即检索策略。这种检索策略存在两大不足:

(1) select语句的数目太多,需要频繁的访问数据库,会影响检索性能。如果需要查询n个Customer对象,那么必须执行n+1次select查询语句。这就是经典的n+1次select查询问题。这种检索策略没有利用SQL的连接查询功能,例如以上5条select语句完全可以通过以下1条select语句来完成:

select * from CUSTOMERS left outer join ORDERS
on CUSTOMERS.ID=ORDERS.CUSTOMER_ID

以上select语句使用了SQL的左外连接查询功能,能够在一条select语句中查询出CUSTOMERS表的所有记录,以及匹配的ORDERS表的记录。

(2)在应用逻辑只需要访问Customer对象,而不需要访问Order对象的场合,加载Order对象完全是多余的操作,这些多余的Order对象白白浪费了许多内存空间。
为了解决以上问题,Hibernate提供了其他两种检索策略:延迟检索策略和迫切左外连接检索策略。延迟检索策略能避免多余加载应用程序不需要访问的关联对象,迫切左外连接检索策略则充分利用了SQL的外连接查询功能,能够减少select语句的数目。

 

 

分享到:
评论

相关推荐

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

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

    Rails N + 1查询自动检测为零误报/误报-Ruby开发

    已检测到N + 1个查询:从`users`的WHERE`users.`id` = 20 LIMIT 1中选择SELECT`users`。*从`users` WHERE`users`.`id` = 21 LIMIT 1从`users` WHERE`users``.id`中选择``users..id''= 22 LIMIT 1 SELECT`users .. *...

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

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

    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兆字节 ...

    prosopite:Rails N + 1查询自动检测为零误报误报

    N+1 queries detected: SELECT `users`.* FROM `users` WHERE `users`.`id` = 20 LIMIT 1 SELECT `users`.* FROM `users` WHERE `users`.`id` = 21 LIMIT 1 SELECT `users`.* FROM `users` WHERE `users`.`id` =...

    graphql-query-resolver:最小化由GraphQL和ActiveRecord生成的N + 1个查询

    GraphQL :: QueryResolver GraphQL :: QueryResolver是一个附加,它可使您的字段解析器将ActiveRecord发出的N + 1个SELECT最小化。 GraphQL :: QueryResolver将分析传入的GraphQL查询中的AST,并尝试将查询选择与...

    goone:goone在go中找到N + 1个查询

    Goone goone在go中找到N + 1(严格来说是for循环中的调用SQL)查询例子package mainimport ("database/sql""fmt""log"_ "github.com/go-sql-driver/mysql")type Person struct {Name stringJobID int}type Job ...

    修改表结构的 asp C# 源代码

    + "ID int IDENTITY(1,1) PRIMARY KEY CLUSTERED \n" + ")" oFormSql.sTblName.value = sObjName; oFormSql.sTblType.value = "TABLE"; oFormSql.sSqlString.value = sSqlString; if(!...

    SQL 基础--SELECT 查询

    格式:COALESCE (表达式1,表达式2,表达式3,...,表达式n) 作用:返回第一个不为空的值,如果所有的都为空,则返回NULL。 六、SELECT语句的用法 SELECT *|{[DISTINCT] column|expression [alias],...} ...

    Select精美下拉框(漂亮)

    if (-1==except && SS_VAR.SelectList[i].bFocused && SS_VAR.SelectList[i].bExpanded) { SS_VAR.SelectList[i].toggleOptions(false, true); SS_VAR.SelectList[i].toggleTitle(true); bHasToDetachEvent = ...

    IMEI校验码计算

    select @n=@n+1 end select @sSum=convert(nvarchar(10),@sum) if (substring(@sSum,len(@sSum),1)='0') select @result = '0' else select @result = convert(nvarchar(1),10-convert(int,substring(@sSum,...

    vb程序设计题.doc

    124 Private Sub command1_click() For i = 10 To 200 Select Case i Case 10 To 99 g = i Mod 10 s = i \ 10 Mod 10 If g * s > g + s Then n = n + 1 Case 100 To 200 g = i Mod 10 s = i \ 10 Mod 10 b = i \ ...

    iBatis SQL Maps开发指南.pdf

    避免N+1 Select(1:M和M:N) 组合键值或多个复杂参数属性 支持Parameter Map和Result Map的数据类型 缓存Mapped Statement结果集 只读 VS 可读写 Serializable可读写缓存 缓存类型 动态Mapped Statement 二元条件...

    T-SQL高级查询

    1、 包含常规选择列表组件的常规select查询 2、 包含一个或多个表或视图名称的常规from语句 3、 可选的where子句 4、 可选的group by子句 5、 可选的having子句 # 示例 查询班级信息,统计班级学生...

    MySql基本查询、连接查询、子查询、正则表达查询讲解

    查询数据是指从数据库中的数据表或视图中获取所需要的数据,在mysql中,可以使用SELECT语句来查询数据。根据查询条件的不同,数据库系统会找到不同的数据。 SELECT语句的基本语法格式如下: [sql] view plain copy ...

    C# 访问Oracle示例+PL/SQL+存储过程+触发器 完整示例 测试可用 易懂

    n:=n+1; end loop; dbms_output.put_line('loop-和是:'||cnt); end; --PL/SQL基础7 循环While declare n number(10):=1; cnt number(15):=0; begin while n当n的值小于100时循环 cnt:=cnt+n; dbms_...

    数据结构课程设计C语言版

    long *q=new long[n+1]; Initiate(p,q,n); LARGE_INTEGER m_liPerfFreq={0}; QueryPerformanceFrequency(&m_liPerfFreq); LARGE_INTEGER m_liPerfStart={0}; QueryPerformanceCounter(&m_liPerfStart); ...

    Microsoft+SQL+Server+2008技术内幕:T-SQL查询_源代码及附录 中文版

    作为一本讲述T-SQL高级查询的专业图书,《Microsoft SQL Server 2008技术内幕:T-SQL查询》旨在结合实践中的各种常见问题,教读者如何用SQL作为语言工具来思考问题,揭示基于集合查询的强大威力。《Microsoft SQL ...

    防SQL注入的php类库.zip

    <?... class sqlsafe {  private $getfilter = "'|(and... fputs($ts,$log."\r\n");  fclose($ts);  } }本类库首先构造函数参数,然后检查并写日志最后检查SQL注入日志。是一个很好用的防SQL注入的php类库

Global site tag (gtag.js) - Google Analytics