hibernate之优化抓取(选择抓取策略之批量预抓取数据)

hibernate之优化抓取(选择抓取策略之批量预抓取数据)

Hibernate执行SQL SELECT语句把对象加载到内存。如果加载一个对象,那么就要执行单个或者几个SELECT,这取决于所涉及的表的数量,以及你所采用的抓取策略。
你的目标是把SQL语句的数量减到最少,简化SQL语句,以便尽可能地提高查询效率。你通过给每个集合或者关联应用最佳的抓取策略来做到这一点。默认情况下,每当访问被关联的对象和集合时,hibernate就延迟抓取它们。如例:
Item item = (Item)session.get(Item.class,new Long(123));
你没有配置任何关联或者集合为非延迟,也没有配置可以为所有关联生成的代理。因而,这项操作生成了下列SQLSELECT语句:
select item.* from ITEM item where item.ITEM_ID = ?
(注意,hibernate生成的真正SQL自动包含生成的别名;为了增加可读性,我们已经在接下来的所有示例中把它们移除了。)你会看到SELECT只查询ITEM表,并获取一个特定的行。所有实体关联和集合都没有被获取。如果你访问任何被代理的关联或者未被初始化的集合,就会执行第二个SELECT以便按需获取数据。
第一个优化步骤是,减少利用默认的延迟行为时定会看到的额外按需SELECT的数量--例如,通过预抓取数据。
----------
批量预抓取数据
如果每一个实体关联和集合都仅仅按需抓取,完成一个特定的过程可能就需要许多额外的SQL SELECT语句了。例如,考虑下列获取所有Item对象的查询,并访问每件货品seller(User类的对象)的数据(这个例子是前面使用过的):
 
一般来说,你在这里应该用一个循环,并遍历结果,但这段代码所公开的问题是一样的。你看到1个SQL SELECT获取所有的Item对象,并且你一处理Item的每一个seller时立即就有另一个SELECT。所有被关联的User对象都代理。这是我们将要深入阐述的最糟糕的案例场景之一:n+1查询问题。SQL看起来像这样:
 
hibernate提供了一些算法,可以预抓取User对象。我们现在讨论的第一个优化称作批量抓取,它像这样进行:如果User的1个代理必须被初始化,就在相同的SELECT中初始化几个代理。换句话说,如果你已经知道持久化上下文中有3个Item实例,并且它们已经把一个代理应用到了它们的seller关联,那么你可以也初始化所有代理而不只是1个。
批量抓取经常被称作瞎猜优化,因为你不知道在一个特定的持久化上下文中,有多少个未被初始化的User代理。在前一个例子中,这个数量取决于返回的Item对象的数量。你猜测并把批量大小抓取策略应用到User类映射:
 
你在告诉hibernate:如果必须初始化1个代理,就在单个SQL SELECT中最多预抓取10个未被初始化的代理。之前的查询和过程所产生的SQL现在看起来可能像这样:
 
获取所有Item对象的第一个语句在你list()查询的时候执行。下一个语句(获取3个User对象)在你一初始化由allItems.get(o).getSeller()返回的第一个代理时,就会被触发。这个查询同时加载3个卖主---因为这就是初始查询要返回的项目数量,以及当前的持久化上下文中未被初始化的代理数量。你定义了批量大小为"最多10个"。如果返回的货品超过10个,你就会看到第二个查询如何在一批中获取10个卖主。如果应用程序命中另一个尚未被初始化的代理,就会获取到另一批的10个,等等,直到持久化上下文中再也没有未被初始化的代理。
批量抓取也可用于集合:
 
如果现在强制初始化1个bids集合,则立即加载相同类型的集合最多10个(如果它们在当前的持久化上下文中没有被初始化):
 
在这个例子中,你再一次拥有了3个处于持久化状态的Item对象,并且接触到了其中一个未被加载的bids集合。现在所有3个Item对象都让它们的bids在单个SELECT中加载。
通过批量策略预抓取代理和集合真的是一种瞎猜。正是这种聪明的优化可以显著地减少(对于初始化所使用的所有对象是必需的)SQL语句的数量。当然,预抓取的唯一缺点是,可能预抓取了最终不需要的数据。用更少的SQL语句的代价可能是更高的内存消耗。后者经常更为重要:内存很便宜,但是可伸缩的数据库服务器则不便宜。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值