如何将百万数据插入数据库

时间:2016-07-01 02:13:55

标签: java multithreading junit oracle10g

我正在尝试将100万条记录插入数据库表。

我想创建至少3个线程,每个线程触发一个插入,然后我们可以在每秒获得3个并行请求。我们可以通过使每个线程等待和唤醒来控制插入的触发完全同时发生一起到同一个中断。然后每个线程进入睡眠状态,直到经过1秒钟的窗口。然后整个过程将重复。我怎么能完成它?

任何建议或提示都会有所帮助。

5 个答案:

答案 0 :(得分:3)

这是基于来自.. http://www.mkyong.com/jdbc/jdbc-preparedstatement-example-batch-update/

的mykong代码的批量插入的快速示例

这基本上为您提供了sqlloader的速度,它可以进行批量插入。并且只应使用1个线程。

我在这里做的是将插入放入一个循环中,表明你必须每隔几千条记录清除批次。

你会删除无限循环并让它插入数据而不是硬编码的mkyong数据

String insertTableSQL = "INSERT INTO DBUSER"
        + "(USER_ID, USERNAME, CREATED_BY, CREATED_DATE) VALUES"
        + "(?,?,?,?)";

PreparedStatement preparedStatement = dbConnection.prepareStatement(insertTableSQL);
try {
    dbConnection.setAutoCommit(false);

    int batchTotal=0;
    for  (;;) { // infinate loop? change this to get your data here
        preparedStatement.setInt(1, 101);
        preparedStatement.setString(2, "mkyong101");
        preparedStatement.setString(3, "system");
        preparedStatement.setTimestamp(4, getCurrentTimeStamp());
        preparedStatement.addBatch();
        if (batchTotal++ == 4096) {
            int[] result = preparedStatement.executeBatch();
            preparedStatement.clearBatch();
            batchTotal=0;                    
        }
    }
    if (batchTotal > 0) {
        int[] result = preparedStatement.executeBatch();
    }

    dbConnection.commit();
}  finally {
    preparedStatement.close();
}

答案 1 :(得分:2)

插入大量数据被认为是一种不好的做法。插入大量数据会花费大量时间,而您可以使用sqlloader或类似工具直接将数据加载到表中。这些加载器速度更快,因为它们不会导致事务管理的开销。

以下是我在数据库中加载大量数据时会问自己的一些问题。

  1. 此参考/静态数据(如国家,城市,银行)
  2. 这是应用程序/使用应用程序生成的动态数据(如账单,通话记录,付款,帐户活动)。
  3. 大多数情况是案例1,在这种情况下首选sqlloader。

    由于数据迁移/升级,可能会出现其他情况(2),在这种情况下,首选sqlloader。

    基于以上解释。您可以选择更好地描述您的问题或选择sqlloader。

答案 2 :(得分:1)

是按记录插入大量数据一个记录不好的做法它需要很长时间并且增加了数据库的开销,即使你将插入过程拆分成不同的线程然后也会在数据库和其他通信过程上的开销超过预期会减速的数据库。 兽的进口方式是......

1)从旧数据库中获取数据的sql转储并导入到超快速的新数据库

2)如果您想使用程序导入,那么您必须进行批处理,这样您就可以一次插入多条记录,从而减少交易的负担。

3)如果您使用了一些数据库管理UI工具,他们还允许您通过CSV或Excel快速导入,如果您在文件中有数据,也可以快速导入。

许多其他方式,但以上三种中的一种适合你..

答案 3 :(得分:1)

我一直使用sqlloader或sqldeveloper来加载大量数据。有意义的是,当我们有delta时,插入数据的java应用程序是有意义的。但是对于第一次设置/迁移数据sql loader /类似选项是最好的。

答案 4 :(得分:0)

我们可以利用 SQL 查询一次插入多行:

<form method='POST' action='{% url "cart:add-item" product.id product.quantity %}' class="form"> {% csrf_token %}
  <input type='hidden' name='product_id' value='{{ product.id }}' />

  {% if in_cart %}
       <button type='submit' class='btn btn-link btn-sm' style="padding:0px;cursor: pointer;">Remove?</button>
  {% else %}
       {% if product in cart.products.all %}
           In cart <button type='submit' class='btn btn-link'>Remove? 
</button>
     {% else %}
         <button type='submit'  class='btn btn-success'>Add to 
cart</button>
{% endif %}

我已经在 SQL Server 上测试过了。我相信它也应该适用于其他数据库(如果需要,可以在 SQL 查询中稍作修改)。

注意:我使用的是 Spring Data JPA 和 Java 8+。

在这个例子中,我的实体类是这样的:

INSERT INTO table_name (col1, col2, col3) VALUES (val1, val2, val3),
(val4, val5, val6), ... (valx, valy, valz)

这是执行相关任务的类:

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "test")
public class Test {
    @Id
    private Long id;
    private String name;
    @Column(name = "age", columnDefinition = "int default 0", nullable = false)
    private int age;
    //Getters and Setters
}