Перемещая большее число строк в SQLite или любой другой реляционной базе данных, вы должны следовать некоторым основным принципам:
1) установить autoCommit
в false т.е. не фиксируйте каждую вставку
2) используйте пакетное обновление , т. е. не выполняйте обратную передачу для каждой строки
3) используйте подготовленный оператор т.е. не разбирайте каждую вставку.
Соединяя это вместе, вы получаете следующий код:
cn
- исходное соединение, cn2
- целевое соединение.
Для каждой вставленной строки вы звоните addBatch
, но только один раз за batchSize
вы звоните executeBatch
, что инициирует обратную передачу.
Не забудьте последний executeBatch
в конце цикла иfinal commit
.
cn2.setAutoCommit(false)
String SEL_STMT = "select id, col1,col2 from tab1"
String INS_STMT = "insert into tab2(id, col1,col2) values(?,?,?)"
def batchSize = 10000
def stmt = cn.prepareStatement(SEL_STMT)
def stmtIns = cn2.prepareStatement(INS_STMT)
rs = stmt.executeQuery()
while(rs.next())
{
stmtIns.setLong(1,rs.getLong(1))
stmtIns.setString(2,rs.getString(2))
stmtIns.setTimestamp(3,rs.getTimestamp(3))
stmtIns.addBatch();
i += 1
if (i == batchSize) {
def insRec = stmtIns.executeBatch();
i = 0
}
}
rs.close()
stmt.close()
def insRec = stmtIns.executeBatch();
stmtIns.close()
cn2.commit()
Пример теста с вашим размером с sqlite-jdbc-3.23.1:
inserted rows: 10000000
total time taken to insert the batch = 46848 ms
Я не наблюдаю никаких проблем с памятью или проблем с большой транзакцией