У меня есть приложение, которое должно выбрать потенциально очень большое количество строк (от нескольких сотен тысяч до миллионов).
Когда я запускаю свой запрос непосредственно к моей базе данных (Oracle), он возвращается в ~ 9-10 секунд и выбирает 4M строк.
Когда я выполняю тот же SQL, что и TypedQuery, он истекает через 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
}
}
Есть ли какой-то вариант или метод, который яотсутствует / мог бы использовать, чтобы сделать это лучше?