Java TypedQuery намного медленнее, чем прямые запросы к БД - PullRequest
0 голосов
/ 23 сентября 2018

У меня есть приложение, которое должно выбрать потенциально очень большое количество строк (от нескольких сотен тысяч до миллионов).

Когда я запускаю свой запрос непосредственно к моей базе данных (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
    }
}

Есть ли какой-то вариант или метод, который яотсутствует / мог бы использовать, чтобы сделать это лучше?

1 Ответ

0 голосов
/ 23 сентября 2018

Это потому, что в Java вы пытаетесь получить все 4 миллиона записей, в то время как в вашей студии Oracle у вас есть ограничение, добавляемое студией в качестве меры предосторожности (только 50 строк или около того, как я предполагаю? Или, может быть, 1000, как в MySQL Workbench?).Если вы думаете, что вы сортируете 4 млн строк за 9 секунд с сортировкой, то я не покупаю их.

В любом случае, загрузка 4M в приложение - это плохой идеал по любой причине.Вы должны попытаться перенести свой «анализ» в базу данных или переосмыслить обработку, чтобы использовать только часть результатов сразу.Вот для чего используется нумерация страниц.Если вы хотите получить все строки, вам придется ждать 5 минут каждый раз, когда вам это нужно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...