面试题:大批量数据高效插入数据库表

原文:http://yakyang.com/?p=592


题目:将一批10万数据通过系统(Java语言)导入数据库表,并要求实时看到导入的进度,请设计出系统方案,重点要考虑导入效率!

这个题场景很简单!

题中提到了两个重要需求:
1、实时看到导入的进度;
2、导入效率。

第一个需求可以简单理解就是能够看到导入过程。进度就是一个大概情况,并不是一个要求非常精准的数,但是如果做的很牛逼就是真实的反应成功导入的条数。这样话实现的方案有大有不同了!第二个需求就是一个无限想象的需求!只要能提高导入效率的都可以写入方案,看来是要看答题人的思考问题的广度和技术经验了。

下面是我的方案也并非完美!

1、 首先考虑10万数据,是一个不小的数据量,题目没有说数据存储的介质,我就不考虑如何读文件了。10万数据如果按照一条一条导入肯定不是一个最优的方案,数据之间没有相关联,那就将数据分隔为1万一批,将10万数据分给10线程处理,这样肯定要比一个线程导的快,这样算是一个分布计算啦!呵呵!

2、 现在我们要考虑一个线程怎么导入快。怎么提高效率,一般有数据库操作,就要重点考虑数据库操作,此题是一个插入数据库表。我们立刻想到:
for(Object o : list ){
    insert into table value ( o );
}
这种显然是拼接SQL一个条条插入数据表嘛!相信一般人都会这么想,这样对吗?肯定没有问题,但是绝对不高效的,每次执行一次就要像数据库传SQL,数据库编译SQL,然后执行。我们是大批数据插入,应该使用批处理方式。
String sql = “insert into table(…) values (?, ?, ?)”;
Connection connection = new getConnection();
PreparedStatement ps = connection.prepareStatement(sql);
for (Object o: list) {
   ps.setString(1,o.get…);
   ps.setString(2, o.get…);
   ps.setString(3, o.get…);
   ps.addBatch();
}
ps.executeBatch();
ps.close();
connection.close();
这样实现速度就比第一种要快很多,SQL语句也只需编译一次。

3、 按照上面做还有问题吗?显然还不够嘛!我们还没有考虑事务!一万条提交一次事务显然不合理,对数据库压力很大,所以要控制事务的粗粒度,可以100条提交一次事务。

4、 接下来就要考虑数据库了,我经常问大家?表建索引和没有索引有啥区别?很多人都说建索引查询速度快,其实还有一点就是插入慢了啊!所以插入的表单表不要建索引,有索引将索引删掉,导入完后再建索引。

5、 高效插入应该差不多了,现在要考虑第二个需求—实时进度。很多人第一反应就是select count(1) from table,这样存在一个问题就是查询的频率,频率大数据就比较精确,如果频率小数据就不准确,5分钟查一次比1分钟获得数据要差很大,这个方案显然不算很合理了。那就在内存设置一个变量n,实时保存插入成功数量,但是根据1点说多线程同时插入,那就有可能两个线程同时加,造成数据也不准确了,那么我们就要考虑对n加锁啦!



到此我们的方案就算完了!是不是最优的?肯定还有改进的空间,但是这样够了

  • 4
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值