Java 这种休眠方法效率很低吗?
这个函数是我正在编写的Hibernate程序的一部分,用于为大学金融系统执行一些后端批量处理。当程序执行时,它会被调用数十万次,而这些调用是程序中最大的单个时间接收器。就目前而言,我想不出一个合理的方法来减少对它的称呼 此函数将会计年度支付期间fypper和该期间的一周作为参数,并返回一个存储支付期间周所在的年度、学期和期限的构造AidYearTermJava 这种休眠方法效率很低吗?,java,sql,oracle,performance,hibernate,Java,Sql,Oracle,Performance,Hibernate,这个函数是我正在编写的Hibernate程序的一部分,用于为大学金融系统执行一些后端批量处理。当程序执行时,它会被调用数十万次,而这些调用是程序中最大的单个时间接收器。就目前而言,我想不出一个合理的方法来减少对它的称呼 此函数将会计年度支付期间fypper和该期间的一周作为参数,并返回一个存储支付期间周所在的年度、学期和期限的构造AidYearTerm public AidYearTerm FypperTermInfo (String fypper, String week) { s
public AidYearTerm FypperTermInfo (String fypper, String week) {
sfa_fws_calendar aidYear = new sfa_fws_calendar();
TypedQuery<sfa_fws_calendar> query = manager.createQuery("FROM sfa_fws_calendar cal "
+ "WHERE cal.id.fypper = ?1 AND cal.id.week_num = ?2",sfa_fws_calendar.class);
query.setParameter(1, fypper);
query.setParameter(2, week);
List<sfa_fws_calendar> aidYearList = query.getResultList();
if(!aidYearList.isEmpty()) {
aidYear = query.getSingleResult();
}
else {
aidYear.setFWS_AID_YR("9999");
aidYear.setSEM("NOTSET");
aidYear.setTERM("NOTSET");
ErrorOut("Could not find term info for "+fypper);
}
DebugOut("found aid year "+aidYear.getFWS_AID_YR()+", term "+aidYear.getTERM());
AidYearTerm aidYearTerm = new AidYearTerm(aidYear.getFWS_AID_YR(),aidYear.getTERM(),aidYear.getSEM());
return aidYearTerm;
}
我可以做些什么来简化/加快这个过程吗?最简单、最明显的优化方法是:
static final TypedQuery<sfa_fws_calendar> query = manager.createQuery("FROM sfa_fws_calendar cal "
+ "WHERE cal.id.fypper = ?1 AND cal.id.week_num = ?2", sfa_fws_calendar.class);
public AidYearTerm FypperTermInfo(String fypper, String week) {
//...
query.setParameter(1, fypper);
query.setParameter(2, week);
List<sfa_fws_calendar> aidYearList = query.getResultList();
不确定调用createQuery的开销,但这肯定只会发生一次
之后,如果所有的东西都是爬行的,这很可能你可以考虑某种形式的高速缓存,但如果有少量的FPPER周组合,这将是有效的。
List<sfa_fws_calendar> aidYearList = query.getResultList();
if(!aidYearList.isEmpty()) {
aidYear = query.getSingleResult(); // <========= DON'T!!!!!
}
编辑:
假设您没有按年度和周键入数百万条记录,那么似乎可以将sfa_fws_日历中的所有必需数据只读取一次到内存中,例如读取到地图中,从而避免数千次往返数据库
请注意,因为fypper和week实际上形成了一个字符串复合键,所以可以构建一个单独的映射,其中键可以是,例如,year+\uwek。然后,您的FyperTerminfo字符串Fyper,字符串week将只返回aidYearCacheMap.getfypper+uuzweek;瞧:这看起来是一个非常简单的选择,所以我认为这可能更像是一个确保Oracle高效运行的问题,特别是因为它每天运行数千次。对于这个查询,您看到了什么样的解释计划?有完整的表格扫描吗?您可能需要为sfa_fws_日历表编制索引,或者如果已有索引,请更改相应的索引并重新计算索引统计信息 例如,类似这样的内容可能有助于更新名为index_name的现有索引: 改变索引名称,重建计算统计;
被调用数十万次-一个数据库查询,执行数十万次?如果除了大幅减少这一数字外,没有什么需要改进的,也不会感到惊讶。顺便问一下,您的数据库中有多少年和周的组合如果不是数百万(我想不是),那么读取它们一次应该很容易,例如将它们存储在HashMap中,然后对缓存的数据进行操作。大约有11000个组合。在将它们存储在hashmap中并引用它而不是重新查询之后,一个过去需要两个小时的过程现在需要大约十五分钟。非常感谢。很高兴听到这个消息。我将在我的答案中添加方法。。。
List<sfa_fws_calendar> aidYearList = query.getResultList();
if(!aidYearList.isEmpty()) {
aidYear = aidYearList.get(0);
}