Mybatis N+1问题

Mybatis是很流行的数据库中间件,对于一对多等复杂关系配置容易产生N+1的问题,下面我们来了解下。

关联嵌套查询


  





我们有两个查询语句:一个来加载博客,另外一个来加载作者,而且博客的结果映射描 述了“selectAuthor”语句应该被用来加载它的 author 属性。

其他所有的属性将会被自动加载,假设它们的列和属性名相匹配。

这种方式很简单, 但是对于大型数据集合和列表将不会表现很好。 问题就是我们熟知的N+1 查询问题。概括地讲,N+1查询问题可以是这样引起的:

  • 执行了一个单独的 SQL 语句来获取结果列表(就是“+1”)。
  • 对返回的每条记录,执行了一个查询语句来为每个加载子内容(就是“N”)。

这个问题会导致成百上千的 SQL 语句被执行。这通常不是期望的。

MyBatis 能延迟加载这样的查询就是一个好处,因此你可以分散这些语句同时运行的消耗。然而,如果你加载一个列表,之后迅速迭代来访问嵌套的数据,你会调用所有的延迟加 载,这样的行为可能是很糟糕的。

所以还有另外一种方法。

关联的嵌套结果

在上面你已经看到了一个非常复杂的嵌套关联的示例。 下面这个是一个非常简单的示例 来说明它如何工作。代替了执行一个分离的语句,我们联合博客表和作者表在一起,就像:


注意这个联合查询, 以及采取保护来确保所有结果被唯一而且清晰的名字来重命名。 这使得映射非常简单。现在我们可以映射这个结果:


  
  
  



  
  
  
  
  

在上面的示例中你可以看到博客的作者关联代表着“authorResult”结果映射来加载作 者实例。

非常重要: id元素在嵌套结果映射中扮演着非常重要的角色。你应该总是指定一个或多个可以唯一标识结果的属性。实际上如果你不指定它的话, MyBatis仍然可以工作,但是会有严重的性能问题。在可以唯一标识结果的情况下, 尽可能少的选择属性。主键是一个显而易见的选择(即使是复合主键)。

现在,上面的示例用了外部的结果映射元素来映射关联。这使得 Author 结果映射可以重用。然而,如果你不需要重用它的话,或者你仅仅引用你所有的结果映射合到一个单独描 述的结果映射中。你可以嵌套结果映射。这里给出使用这种方式的相同示例:


  
  
  
    
    
    
    
    
  

如果blog有一个co-author怎么办? select语句将看起来这个样子:


再次调用Author的resultMap将定义如下:


  
  
  
  
  

若结果中的列名与resultMap中的列名不同。 你需要指定columnPrefix去重用映射co-author结果的resultMap


  
  
  
  

上面你已经看到了如何处理“有一个”类型关联。但是“有很多个”是怎样的?
下面这 个部分就是来讨论这个主题的。

官方链接:http://www.mybatis.org/mybatis-3/zh/sqlmap-xml.html

大道,在太极之上而不为高;在六极之下而不为深;先天地而不为久;长于上古而不为老

你可能感兴趣的:(Mybatis N+1问题)