我需要创建一个约需要插入数据库的50K记录列表。Java列表v/s数据库列表哪一个很贵?
我能想到的两种方法是在性能
方面更好的办法- 存储过程,它接受这些对象的名单,将它们插入Java和使用每一条记录调用数据库插入
- 建构列表MyBatis的
我需要创建一个约需要插入数据库的50K记录列表。Java列表v/s数据库列表哪一个很贵?
我能想到的两种方法是在性能
方面更好的办法表现最好的将来自插入语句的批次,如下所示:
insert into my_table (c1, c2, c3) values
(v1, v2, v3),
(v4, v5, v6),
...
如果您将它分成50,000个插入语句,您将获得更差的性能。插入语句越少越好。每个插入语句都需要mysql解析查询,并获取并释放必要表上的锁,更不用说启动和提交事务。例如,如果您可以在500行的100个块中完成此操作,则会削减49,900x这个开销。
如果您想使用LOAD DATA INFILE命令,您甚至可以进一步提高性能,但这会使事情变得复杂一些,根据您的具体要求可能不值得。
这是无效的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
你最好的表现将是某种形式的批量插入不管是
多记录插入:使用本地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 MB(或100万个字符)。只是发送和解析这样的命令将需要一些时间。您很可能会额外努力发送CLOB等命令。 –
我想用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();
}
这真的是最好的答案,因为它直接处理java'List',如何以可管理的批次分解它(并不总是一个单一的兆字节批是最好的),以及如何以标准jdbc方式处理批处理。 – YoYo
无论哪种方式是好的,按我的知识,我会选择2 MyBatis的一批去。 – PKR
您应该为每种方法确实设置测试用例,并查看数据,硬件,网络等的性能。 – Boneist
jdbc使用标准SQL直接支持批插入。虽然批处理实现不能保证被所有数据库支持,但它受Oracle jdbc驱动程序支持,而Oracle PLSQL仅*受Oracle支持。另外,对于存储过程,您将具有处理数组传递的额外复杂性。 – YoYo