Доброго времени суток. В моем приложении каждую минуту происходит сканирование игровых серверов, с последующим занесением результатов в базу данных. Столкнулся с серьезной проблемой производительности. Занесение результатов в БД (около 2000 записей) занимает ~30 секунд.
Есть следующий код:
@Service
public class ServerScannerImpl implements ServerScanner
{
@Transactional
public void process()
{
...
... // Здесь код сканирования, далее занесение результата в БД
handleResult();
}
private void handleResult()
{
fillServerInfo(server, info); // Для каждого сервера (примерно 2000) вызывается этот метод
}
private void fillServerInfo(Server server, ServerInfo info)
{
...
...
Map map = mapService.getMapByHttpName(mapHttpName, game.getId());
if (map == null)
{
map = new Map();
map.setName(info.getMap());
map.setGame(game);
map.setHttpName(mapHttpName);
mapService.addMap(map);
}
server.setMap(map);
...
...
serverService.addSever(server);
}
@Autowired
private ServerService serverService;
@Autowired
private MapService mapService;
}
С помощью профайлера выяснил, что 80% времени выполнения приходится на этот метод:
Map map = mapService.getMapByHttpName(mapHttpName, game.getId());
@Service
@Transactional(readOnly = true)
public class MapServiceImpl implements MapService
{
public Map getMapById(Integer id)
{
return mapDAO.getMapById(id);
}
public Map getMapByHttpName(String httpName, Integer gameId)
{
return mapDAO.getMapByHttpName(httpName, gameId);
}
@Transactional(readOnly = false)
public void addMap(Map map)
{
mapDAO.addMap(map);
}
public List<Map> getAllMaps()
{
return mapDAO.getAllMaps();
}
@Transactional(readOnly = false)
public void removeMap(Map map)
{
mapDAO.removeMap(map);
}
@Autowired
private MapDAO mapDAO;
}
По call tree видно, что каждый раз, перед выполнением запроса к базе, происходит dirty checking:
org.hibernate.internal.SessionImpl.autoFlushIfRequired(Set)
А поскольку метод mapService.getMapByHttpName(mapHttpName, game.getId()) вызывается ~2000 раз, то львиная доля времени уходит на dirty checking.
Добавил в MapServiceImpl readOnly = true к аннотации @Transactional, но на ситуацию это не повлияло. Я новичек в этой области, поэтому не представляю как решить эту проблему. Спасибо за помощь.