gpt4 book ai didi

java - 如何超快地插入 100,000 个父行,每个父行有 200 个子行?

转载 作者:搜寻专家 更新时间:2023-10-30 20:22:57 26 4
gpt4 key购买 nike

我有一个名为 OrderEvent 的父实体和一个名为 PreCondition 的子实体。一个 OrderEvent 可以有多个 PreConditions(>= 200)。我需要保存 100000 OrderEvent + 100000 * 200 PreCondition。我使用 Repository.save(list Of OrderEvents) 并为每 1000 条记录保存到数据库中。插入 1000 个 OrderEvents 大约需要 30 秒。

保存所有 100000 个 OrderEvents 需要将近一个小时。

有什么方法可以将时间缩短到 2 分钟以下?

尝试保存存储库的实体方法

    public  void parseOrder(String path, String collectionName) throws ParseException {
BufferedReader reader;
Connection conn = (Connection) em.unwrap(java.sql.Connection.class);
System.out.println(conn);
try {
reader = new BufferedReader(new FileReader(
path));
String line = reader.readLine();

String jobNumber = line.substring(0, 7).trim();
String recordType = line.substring(7, 9).trim();
Integer len = line.length();
preId = 0L;
postId = 0L;
eventId = 0L;

OrderEvent orderEvent = this.paraseHeader(line,len,jobNumber,collectionName);
Integer count = 1;
Integer batch = 0;
long startTime = System.nanoTime();

List<OrderEvent> list = new ArrayList<OrderEvent>();
while (line != null) {
line = reader.readLine();
if (line == null) {
continue;
}
jobNumber = line.substring(0, 7).trim();
recordType = line.substring(7, 9).trim();
len = line.length();

if (recordType.equals("0H")) {

count++;
batch++;
if (batch.equals(1000)) {
orderRepository.save(list);
list.clear();
long estimatedTime = System.nanoTime() - startTime;
System.out.println("Processed " + batch + " records in " + estimatedTime / 1_000_000_000. + " second(s).");

batch = 0;
startTime = System.nanoTime();
}


list.add(orderEvent);
//orderRepository.saveAndFlush(orderEvent);
orderEvent = this.paraseHeader(line,len,jobNumber,collectionName);

} else if (recordType.equals("2F")) {
this.paraseFeature(line,len,jobNumber,orderEvent);
}
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
}

}

private OrderEvent paraseHeader (String line,Integer len,String jobNumber,String collectionName) throws ParseException {

String model = line.substring(9, 16).trim();
String processDate = line.substring(len-11,len-3).trim();
String formattedProcessDate = processDate.substring(0,4) + "-" +
processDate.substring(4,6) +"-" + processDate.substring(6,8) + " 00:00:00";

//eventId++;

OrderEvent orderEvent = new OrderEvent(jobNumber,UUID.randomUUID().toString(),collectionName,
formatter.parse(formattedProcessDate));

// preId++;
//postId++;
orderEvent.fillPrecondition("Model", "Stimulus", "OP_EQ", model);
orderEvent.fillPostcondition("Add_Fact","Coded","Response","True");


return orderEvent;
}
private void paraseFeature (String line,Integer len, String jobNumber, OrderEvent orderEvent) {

// preId++;
String feature = line.substring(len-7,len).trim();
orderEvent.fillPrecondition("Feature", "Stimulus", "OP_EQ", feature);
}

最佳答案

这通常取决于数据库设置,例如客户端的延迟是多少,表上的索引是什么,查询如何锁定表等等。

确保您了解在网络操作上花费了多少时间。这可能是限制因素,尤其是当您的数据库位于世界的另一端时。

首先确定客户端和数据库服务器之间的延迟是多少。如果它是 10 毫秒,那么逐行插入将是:100,000 * 200 * 10ms = 200000s ~ 56h。这非常慢,因此请确保您使用的是 JDBC 批量插入。

有时可以通过创建影子表显着加快插入过程:

  1. 创建与 OrderEventsPreCondition 表相同的新表。一些 RDBMS 允许使用 CREATE TABLE ... AS SELECT ... FROM ... 语法。
  2. 禁用影子表上的外键和索引。
  3. 批量插入所有数据。
  4. 在影子表上启用外键和索引。这有望确保导入的数据是正确的。
  5. 将影子表插入到实际表中,例如通过运行 INSERT INTO ... SELECT ... FROM ...
  6. 删除影子表。

然而,最好的选择是跳过 JDBC 并切换到数据库提供的批量加载实用程序,例如Oracle 数据库有 External TablesSQL*Loader .这些工具专为高效摄取大量数据而设计,而 JDBC 是一个通用接口(interface)。

关于java - 如何超快地插入 100,000 个父行,每个父行有 200 个子行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55418967/

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