繁体   English   中英

Java多线程在数据库中插入数百万条记录

[英]Java multi-threading insert millions of records in the database

我是Java新手,还是多线程新手。 面试官一次又一次地问我一个问题。 “给出一个csv文件-如果您要求读取java中的一个文件,该文件包含数百万条记录,然后在较短的时间内将这些记录插入数据库中。” 采访者还问我-如何利用“多线程,批处理和弹簧”之类的概念来解决上述问题?

我在Inernet上收到了以下代码,但效果并不好,除了'PreparedStatement',您还有其他选择吗? 即使我在下面的代码中也看不到使用multithreadig。

  BufferedReader in = new BufferedReader(new FileReader(file)); java.util.List<String[]> allLines = new ArrayList<String[]>(); // used for something else String sql = "insert into test (a, b, c, d)” + " values (?,?,?,?)"; PreparedStatement pstmt = conn.prepareStatement(sql); int i=0; while ((line = in.readLine()) != null) { line = line.trim().replaceAll(" +", " "); String[] sp = line.split(" "); String msg = line.substring(line.indexOf(sp[5])); allLines.add(new String[]{sp[0] + " " + sp[1], sp[4], sp[5], msg}); pstmt.setString(1, sp[0] + " " + sp[1]); pstmt.setString(2, sp[4]); pstmt.setString(3, sp[5]); pstmt.setString(4, msg); pstmt.addBatch(); i++; if (i % 1000 == 0){ pstmt.executeBatch(); conn.commit(); } } pstmt.executeBatch(); 

不是一个真正的答案,但是给您一些提示:

请注意,对于sql-server,它可以接收的最大包大小有一个可配置的限制

  • 询问CSV文件的属性是什么
    是否可以假设每个条目代表唯一的东西,而不是代表同一数据库条目的多行

  • 检查该表的主键是什么

如果给出了唯一性,则可以并行进行导入(分割文件)。 关闭主键可能是必须的,因此数据库不会锁定插入命令。

如果未提供唯一性,则可能需要预处理文件以使条目唯一。

  • 考虑批处理大小:我不是数据库专家,但我学到的知识都不大也不小。

  • 不知道您用spring指的是什么:spring框架,也许吗?

SQL插入将锁定该表,使其无法进行进一步的操作,直到发出提交为止。 因此,所有插入将按顺序是FIFO。 还记得ACID属性吗? 从学校? 再次阅读。
插入不能使用多个线程来完成,没有用。 因为,这些线程将继续等待获得对表的锁定,并且最终消耗的时间比在“ for循环”中花费的时间更多。

批量插入是Java中提供的一项规定,可以一次插入多个条目,但是从数据库方面来看,它是n个具有一次提交的插入。 提供它以简化编程。

现在,解决方案。

要将数百万条记录插入数据库表中,可以通过执行以下操作来实现。 创建许多临时表。 创建一打线程。 将您的数百万条记录分割成十几个线程,这些线程将数据插入各自的表中。 最后,将这几十个表的所有数据合并到最终表中。 您将比单循环插入快12倍。 此方法的性能也取决于您的计算机配置。 您需要足够的核心和足够的内存来执行此操作。

为了获得更好的性能,所有这几十个表都不应具有索引,这会略微提高插入性能。

如果您有一个好的服务器,请使用100个线程和100个表。 您将比单循环快100倍。

如果您在任何银行或零售公司的Live DB上执行此类操作,则将在EOD前被解雇。 此类高性能操作必须预先计划,并且必须传达给数据库管理员,并且只有在收到批准电子邮件后才能进行。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM