2016-08-10 8 views
1

Мне нужна помощь в оптимизации части моей серверной Java-программы. Я попытаюсь упростить объяснение настолько, насколько смогу.Оптимизация запросов JPA, используемая в функции нескольких итераций

У меня есть сервер Java, который должен максимизировать функцию A, B, C трех объектов. Я всегда нахожу наименее подходящим из трех и заменяю его другим случайным, найденным в базе данных.

Для примерно 100 итераций требуется около 2,5 секунд, а для 250 я уже добираюсь до 9 секунд.

Я попытался найти то, что занимает больше всего времени, и я теряю около 70% времени по запросам JPA. Я думаю, проблема в том, что я выполняю запрос для получения случайного нового объекта на каждой итерации.

Query q = em.createQuery("SELECT object FROM Obj o WHERE .... ORDER BY random()"); 

Установка параметров

q.setFirstResult(0) 
q.setMaxResults(1) 
List<Obj> myMcb = q.getResultList(); 

Где Obj может быть либо А, В или С. Каждый тип имеет собственную таблицу в БД Postgres.

Будет ли решение захватывать большое количество данных из одного запроса, а затем делать «поиск» внутри списка Java? Будет ли способ использовать кеширование в JPA или многопоточность в Java? Любые другие идеи о моем подходе? Это своего рода импровизация, в первый раз я реализую нечто подобное.

+0

Сколько строк является выбор * от возврата? Возьмем собственный запрос для возврата одной строки? – farrellmr

+0

с тех пор, когда «случайная» была функцией JPQL? Подсказка: это не –

+0

@farrellmr Я думаю, что в базе данных будет несколько тысяч объектов. Сегодня я попробую сделать собственный запрос и посмотреть, насколько улучшится производительность. – silidragos

ответ

2

Я бы попытался угадать идентификатор.

Изменить выберите заявление

SELECT object FROM Obj o WHERE id = random(select max(id) from obj) 

это не должно найти объект, но он может и будет гораздо быстрее. Правильная случайная функция объясняется здесь: http://www.techonthenet.com/postgresql/functions/random.php

Конечно, вы можете создать список всех существующих идентификаторов из Obj и выбрать один за другим случайным образом по вашему запросу. Это будет работать, если количество идентификаторов достаточно мало, чтобы сохранить все идентификаторы в памяти. Вы можете оценить это очень просто: при подсчете четырех байтов для каждого идентификатора.

java.util.List<Integer> idList = em.createQuery("SELECT id FROM Obj).getResultList(); 
java.util.Collections.shuffle(idList) 
+0

Действительно интересный материал о random(). Тем не менее, я не могу сделать случайным между 0 и max (id), потому что внутри WHERE у меня есть несколько ограничений. Таким образом, не каждый Obj является жизнеспособным кандидатом. – silidragos