Ускорить обработку массива и базы данных
Есть большой файл с данными радаров. Формат каждой строки такой
0,47.323057,42.214830,1,60,1,7
Я сначала копирую этот файл себе на устройство, затем каждую строку раскладываю и добавляю в базу данных. Код применяю такой
while ((line = reader.readLine()) != null) {
try {
_count_2++;
line_array = line.split(",");
contentValues.put(SpeedCamBase.IDX, line_array[0]);
contentValues.put(SpeedCamBase.Longitude, line_array[1]);
contentValues.put(SpeedCamBase.Latitude, line_array[2]);
contentValues.put(SpeedCamBase.Type, line_array[3]);
contentValues.put(SpeedCamBase.Speed, line_array[4]);
contentValues.put(SpeedCamBase.Dir_type, line_array[5]);
contentValues.put(SpeedCamBase.Direction, line_array[6]);
database_speedcam.insert(SpeedCamBase.TABLE_SETTING, null, contentValues);
} catch (OutOfMemoryError e) {
}
}
Таких строк может быть до 200000. И обработка занимает долгое время. Как можно ускорить обработку данных?
Если использовать потоки, то как сделать синхронизацию?
Ответы (2 шт):
Если используется mySQL, то вместо построчного чтения и обработки файла данных можно отправить LOAD DATA запрос при условии, что этот файл находится на машине, где запущен сервер БД:
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/myDB", "root", "pswd");
String dataFilename = "C:\tmp\speedcam_data.csv";
Statement stmt = conn.createStatement();
String sql = "LOAD DATA INFILE '" + dataFilename + "' \n"
+ " REPLACE \n" // заменить данные
+ " INTO TABLE speedcam \n"
+ " COLUMNS TERMINATED by ',' \n"
// + " IGNORE 1 LINES" // если файл содержит строку-заголовок, раскомментировать
;
stmt.execute(sql);
Если оператор LOAD DATA не поддерживается, то можно применить PreparedStatement c обработкой пакетов (batch), при этом следует отключить авто-коммит conn.setAutoCommit(false);
Также для mySQL есть дополнительная опция ?rewriteBatchedStatements=true, которую можно добавить в строку соединения с БД.
private static final String INSERT_SQL = "INSERT INTO speedcam "
+ "(idx, longitude, latitude, `type`, speed, dir_type, direction) "
+ "VALUES (?, ?, ?, ?, ?, ?, ?)";
private static final int BATCH_SIZE = 50;
public void loadData(String dataFilename) throws IOException, SQLException {
try (
Connection conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/myDB?rewriteBatchedStatements=true",
"root", "pswd"
);
PreparedStatement stmt = conn.prepareStatement(INSERT_SQL);
BufferedReader br = new BufferedReader(new FileReader(dataFilename));
) {
String line;
int count = 0;
boolean autoCommit = conn.getAutoCommit();
if (autoCommit) {
conn.setAutoCommit(false);
}
// 0,47.323057,42.214830,1,60,1,7
while ((line = br.readLine()) != null) {
String[] cols = line.split(",");
stmt.setInteger(1, Integer.parseInt(cols[0])); // id
stmt.setDouble (2, Double.parseDouble(cols[1])); // lat
stmt.setDouble (3, Double.parseDouble(cols[2])); // lng
stmt.setInteger(4, Integer.parseInt(cols[3])); // type
stmt.setInteger(5, Integer.parseInt(cols[4])); // speed
stmt.setInteger(6, Integer.parseInt(cols[5])); // dir_type
stmt.setInteger(7, Integer.parseInt(cols[6])); // direction
stmt.addBatch();
count++;
if (count == BATCH_SIZE) {
stmt.executeBatch();
count = 0;
}
}
if (count > 0) {
stmt.executeBatch();
}
conn.commit();
if (autoCommit) {
// восстановить авто-коммит
conn.setAutoCommit(true);
}
}
}
база MySQL Проблема решена, скорость обработки увеличилась раз в 10.
dbSpeedCam = new SpeedCamBase(mContext);
database_speedcam = dbSpeedCam.getWritableDatabase();
contentValues = new ContentValues();
database_speedcam.beginTransaction(); <-- пишем эту строчку
///
while ((line = reader.readLine()) != null) {
try {
_count_2++;
line_array = line.split(",");
contentValues.put(SpeedCamBase.KEY_ID, _count_2);
contentValues.put(SpeedCamBase.IDX, line_array[0]);
contentValues.put(SpeedCamBase.Longitude, line_array[1]);
contentValues.put(SpeedCamBase.Latitude, line_array[2]);
contentValues.put(SpeedCamBase.Type, line_array[3]);
contentValues.put(SpeedCamBase.Speed, line_array[4]);
contentValues.put(SpeedCamBase.Dir_type, line_array[5]);
contentValues.put(SpeedCamBase.Direction, line_array[6]);
database_speedcam.insert(SpeedCamBase.TABLE_SETTING, null, contentValues);
} catch (OutOfMemoryError e) {
}
}
///
database_speedcam.setTransactionSuccessful(); <-- пишем эту строчку
database_speedcam.endTransaction(); <-- пишем эту строчку