休眠条件查询需要时间从数据库表中获取记录

时间:2019-01-04 12:34:21

标签: hibernate hibernate-mapping criteria hibernate-criteria

在我的项目中,我将10000条记录插入表中。如果有任何记录,我们将使用休眠条件来获取它,并将其与新记录进行比较。表中的数据很少,大约有10000条记录。对于休眠标准,我们已经应用了条件。这个休眠标准是从表中获取6条记录。但是为什么我调用criteria.list()方法来获取6条记录会花费时间

休眠标准查询:

select this_.CLASS_TYPE as CLASS1_15_0_, this_.CLASS_UNIT_TYPE as CLASS2_15_0_, this_.CLASS_UNIT_CODE as CLASS3_15_0_, 
this_.ID as ID15_0_, this_.LANG_CODE_ISO as LANG5_15_0_, this_.CTY_CODE_ISO as CTY6_15_0_, this_.NAME as NAME15_0_, this_.INS_DTIME as INS8_15_0_,this_.UPD_DTIME as UPD9_15_0_, this_.DEL_DTIME as DEL10_15_0_ from FI_SALES_LOCATION_V this_ where (this_.CLASS_TYPE='BU' and this_.CLASS_UNIT_TYPE='STO' and this_.CLASS_UNIT_CODE='A1000') and this_.DEL_DTIME is null and ((this_.LANG_CODE_ISO='en' and this_.CTY_CODE_ISO='GB' and this_.ID='A1000') or (this_.LANG_CODE_ISO='en' and this_.CTY_CODE_ISO='GB' and this_.ID='AP1000') or (this_.LANG_CODE_ISO='pt' and this_.CTY_CODE_ISO='PT' and this_.ID='AP1000') or (this_.LANG_CODE_ISO='pt' and this_.CTY_CODE_ISO='PT' and this_.ID='A1000') or (this_.LANG_CODE_ISO='s1' and this_.CTY_CODE_ISO='SI' and this_.ID='AP1000') or (this_.LANG_CODE_ISO='s1' and this_.CTY_CODE_ISO='SI' and this_.ID='A1000'));

2 个答案:

答案 0 :(得分:0)

尝试以这种方式编写查询:

select this_.CLASS_TYPE as CLASS1_15_0_, this_.CLASS_UNIT_TYPE as CLASS2_15_0_, this_.CLASS_UNIT_CODE as CLASS3_15_0_, 
this_.ID as ID15_0_, this_.LANG_CODE_ISO as LANG5_15_0_, this_.CTY_CODE_ISO as CTY6_15_0_, this_.NAME as NAME15_0_, this_.INS_DTIME as INS8_15_0_,this_.UPD_DTIME as UPD9_15_0_, this_.DEL_DTIME as DEL10_15_0_ 
from FI_SALES_LOCATION_V this_ 
where 
(this_.CLASS_TYPE='BU' and this_.CLASS_UNIT_TYPE='STO' and this_.CLASS_UNIT_CODE='A1000') 
and this_.DEL_DTIME is null 
and (this_.LANG_CODE_ISO='en' and this_.CTY_CODE_ISO='GB' and this_.ID='A1000') 
UNION ALL
select this_.CLASS_TYPE as CLASS1_15_0_, this_.CLASS_UNIT_TYPE as CLASS2_15_0_, this_.CLASS_UNIT_CODE as CLASS3_15_0_, 
this_.ID as ID15_0_, this_.LANG_CODE_ISO as LANG5_15_0_, this_.CTY_CODE_ISO as CTY6_15_0_, this_.NAME as NAME15_0_, this_.INS_DTIME as INS8_15_0_,this_.UPD_DTIME as UPD9_15_0_, this_.DEL_DTIME as DEL10_15_0_ 
from FI_SALES_LOCATION_V this_ 
where 
(this_.CLASS_TYPE='BU' and this_.CLASS_UNIT_TYPE='STO' and this_.CLASS_UNIT_CODE='A1000') 
and this_.DEL_DTIME is null 
and (this_.LANG_CODE_ISO='en' and this_.CTY_CODE_ISO='GB' and this_.ID='AP1000') 
UNION ALL
select this_.CLASS_TYPE as CLASS1_15_0_, this_.CLASS_UNIT_TYPE as CLASS2_15_0_, this_.CLASS_UNIT_CODE as CLASS3_15_0_, 
this_.ID as ID15_0_, this_.LANG_CODE_ISO as LANG5_15_0_, this_.CTY_CODE_ISO as CTY6_15_0_, this_.NAME as NAME15_0_, this_.INS_DTIME as INS8_15_0_,this_.UPD_DTIME as UPD9_15_0_, this_.DEL_DTIME as DEL10_15_0_ 
from FI_SALES_LOCATION_V this_ 
where 
(this_.CLASS_TYPE='BU' and this_.CLASS_UNIT_TYPE='STO' and this_.CLASS_UNIT_CODE='A1000') 
and this_.DEL_DTIME is null 
and (this_.LANG_CODE_ISO='pt' and this_.CTY_CODE_ISO='PT' and this_.ID='AP1000') 
UNION ALL
select this_.CLASS_TYPE as CLASS1_15_0_, this_.CLASS_UNIT_TYPE as CLASS2_15_0_, this_.CLASS_UNIT_CODE as CLASS3_15_0_, 
this_.ID as ID15_0_, this_.LANG_CODE_ISO as LANG5_15_0_, this_.CTY_CODE_ISO as CTY6_15_0_, this_.NAME as NAME15_0_, this_.INS_DTIME as INS8_15_0_,this_.UPD_DTIME as UPD9_15_0_, this_.DEL_DTIME as DEL10_15_0_ 
from FI_SALES_LOCATION_V this_ 
where 
(this_.CLASS_TYPE='BU' and this_.CLASS_UNIT_TYPE='STO' and this_.CLASS_UNIT_CODE='A1000') 
and this_.DEL_DTIME is null 
and (this_.LANG_CODE_ISO='pt' and this_.CTY_CODE_ISO='PT' and this_.ID='A1000') 
UNION  ALL
select this_.CLASS_TYPE as CLASS1_15_0_, this_.CLASS_UNIT_TYPE as CLASS2_15_0_, this_.CLASS_UNIT_CODE as CLASS3_15_0_, 
this_.ID as ID15_0_, this_.LANG_CODE_ISO as LANG5_15_0_, this_.CTY_CODE_ISO as CTY6_15_0_, this_.NAME as NAME15_0_, this_.INS_DTIME as INS8_15_0_,this_.UPD_DTIME as UPD9_15_0_, this_.DEL_DTIME as DEL10_15_0_ 
from FI_SALES_LOCATION_V this_ 
where 
(this_.CLASS_TYPE='BU' and this_.CLASS_UNIT_TYPE='STO' and this_.CLASS_UNIT_CODE='A1000') 
and this_.DEL_DTIME is null 
and (this_.LANG_CODE_ISO='s1' and this_.CTY_CODE_ISO='SI' and this_.ID='AP1000') 
UNION ALL
select this_.CLASS_TYPE as CLASS1_15_0_, this_.CLASS_UNIT_TYPE as CLASS2_15_0_, this_.CLASS_UNIT_CODE as CLASS3_15_0_, 
this_.ID as ID15_0_, this_.LANG_CODE_ISO as LANG5_15_0_, this_.CTY_CODE_ISO as CTY6_15_0_, this_.NAME as NAME15_0_, this_.INS_DTIME as INS8_15_0_,this_.UPD_DTIME as UPD9_15_0_, this_.DEL_DTIME as DEL10_15_0_ 
from FI_SALES_LOCATION_V this_ 
where 
(this_.CLASS_TYPE='BU' and this_.CLASS_UNIT_TYPE='STO' and this_.CLASS_UNIT_CODE='A1000') 
and this_.DEL_DTIME is null 
and (this_.LANG_CODE_ISO='s1' and this_.CTY_CODE_ISO='SI' and this_.ID='A1000');

