Improve database performance by executing queries in batch

This commit is contained in:
Keir Nellyer 2016-06-23 00:57:41 +01:00
parent 09a74e3772
commit 352ecc6ad6
2 changed files with 97 additions and 59 deletions

View File

@ -67,56 +67,20 @@ public class SnapshotRepository extends MinecraftRepository
}
public CompletableFuture<Void> insertSnapshots(int reportId, Collection<Snapshot> snapshots)
{
return CompletableFuture.<Void>allOf(snapshots.stream()
.map(snapshot -> insertSnapshot(reportId, snapshot))
.toArray(CompletableFuture[]::new));
}
public CompletableFuture<Void> insertSnapshot(int reportId, Snapshot snapshot)
{
return CompletableFuture.supplyAsync(() ->
{
try (Connection connection = DBPool.getAccount().getConnection())
{
long messageId = snapshot.getId().orElse((long) -1);
PreparedStatement insertSnapshotStatement = connection.prepareStatement(INSERT_SNAPSHOT, Statement.RETURN_GENERATED_KEYS);
if (messageId == -1)
for (Snapshot snapshot : snapshots)
{
PreparedStatement insertSnapshotStatement = connection.prepareStatement(INSERT_SNAPSHOT, Statement.RETURN_GENERATED_KEYS);
insertSnapshotStatement.setInt(1, snapshot.getSenderId());
insertSnapshotStatement.setString(2, _serverName);
insertSnapshotStatement.setTimestamp(3, new Timestamp(snapshot.getSentTime().atZone(ZONE_ID).toInstant().toEpochMilli()));
insertSnapshotStatement.setString(4, snapshot.getMessage());
insertSnapshotStatement.setInt(5, snapshot.getType().getId());
insertSnapshotStatement.executeUpdate();
ResultSet resultSet = insertSnapshotStatement.getGeneratedKeys();
if (resultSet.next())
{
messageId = resultSet.getLong(1);
snapshot._id = messageId;
}
else
{
throw new IllegalStateException("Query did not return a message id (we need one).");
}
insertSnapshotStatement.close();
for (int recipientId : snapshot.getRecipientIds())
{
PreparedStatement insertRecipientStatement = connection.prepareStatement(INSERT_SNAPSHOT_RECIPIENT);
insertRecipientStatement.setLong(1, messageId);
insertRecipientStatement.setInt(2, recipientId);
insertRecipientStatement.execute();
}
insertSnapshot(connection, insertSnapshotStatement, reportId, snapshot);
}
PreparedStatement reportSnapshotMapping = connection.prepareStatement(INSERT_REPORT_SNAPSHOT_MAPPING);
reportSnapshotMapping.setInt(1, reportId);
reportSnapshotMapping.setLong(2, messageId);
reportSnapshotMapping.execute();
insertSnapshotStatement.executeBatch();
}
catch (SQLException e)
{
@ -126,4 +90,73 @@ public class SnapshotRepository extends MinecraftRepository
return null;
});
}
public CompletableFuture<Void> insertSnapshot(int reportId, Snapshot snapshot)
{
return CompletableFuture.supplyAsync(() ->
{
try (Connection connection = DBPool.getAccount().getConnection())
{
PreparedStatement insertSnapshotStatement = connection.prepareStatement(INSERT_SNAPSHOT, Statement.RETURN_GENERATED_KEYS);
insertSnapshot(connection, insertSnapshotStatement, reportId, snapshot);
insertSnapshotStatement.executeBatch();
}
catch (SQLException e)
{
throw new RuntimeException(e);
}
return null;
});
}
// this allows snapshots to be inserted in batch
private void insertSnapshot(Connection connection, PreparedStatement insertSnapshotStatement, int reportId, Snapshot snapshot) throws SQLException
{
long messageId = snapshot.getId().orElse((long) -1);
if (messageId == -1)
{
insertSnapshotStatement.setInt(1, snapshot.getSenderId());
insertSnapshotStatement.setString(2, _serverName);
insertSnapshotStatement.setTimestamp(3, new Timestamp(snapshot.getSentTime().atZone(ZONE_ID).toInstant().toEpochMilli()));
insertSnapshotStatement.setString(4, snapshot.getMessage());
insertSnapshotStatement.setInt(5, snapshot.getType().getId());
insertSnapshotStatement.addBatch();
ResultSet resultSet = insertSnapshotStatement.getGeneratedKeys();
if (resultSet.next())
{
messageId = resultSet.getLong(1);
snapshot._id = messageId;
}
else
{
throw new IllegalStateException("Query did not return a message id (we need one).");
}
insertSnapshotStatement.close();
PreparedStatement insertRecipientStatement = connection.prepareStatement(INSERT_SNAPSHOT_RECIPIENT);
for (int recipientId : snapshot.getRecipientIds())
{
insertRecipientStatement.setLong(1, messageId);
insertRecipientStatement.setInt(2, recipientId);
insertRecipientStatement.addBatch();
}
insertRecipientStatement.executeBatch();
}
insertReportSnapshotMapping(connection, reportId, messageId);
}
private void insertReportSnapshotMapping(Connection connection, int reportId, long messageId) throws SQLException
{
PreparedStatement reportSnapshotMapping = connection.prepareStatement(INSERT_REPORT_SNAPSHOT_MAPPING);
reportSnapshotMapping.setInt(1, reportId);
reportSnapshotMapping.setLong(2, messageId);
reportSnapshotMapping.execute();
}
}

