如何解决Java TypedQuery比直接查询DB要慢得多?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (1)
  • 关注 (0)
  • 查看 (288)

我有一个应用程序,需要选择一个可能非常大的行(数十万到数百万)

当我直接对我的数据库(Oracle)运行查询时,它返回~9-10s并选择4M行。

当我执行与TypedQuery相同的SQL时,会在5分钟后超时。

我已经尝试过分页,hibernate scrollableresults,设置查询只读,禁用缓存甚至尝试了nativeQuery,但似乎没有任何帮助。

示例代码如下:

StringBuffer sql = new StringBuffer();
sql.append("SELECT t from TestResult t WHERE t.endDatetime >= ");
sql.append(getDateSelector(timestampStart));
sql.append(" AND t.endDatetime <= ");
sql.append(getDateSelector(timestampEnd));
sql.append(" ORDER BY t.nodeId, t.endDatetime DESC");

TypedQuery<TestResult> query = entityManager.createQuery(sql.toString(), TestResult.class);

testResults = query.getResultList();

分页示例:

@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public List<TestResult> iterateAllTestResults(String startDateTime, String endDateTime)
{
    int offset = 0;
    List<TestResult> allTestResults = new ArrayList<>();

    List<TestResult> testResults;
    while ((testResults = this.getAllTestResultsIterableHelper(offset, 100, startDateTime, endDateTime)).size() > 0)
    {
        allTestResults.addAll(testResults);
        offset += testResults.size();
    }

    return allTestResults;
}

private List<TestResult> getAllTestResultsIterableHelper(int offset, int max, String startDateTime, String endDateTime)
{

    try
    {
        Timestamp timestampStart = DateTimeFormatter.convertFormattedDateToTimestamp(startDateTime);
        Timestamp timestampEnd = DateTimeFormatter.convertFormattedDateToTimestamp(endDateTime);

        StringBuffer sql = new StringBuffer();
        sql.append("SELECT t from TestResult t WHERE t.endDatetime >= ");
        sql.append(getDateSelector(timestampStart));
        sql.append(" AND t.endDatetime <= ");
        sql.append(getDateSelector(timestampEnd));
        sql.append(" ORDER BY t.nodeId, t.endDatetime DESC");

        List<TestResult> results = entityManager.().createQuery(sql.toString(), TestResult.class).setFirstResult(offset).setMaxResults(max).getResultList();

        return results;
    }
    catch (Exception e)
    {
        // omitted
    }
}

是否有一些选项或技术我缺少/可以用来做得更好?

提问于
用户回答回答于

这是因为在Java中你尝试获取所有4百万条记录,而在你的Oracle工作室中,作为预防措施,你在工作室中增加了限制(我假设只有50行左右?或者像mysql workbench中的1000行?)。如果您认为在9秒内通过排序获取4m行,那么我不会购买它。无论如何,无论出于何种原因,将4M读入应用程序都是相当糟糕的。您应该尝试将“analisys”移动到数据库中,或者重新考虑处理,这样您一次只能使用某些部分。这就是使用分页的原因。如果你想要获得所有行,那么你每次需要时都需要等待5分钟。

扫码关注云+社区

领取腾讯云代金券