Sql 理解ORM的嵌套选择

Sql 理解ORM的嵌套选择,sql,join,orm,sql-subselect,Sql,Join,Orm,Sql Subselect,我正在阅读解释嵌套循环连接算法的文章,但我并不完全理解嵌套选择的实际工作原理。以下是本文提供的一个示例: 示例搜索姓氏以“WIN”开头的员工 并为这些员工获取所有销售额 表示嵌套循环联接的查询如下所示: select employees0_.subsidiary_id as subsidiary1_0_ -- MORE COLUMNS from employees employees0_ where upper(employees0_.last_name) like ?; se

我正在阅读解释嵌套循环连接算法的文章,但我并不完全理解嵌套选择的实际工作原理。以下是本文提供的一个示例:

示例搜索姓氏以“WIN”开头的员工 并为这些员工获取所有销售额

表示嵌套循环联接的查询如下所示:

select employees0_.subsidiary_id as subsidiary1_0_
       -- MORE COLUMNS
from employees employees0_ 
where upper(employees0_.last_name) like ?;

select sales0_.subsidiary_id as subsidiary4_0_1_
         -- MORE COLUMNS
from sales sales0_
where sales0_.subsidiary_id=? 
  and sales0_.employee_id=?;

select sales0_.subsidiary_id as subsidiary4_0_1_
         -- MORE COLUMNS
from sales sales0_
where sales0_.subsidiary_id=? 
  and sales0_.employee_id=?;

如您所见,最后两个查询完全相同。这就是我所困惑的。为什么仅仅生成前两个查询还不够?为什么我们必须生成第三个呢?

请记住,您粘贴的代码是引用的文章示例,说明了不应执行的操作–反模式


也就是说,查询是参数化的,因此实际上并不完全相同。两个首字母?每个查询中的字符都是参数,在for循环的每次迭代中,这些参数都将被子对象id的不同值替换。

无需生成第三个查询。如果手动编写SQL查询,则可以将检索到的所有员工的所有销售作为单个查询加载。但当程序代码如本文所示时,就会出现N+1查询反模式:

雇员e:emp{ //流程员工 对于销售,s:e.getSales{ //为员工处理销售 } } 在该代码中,e.getSales方法为一名员工加载数据。此方法没有足够的信息来加载所有其他员工的销售数据,因为ORM没有需要加载销售数据的完整员工列表。因此,ORM被迫在单独的查询中加载每个员工的销售数据

一些ORM可以自动避免N+1查询问题。例如,以Python编写,本文中的代码如下所示:

第一个查询加载所有必需的员工 employees=如果e.lastName.startswith'WIN' 对于e-in员工: 流程员工 在e.sales中出售: 为员工处理销售 当程序启动循环覆盖员工查询时,PonyORM会立即加载所有必要的员工。当请求第一名员工的销售项目时,PonyORM仅为该员工加载该项目,因为ORM不知道我们的意图,并假设我们可能只需要第一名员工的销售数据。但是,当请求第二个员工的销售数据时,PonyORM注意到N+1查询反模式,看到内存中加载了N个员工对象,并在单个查询中加载所有剩余员工的销售。这种行为可以看作是一种启发。如果for循环包含break操作,它可能会加载一些额外的sales对象。但是这种启发式通常会带来更好的性能,因为它可以大大减少查询的数量。通常情况下,加载一些额外数据不是问题,更重要的是减少到服务器的往返次数。

您是否自己尝试过Hibernate JPA 3.6.0来创建查询?看起来像是复制/粘贴打字错误。