View File

@ -357,39 +357,44 @@ public class ReportRepository extends MinecraftRepository
if (idOptional.isPresent())
{
PreparedStatement setReportMessageStatement = connection.prepareStatement(SET_REPORT_MESSAGE);
PreparedStatement setReportHandlerStatement = connection.prepareStatement(SET_REPORT_HANDLER);
PreparedStatement setReportResultStatement = connection.prepareStatement(SET_REPORT_RESULT);
for (Map.Entry<Integer, ReportMessage> entry : report.getMessages().entrySet())
{
ReportMessage reportMessage = entry.getValue();
PreparedStatement preparedStatement = connection.prepareStatement(SET_REPORT_MESSAGE);
preparedStatement.setInt(1, idOptional.get()); // report id
preparedStatement.setInt(2, entry.getKey()); // reporter id
preparedStatement.setString(3, reportMessage.getMessage()); // reason
preparedStatement.setString(4, reportMessage.getServer()); // server
preparedStatement.setInt(5, reportMessage.getServerWeight()); // weight
preparedStatement.setTimestamp(6, new Timestamp(reportMessage.getTimeCreated().getTime())); // time
preparedStatement.execute();
setReportMessageStatement.setInt(1, idOptional.get()); // report id
setReportMessageStatement.setInt(2, entry.getKey()); // reporter id
setReportMessageStatement.setString(3, reportMessage.getMessage()); // reason
setReportMessageStatement.setString(4, reportMessage.getServer()); // server
setReportMessageStatement.setInt(5, reportMessage.getServerWeight()); // weight
setReportMessageStatement.setTimestamp(6, new Timestamp(reportMessage.getTimeCreated().getTime())); // time
setReportMessageStatement.addBatch();
}
Optional<Integer> handlerIdOptional = report.getHandlerId();
if (handlerIdOptional.isPresent())
{
PreparedStatement preparedStatement = connection.prepareStatement(SET_REPORT_HANDLER);
preparedStatement.setInt(1, idOptional.get()); // report id
preparedStatement.setInt(2, handlerIdOptional.get()); // handler id
preparedStatement.execute();
setReportHandlerStatement.setInt(1, idOptional.get()); // report id
setReportHandlerStatement.setInt(2, handlerIdOptional.get()); // handler id
setReportHandlerStatement.addBatch();
}
Optional<ReportResult> reportResultOptional = report.getReportResult();
if (reportResultOptional.isPresent())
{
ReportResult reportResult = reportResultOptional.get();
PreparedStatement preparedStatement = connection.prepareStatement(SET_REPORT_RESULT);
preparedStatement.setInt(1, idOptional.get()); // report id
preparedStatement.setInt(2, reportResult.getResultType().getId()); // result id
preparedStatement.setString(3, reportResult.getReason()); // reason
preparedStatement.setTimestamp(4, new Timestamp(reportResult.getClosedTime().getTime())); // closed time
preparedStatement.execute();
setReportResultStatement.setInt(1, idOptional.get()); // report id
setReportResultStatement.setInt(2, reportResult.getResultType().getId()); // result id
setReportResultStatement.setString(3, reportResult.getReason()); // reason
setReportResultStatement.setTimestamp(4, new Timestamp(reportResult.getClosedTime().getTime())); // closed time
setReportResultStatement.addBatch();
}
setReportMessageStatement.executeBatch();
setReportHandlerStatement.executeBatch();
setReportResultStatement.executeBatch();
}
else
{