简体   繁体   English

这种Hibernate方法效率很低吗?

[英]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 . 请注意,因为fypperweek实际上形成了一个(字符串)复合键,所以您可以构建一个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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM