[英]Is this Hibernate method very inefficient?
This function is a piece of a Hibernate program I am writing to do some back-end bulk processing for a university financial system. 这个函数是我写的一个Hibernate程序的一部分,用于为大学金融系统做一些后端批量处理。 It gets called several hundred thousand times when the program executes, and these calls are the single biggest time-sink in the program.
程序执行时会调用数十万次,这些调用是程序中单个最大的时间接收器。 For the moment I cannot think of a plausible way to call it less often.
目前我想不出一种似乎不太常用的称呼方式。
This function takes a fiscal year pay period ("fypper") and a week in that period as arguments, and returns a construct ("AidYearTerm") that stores the year, semester, and term that the pay period week falls in. 此函数将会计年度支付期(“fypper”)和该期间的一周作为参数,并返回一个构造(“AidYearTerm”),用于存储支付期间周的年份,学期和期限。
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;
}
Is there something I can do to make this simpler/faster? 我能做些什么来使这更简单/更快?
The simplest and most obvious optimisation would be something like: 最简单和最明显的优化是:
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();
Not sure of the overhead of calling createQuery
but this would certainly only get that to happen once. 不确定调用
createQuery
的开销,但这肯定只会发生一次。
After that - if everything still runs at a crawl (and this is likely) you could consider some form of cacheing (perhaps ehcache ) but that would only be effective if there were a comparatively small number of fypper|week
combinations. 在那之后 - 如果一切仍然在爬行(这很可能),你可以考虑某种形式的缓存(也许是ehcache ),但只有在相对较少的
fypper|week
组合时才会有效。
At a first glance: 乍一看:
List<sfa_fws_calendar> aidYearList = query.getResultList();
if(!aidYearList.isEmpty()) {
aidYear = query.getSingleResult(); // <========= DON'T!!!!!
}
Query.getSingleResult()
runs the same query again! Query.getSingleResult()
再次运行相同的查询!
Use: 采用:
List<sfa_fws_calendar> aidYearList = query.getResultList();
if(!aidYearList.isEmpty()) {
aidYear = aidYearList.get(0);
}
Edit: 编辑:
Assuming you don't have millions of records keyed by year and week, it seems feasible to read all required data from sfa_fws_calendar
into memory only once, for example into a Map
, to subsequently avoid thousands of round trips to the DB. 假设您没有按年和周计算数百万条记录,似乎可以将所有必需的数据从
sfa_fws_calendar
入内存一次,例如读取到Map
,以便随后避免数千次往返数据库。
Note that, because fypper
and week
actually form a (string) composite key, you could build a single Map<String, AidYearTerm>
, where the keys could be, for example, year + "_" + week
. 请注意,因为
fypper
和week
实际上形成了一个(字符串)复合键,所以您可以构建一个Map<String, AidYearTerm>
,其中键可以是,例如, year + "_" + week
。 Then your FypperTermInfo (String fypper, String week)
would just return aidYearCacheMap.get(fypper + "_" + week);
那么你的
FypperTermInfo (String fypper, String week)
就会return aidYearCacheMap.get(fypper + "_" + week);
and voilà :) 和瞧瞧:)
That looks like a pretty straightforward select, so I think this may be more of an issue around making sure Oracle runs it efficiently (especially since it's run many thousands of times per day). 这看起来非常简单,所以我认为这可能是确保Oracle有效运行它的一个问题(特别是因为它每天运行数千次)。 What kind of explain plan do you see for this query?
你对这个查询有什么样的解释计划? Are there any full table scans?
有没有全表扫描? You may need to index sfa_fws_calendar table, or if there are already indices in place, alter the appropriate index and recompute the index statistics.
您可能需要索引sfa_fws_calendar表,或者如果已经存在索引,则更改相应的索引并重新计算索引统计信息。
For example, something like this might help update an existing index called index_name: 例如,像这样的东西可能有助于更新名为index_name的现有索引:
ALTER INDEX index_name REBUILD COMPUTE STATISTICS;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.