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

当我直接对我的数据库(Oracle)运行查询时,它会在大约9-10秒内返回并选择4M行。

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

我试过分页,休眠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中,您尝试在Oracle Studio中获取全部4百万条记录时,为预防起见,Studio增加了限制(我假设只有50行左右,或者像在MySQL Workbench中那样可能有1000行)。如果您认为要在9秒钟内通过排序获取400万行,那么我就不买它。

无论如何,无论出于何种原因将4M引入应用程序都是很糟糕的选择。您应该尝试将“分析”移至数据库,或者重新考虑处理过程,以便一次只使用所有结果的一部分。这就是分页的用途。如果您想获得所有行,那么每次需要时您都必须等待5分钟。

10-06 07:21
查看更多