Пару лет назад я написал небольшую утилиту для перемещения данных из Oracle db в db Postgres. Я использовал Java и JDBC для этого, потому что я хотел, чтобы Java обрабатывала форматирование данных для данных, используемых в подготовленном заявлении для вставки. Исходная версия утилиты предполагала, что имена таблиц и имена столбцов были одинаковыми в обеих базах данных. Более поздние версии приняли файл сопоставления для обработки различий имен. Эта утилита была большим хитом в моей организации, но, к сожалению, она не масштабировалась. Он максимизируется примерно на миллион строк, перемещаемых в час. Теперь у нас есть таблицы с 30 + миллионами строк, и никто не хочет ждать 30 часов для передачи своих данных.Oracle to Postgres data transfer
Метод ниже - это сердце полезности и причина, по которой он не масштабируется. Этот метод выполняется один раз для каждого столбца данных, поэтому он вызывается (num_rows * num_cols раз). С профилировщиком я вижу, что этот метод потребляет 58% времени выполнения. Только вызовы getObject() и findColumn() составляют 53% времени выполнения!
public void setPlaceholderValue (int placeHolderNum, ResultSet rs, String oracleColumnName, PreparedStatement stmt) throws Exception {
int columnIndex = rs.findColumn(oracleColumnName) ;
int columnType = rs.getMetaData().getColumnType(columnIndex) ;
try{
if (rs.getObject(oracleColumnName) != null){
switch (columnType) {
case Types.VARCHAR: stmt.setString(placeHolderNum, rs.getString(columnIndex)); break;
case Types.INTEGER: stmt.setInt(placeHolderNum, rs.getInt(columnIndex)); break ;
case Types.DATE: stmt.setDate(placeHolderNum, rs.getDate(columnIndex)); break;
case Types.FLOAT: stmt.setFloat(placeHolderNum, rs.getFloat(columnIndex)); break ;
case Types.NUMERIC: stmt.setBigDecimal(placeHolderNum,rs.getBigDecimal(columnIndex)); break ;
case Types.TIMESTAMP: stmt.setTimestamp(placeHolderNum, rs.getTimestamp(columnIndex)); break ;
default: throw new SQLException("The result set column type " + rs.getMetaData().getColumnType(columnIndex) + " was not recognized. see the java.sql.Types class at http://java.sun.com/j2se/1.5.0/docs/api/ ");
}
} else {
stmt.setNull(placeHolderNum, columnType);
}
} catch (SQLException e){
System.out.println ("SQLException: " + e.getMessage() + " for record id=" + rs.getLong("id"));
throw new SQLException("rethrow");
}
}
Я не уверен, что смогу реорганизовать этот метод, чтобы снизить время передачи. Я думаю, что столбец под столбцом просто не масштабируется.
Может ли кто-нибудь предложить лучший способ сделать это? Язык не проблема, я могу сделать это с чем-нибудь, что может справиться с работой . В идеале я хотел бы видеть скорость передачи не менее 10 миллионов записей в час.
10M записи час кажется довольно smokin '. –