即使编写更多内容,执行UNION ALL而不是OR也会提高性能。

或者您可以为表建立索引,但是会降低INSERT的性能。

答案 1 :(得分:0)

考虑问题和评论中的信息,这就是代码的作用:

  • 对于每个要插入的记录,您都可以通过条件进行选择。
  • 进行检查,然后根据情况保留或合并记录。

您必须了解休眠会话在某些情况下的行为。当您在休眠状态下执行操作时,您正在做的事情(在第一时间)是在更新休眠会话。无论是插入,删除还是更新,该操作都将在会话中执行,Hibernate甚至会记录一条SQL语句,但是它不会立即刷新到您的数据库中(是的,这具有误导性)。

通常情况下,所有内容都将被刷新并结束事务,但是在某些情况下,休眠将刷新操作以使会话保持最新状态。在您的情况下,您有多个记录要插入/合并,但是在执行每个操作之前,您都要执行选择。 Hibernate会检测到该操作,并将刷新每个先前存储的操作,这仅仅是因为查询数据库是否有待刷新的未决操作是没有意义的。数据库需要处于可能的最新状态。不要试图与之抗争,它是按照这种方式工作的。

所以我最好的猜测是,当您的选择花费太多时间执行时,这是因为休眠状态刷新了先前的插入/更新操作

解决方法:

我想不出任何简单的方法来解决这个问题。您将不得不重新考虑您的方法。

有一件事很重要:即使您只需要纯插入而没有任何验证,您也会遇到一些麻烦,因为您的代码正在尝试插入数千条记录。这样做的最大问题是,就像我之前写的那样,休眠状态直到事务结束才刷新操作。因此,它将把每个要执行的语句保存在内存中。您很有可能会耗尽内存。

我要做的第一件事是检查批处理中的休眠文档(从docs开始)。之后,我将找出一种策略来优化插入大量记录和验证所需的需求。 不用处理单个记录,而可以处理数据块。

从可用的少量信息中,我将尝试以下工作流程:

在进行所有操作之前,请定义休眠的批处理大小属性(同样,请查看有关批处理的文档)

  • 在处理数据时,请使用与批量大小定义的大小相同的数据切片
  • 进行选择,在要插入的那些记录中选择所有可能要验证的记录
  • 执行所需的验证,以检查切片中的每个记录是合并还是插入
  • 组插入并合并并执行操作。刷新并清除休眠会话
  • 获取下一个数据片段,然后重复该过程

基本上,这是您正在执行的“相同”过程,但是它将对大块记录执行,而不是在每条记录中都执行。

相关问题