gpt4 book ai didi

java - 如何优化从平面文件到 BD PostgreSQL 的数据导入?

转载 作者:行者123 更新时间:2023-11-29 13:59:33 27 4
gpt4 key购买 nike

大家早上好,我有一个问题,你正好需要导入1400万条记录,其中包含一家公司的客户信息。

平面文件。 txt有2.8GB,我开发了一个java程序,逐行读取平面文件,处理信息放入一个对象中,然后插入到PostgreSQL数据库中的一个表中,主题是我做了计算在 112 分钟内插入了 100000 条记录,但问题是我插入了零件。

public static void main(String[] args) {  

// PROCESSING 100,000 records in 112 minutes
  // PROCESSING 1,000,000 records in 770 minutes = 18.66 hours

loadData(0L, 0L, 100000L);
}

/**
* Load the number of records Depending on the input parameters.
* @param counterInitial - Initial counter, type long.
* @param loadInitial - Initial load, type long.
* @param loadLimit - Load limit, type long.
*/
private static void loadData(long counterInitial, long loadInitial, long loadLimit){
Session session = HibernateUtil.getSessionFactory().openSession();
try{
FileInputStream fstream = new FileInputStream("C:\\sppadron.txt");
DataInputStream entrada = new DataInputStream(fstream);
BufferedReader buffer = new BufferedReader(new InputStreamReader(entrada));
String strLinea;
while ((strLinea = buffer.readLine()) != null){
if(counterInitial > loadInitial){
if(counterInitial > loadLimit){
break;
}
Sppadron spadron= new Sppadron();
spadron.setSpId(counterInitial);
spadron.setSpNle(strLinea.substring(0, 9).trim());
spadron.setSpLib(strLinea.substring(9, 16).trim());
spadron.setSpDep(strLinea.substring(16, 19).trim());
spadron.setSpPrv(strLinea.substring(19, 22).trim());
spadron.setSpDst(strLinea.substring(22, 25).trim());
spadron.setSpApp(strLinea.substring(25, 66).trim());
spadron.setSpApm(strLinea.substring(66, 107).trim());
spadron.setSpNom(strLinea.substring(107, 143).trim());
String cadenaGriSecDoc = strLinea.substring(143, strLinea.length()).trim();
String[] tokensVal = cadenaGriSecDoc.split("\\s+");
if(tokensVal.length == 5){
spadron.setSpNac(tokensVal[0]);
spadron.setSpSex(tokensVal[1]);
spadron.setSpGri(tokensVal[2]);
spadron.setSpSec(tokensVal[3]);
spadron.setSpDoc(tokensVal[4]);
}else{
spadron.setSpNac(tokensVal[0]);
spadron.setSpSex(tokensVal[1]);
spadron.setSpGri(tokensVal[2]);
spadron.setSpSec(null);
spadron.setSpDoc(tokensVal[3]);
}
try{
session.getTransaction().begin();
session.save(spadron); // Insert
session.getTransaction().commit();
} catch (Exception e) {
session.getTransaction().rollback();
e.printStackTrace();
}
}
counterInitial++;
}
entrada.close();
} catch (Exception e) {
e.printStackTrace();
}finally{
session.close();
}
}

主要问题是如果他们在我插入前一百万条记录时检查我的代码,参数如下:loadData (0L, 0L, 1000000L);

问题是,当您插入以下记录时,在这种情况下,下一百万条记录将是:loadData (0L, 1000000L, 2000000L);什么会导致它回滚前 1000 亿条记录,然后当计数器最近的值为 1000001 时将开始插入以下记录,有人可以给我一个更优化的插入记录的建议,知道有必要对待前面代码中显示的信息。

最佳答案

参见 How to speed up insertion performance in PostgreSQL .

您应该做的第一件事是绕过 Hibernate。 ORM 很方便,但您要为这种方便付出速度上的代价,尤其是批量操作时。

您可以使用 JDBC PreparedStatement 将插入分组到合理大小的事务中,并使用多值 insert

但就我个人而言,我会 use PgJDBC's support for the COPY protocol更直接地进行插入。打开 Hibernate Session 对象以获取底层 java.sql.Connectionget the PGconnection interface for it , getCopyAPI() 获取CopyManager,并使用copyIn将您的数据输入数据库。

由于看起来您的数据不是 CSV 格式而是固定宽度的字段格式,您需要做的是启动一个线程从文件中读取数据,将每个数据转换为适用于 PostgreSQL 的 CSV 格式输入,并将其写入缓冲区,copyIn 可以使用传递的 Reader 进行消费。这听起来比实际更复杂,并且有很多使用 java.io.Readerjava.io.Writer 接口(interface)的 Java 生产者/消费者线程实现的例子.

您可以改为为 Reader 编写一个过滤器,它包装底层文件阅读器并转换每一行。这比生产者/消费者线程要简单得多。首先将其作为首选进行研究。

关于java - 如何优化从平面文件到 BD PostgreSQL 的数据导入?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23660415/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com