Мне нужно, чтобы вы разбирались в узких местах / улучшениях производительности с помощью следующего кода.
У меня есть огромная коллекция (~ 2,5 миллиона объектов) INTEREST_RATES, чтобы многократно проходить и извлекать и возвращать списки подходящих записей. Мое текущее решение для этого - база данных памяти HSQL:
Структура таблицы INTEREST_RATE :
CREATE MEMORY TABLE INTEREST_RATES " +
"(EFFECTIVE_DATE DATE not NULL, "
+ "INTEREST_RATE DOUBLE not NULL, "
+ "INTEREST_RATE_CD INT not NULL, "
+ "INTEREST_RATE_TERM INT not NULL, "
+ "INTEREST_RATE_TERM_MULT VARCHAR(5) not NULL,"
+ "TERM_IN_DAYS DOUBLE not NULL,"
+ "PRIMARY KEY (EFFECTIVE_DATE, INTEREST_RATE_CD, INTEREST_RATE_TERM, INTEREST_RATE_TERM_MULT))"
CREATE INDEX dtidx ON INTEREST_RATES (EFFECTIVE_DATE, INTEREST_RATE_CD)
Запрос :
SELECT * from INTEREST_RATES where INTEREST_RATE_CD = ? and
EFFECTIVE_DATE = (SELECT MAX(EFFECTIVE_DATE) from INTEREST_RATES
where INTEREST_RATE_CD = ? AND EFFECTIVE_DATE <= ?)
-> Итак, я пытаюсь получить последние доступные ЦЕНЫ для определенного INTEREST_RATE_CD, давая верхний предел даты.
Java-часть для выполнения запроса :
PreparedStatement p = con.prepareStatement(sql);
p.setLong(1, intRateCd);
p.setLong(2, intRateCd);
p.setDate(3, someDate);
ResultSet r = p.executeQuery();
return resultSetToList(r);
Основной цикл Java с использованием Futures / многопоточности :
ExecutorService executor = Executors.newFixedThreadPool(4);
CompletionService<TestResult> completionService = new ExecutorCompletionService<>(executor);
long futureCount = 0;
while(deals.next()) //deals is a ScrollableResults set from Hibernate
{
IDealEntity deal = (IDealEntity) deals.get()[0];
//These tasks contain the INTEREST_RATE query action
QueryTask task = new QueryTask(some params...);
completionService.submit(task);
}
try
{
while(futureCount < dealCount)
{
Future<TestResult> result = completionService.take();
TestResult testResult = result.get();
futureCount++;
testResults.add(testResult);
}
executor.shutdown();
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
}
catch (Exception ex)
{
ex.printStackTrace();
}
Теперь, когда я пытаюсь улучшить производительность или найти ошибки в моем коде, мои вопросы будут такими:
Пока что HSQL был самым быстрым, что я мог придумать. Также попробовал H2, который был waaaaay медленнее.
Почти нет разницы, если я использую 1 размер ThreadPool или 4 потока ...
Любые советы, идеи или что-либо приветствуется!
Всего 2 ответа
Я не думаю, что в базе данных памяти хороший подход для ее решения. Самое главное, чтобы избежать полного сканирования таблицы. Мне кажется, что у вас есть правильные индексы. Было бы полезно увидеть реальные сроки, которые должны составлять миллисекунды.
Если этого недостаточно, вы можете загрузить всю структуру в память в виде вложенных индексированных коллекций или хеш-таблиц и использовать Java для непосредственного их обхода.
Я считаю, что когда мы имеем дело с очень большим объемом данных, то база данных в памяти может создать проблемы, так как она будет использовать очень большой объем памяти, если не использовать распределенную базу данных в памяти.
Другой альтернативой, если не использовать распределенную базу данных в памяти, может быть использование Cache с хорошо подходящими политиками вытеснения и т. Д.