2016-12-02 90 views
3

我需要创建一个约需要插入数据库的50K记录列表。Java列表v/s数据库列表哪一个很贵?

我能想到的两种方法是在性能

方面更好的办法
  1. 存储过程,它接受这些对象的名单,将它们插入Java和使用每一条记录调用数据库插入
  2. 建构列表MyBatis的
+0

无论哪种方式是好的,按我的知识,我会选择2 MyBatis的一批去。 – PKR

+1

您应该为每种方法确实设置测试用例,并查看数据,硬件,网络等的性能。 – Boneist

+0

jdbc使用标准SQL直接支持批插入。虽然批处理实现不能保证被所有数据库支持,但它受Oracle jdbc驱动程序支持,而Oracle PLSQL仅*受Oracle支持。另外,对于存储过程,您将具有处理数组传递的额外复杂性。 – YoYo

回答

0

表现最好的将来自插入语句的批次,如下所示:

insert into my_table (c1, c2, c3) values 
    (v1, v2, v3), 
    (v4, v5, v6), 
    ... 

如果您将它分成50,000个插入语句,您将获得更差的性能。插入语句越少越好。每个插入语句都需要mysql解析查询,并获取并释放必要表上的锁,更不用说启动和提交事务。例如,如果您可以在500行的100个块中完成此操作,则会削减49,900x这个开销。

如果您想使用LOAD DATA INFILE命令,您甚至可以进一步提高性能,但这会使事情变得复杂一些,根据您的具体要求可能不值得。

+0

这是无效的oracle语法,尽管你可以通过各种方式实现类似的结果,例如'insert into my_table(c1,c2,c3)select double,union的所有v1,v2,v3所有从双重联合中选择v4,v5,v6所有......'或'将所有值都插入my_table(c1,c2,c3)值(v1,v2,v3)到my_table(c1,c2,c3)值(v4,v5,v6)中... select * from dual “一切都显得更加冗长,但他们确实达到了将所有内容都保存在一个声明中的预期结果。 – Sentinel

0

你最好的表现将是某种形式的批量插入不管是

多记录插入:使用本地PL

insert into your_table(c1,c2,c3) 
select v1, v2, v3 from dual union all 
select v4, v5, v6 from dual union all 
... 
select vN, vO, vP from dual; 

insert all 
into your_table(c1,c2,c3) values (v1,v2,v3) 
into your_table(c1,c2,c3) values (v4,v5,v6) 
... 
into your_table(c1,c2,c3) values (vN,vO,vP) 
select * from dual; 

批量插入/ SQL集合:

FORALL i IN your_collection.first .. your_collection.last 
    INSERT INTO your_table(c1,c2,c3) 
    VALUES(your_collection(i).v1 
     , your_collection(i).v2 
     , your_collection(i).v3); 

FORALL i IN INDICES OF your_collection 
    INSERT INTO your_table(c1,c2,c3) 
    VALUES(your_collection(i).v1 
     , your_collection(i).v2 
     , your_collection(i).v3); 

或使用绑定阵列批量插入:

BEGIN 
    FORALL i IN :lower .. :upper 
    INSERT INTO your_table(c1,c2,c3) 
    VALUES(:v1(i), :v2(i), :v3(i)); 
END; 
+1

我怀疑提议的“多记录插入”能否提供足够的性能。该命令的大小可能为1 MB(或100万个字符)。只是发送和解析这样的命令将需要一些时间。您很可能会额外努力发送CLOB等命令。 –

4

我想用PreparedStatement和批量插入是你最好的选择。 PreparedStatement的好处在于,sql被缓存在RDBMS服务器上,批量插入可以以批处理的形式完成。

喜欢的东西:

private void doInsert(Connection conn, List<Data> data){ 
    String sql = "INSERT INTO T (A,B,C) VALUES (?,?,?)"; 
    PreparedStatement ps = conn.prepareStatement(sql); 
    int count = 0; 
    for(Data d : data) { 
     count++; 
     ps.setString(1, data.getA()); 
     ps.setString(2, data.getB()); 
     ps.setString(3, data.getC()); 
     ps.addBatch(); 
     if (count%1000 == 0) { 
      ps.executeBatch(); 
     } 
    } 
    ps.executeBatch(); 
    ps.close(); 
} 
+0

这真的是最好的答案,因为它直接处理java'List',如何以可管理的批次分解它(并不总是一个单一的兆字节批是最好的),以及如何以标准jdbc方式处理批处理。 – YoYo

相关问题