jdbc批量插入,通过csv文件多数据拼一条sql执行。
2014-12-09 00:00
453 查看
因以后工作可能需要,写了一个小工具类 , 博客记录下。
原理是通过读取csv文件进行sql语句的拼串,将要插入的多数据拼成一条来执行,效率比多条执行要高很多。
测试了一下,10W条数据(简单的测试数据)用传统的PrepareStatement的addBatch()方法1000条执行一次,耗时7秒左右。
现在通过拼串的方法将1000条数据拼成一条sql 10W条下来用时1秒多。
工具的参数写的有点死,结合实际的时候需要改动。而且还有好多可以优化的地方。希望大家指正。
另外附带一个 输出CSV文件的简单实现:
原理是通过读取csv文件进行sql语句的拼串,将要插入的多数据拼成一条来执行,效率比多条执行要高很多。
测试了一下,10W条数据(简单的测试数据)用传统的PrepareStatement的addBatch()方法1000条执行一次,耗时7秒左右。
现在通过拼串的方法将1000条数据拼成一条sql 10W条下来用时1秒多。
工具的参数写的有点死,结合实际的时候需要改动。而且还有好多可以优化的地方。希望大家指正。
package db; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; /** * 利用csv文件拼一条sql语句进行数据库插入 * * @author cuijk * @date 2014-12-8 * */ public class SqlUtil { private static String driver = "com.mysql.jdbc.Driver"; private static String url = "jdbc:mysql://localhost:3306/test?autoReconnect=true&useUnicode=true&characterEncoding=utf-8"; private static String user = "root"; private static String pwd = "root"; private static String filePath = "d://test.csv"; // 读取文件时要用的字符编码 private static String charset = "UTF-8"; // sql前后缀 private static String preSql = "INSERT INTO users(username,pwd) VALUES "; // 参数 private static String sufSql = "(?,?),"; public static void main(String[] args) { int i = insert(driver, url, user, pwd, preSql, sufSql, filePath, charset); System.out.println(i); } /** * * @param driver * 数据库驱动 * <p> * com.mysql.jdbc.Driver * @param url * 数据库url * <p> * jdbc:mysql://localhost:3306/test * @param user * 用户名 * @param pwd * 密码 * @param preSql * sql语句前缀 * <p> * INSERT INTO users(username,pwd) VALUES * @param sufSql * sql语句后缀 * <p> * (?,?), * @param filePath * 文件路径 * <p> * d://test.csv * @param charset * 读取文件时所用的编码 * <p> * UTF-8 * @return * */ public static int insert(String driver, String url, String user, String pwd, String preSql, String sufSql, String filePath, String charset) { long start = System.currentTimeMillis(); StringBuilder sqlSb = null; Connection conn = null; BufferedReader br = null; InputStreamReader isr = null; PreparedStatement pstm = null; int count = 0; int total = 0; try { String line = ""; isr = new InputStreamReader( new FileInputStream(new File(filePath)), charset); br = new BufferedReader(isr); // 获取非手动提交Connection conn = getConnection(driver, url, user, pwd); sqlSb = new StringBuilder(preSql); List<String> list1 = new ArrayList<String>(); List<String> list2 = new ArrayList<String>(); while ((line = br.readLine()) != null) { count++; total++; sqlSb.append(sufSql); list1.add(line.substring(0, line.indexOf(","))); list2.add(line.substring(line.indexOf(",") + 1, line.length())); if (count >= 1000) { // 去除sql最后的一个','; sqlSb.delete(sqlSb.length() - 1, sqlSb.length()); pstm = conn.prepareStatement(sqlSb.toString()); // 填充占位符 for (int i = 0; i < count; i++) { pstm.setString(i * 2 + 1, list1.get(i)); pstm.setString(i * 2 + 2, list2.get(i)); } pstm.execute();// 执行一条sql语句 conn.commit(); System.out.println("处理 : " + count + "条记录。"); // 处理完1000条就清空一次 sqlSb = new StringBuilder(preSql); count = 0; list1.clear(); list2.clear(); } } if (count > 0) { // 清理sql语句 sqlSb = new StringBuilder(preSql); for (int i = 0; i < count; i++) { sqlSb.append(sufSql); } // 删除最后一个',' sqlSb.delete(sqlSb.length() - 1, sqlSb.length()); pstm = conn.prepareStatement(sqlSb.toString()); for (int i = 0; i < count; i++) { pstm.setString(i * 2 + 1, list1.get(i)); pstm.setString(i * 2 + 2, list2.get(i)); } pstm.execute(); pstm.clearBatch(); System.out.println("处理 : " + count + "条数据"); conn.commit(); } list1.clear(); list2.clear(); double time = ((double) (System.currentTimeMillis() - start)) / 1000; System.out.println("处理完毕,共处理" + total + "条记录,花费 : " + time + "秒"); return total; } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { if (br != null) { br.close(); } if (isr != null) { isr.close(); } } catch (IOException e) { e.printStackTrace(); } closeConn(conn); } return 0; } /** * 获取链接,setAutoCommit(false),设置非自动提交 * * @param dbDriver * @param dbUrl * @param dbUser * @param dbPwd * @return * @throws InstantiationException * @throws IllegalAccessException * @throws ClassNotFoundException * @throws SQLException */ private static Connection getConnection(String dbDriver, String dbUrl, String dbUser, String dbPwd) throws InstantiationException, IllegalAccessException, ClassNotFoundException, SQLException { Class.forName(dbDriver).newInstance(); Connection conn = DriverManager.getConnection(dbUrl, dbUser, dbPwd); conn.setAutoCommit(false); return conn; } /** * 关闭链接 * * @param conn */ private static void closeConn(Connection conn) { try { if (conn != null) { conn.close(); } } catch (SQLException e) { e.printStackTrace(); System.out.println("连接未正常关闭"); } } }
另外附带一个 输出CSV文件的简单实现:
package io; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.io.OutputStreamWriter; import java.util.ArrayList; import java.util.List; public class CSVUtil { public static void main(String[] args) { int count = 100054; File file = new File("d://test.csv"); long s = System.currentTimeMillis(); List<String> dataList = new ArrayList<String>(); for (int i = 0; i < count; i++) { dataList.add("测试一1,测试二2"); } exportCsv(file, dataList); dataList.clear(); double e = (double) System.currentTimeMillis(); System.out.println((e - s) / 1000); } public static boolean exportCsv(File file, List<String> dataList) { boolean isSucess = false; FileOutputStream out = null; OutputStreamWriter osw = null; BufferedWriter bw = null; try { out = new FileOutputStream(file); osw = new OutputStreamWriter(out, "UTF-8"); bw = new BufferedWriter(osw); if (dataList != null && !dataList.isEmpty()) { for (String data : dataList) { // 为文件加入bom信息头 bw.write(new String(new byte[] { (byte) 0xEF, (byte) 0xBB, (byte) 0xBF })); bw.write(new String(data.getBytes("UTF-8"))); bw.newLine(); } bw.flush(); } isSucess = true; } catch (Exception e) { isSucess = false; } finally { if (bw != null) { try { bw.close(); bw = null; } catch (IOException e) { e.printStackTrace(); } } if (osw != null) { try { osw.close(); osw = null; } catch (IOException e) { e.printStackTrace(); } } if (out != null) { try { out.close(); out = null; } catch (IOException e) { e.printStackTrace(); } } } return isSucess; } public static List<String> importCsv(File file) { List<String> dataList = new ArrayList<String>(); BufferedReader br = null; try { br = new BufferedReader(new FileReader(file)); String line = ""; while ((line = br.readLine()) != null) { dataList.add(line); } } catch (Exception e) { } finally { if (br != null) { try { br.close(); br = null; } catch (IOException e) { e.printStackTrace(); } } } return dataList; } }
相关文章推荐
- sql-insert一条语句执行多条数据插入
- mysql通过一条sql完成没有则更新,有则插入新数据
- 数据库操作_连接SQL Server数据库示例;连接ACCESS数据库;连接到 Oracle 数据库示例;SqlCommand 执行SQL命令示例;SqlDataReader 读取数据示例;使用DataAdapter填充数据到DataSet;使用DataTable存储数据库表;将数据库数据填充到 XML 文件;10 使用带输入参数的存储过程;11 使用带输入、输出参数的存储过程示;12 获得数据库中表的数目和名称;13 保存图片到SQL Server数据库示例;14 获得插入记录标识号;Exce
- 执行一条SQL语句,插入多条数据!
- 通过 java 把excel xls中数据转为可直接插入数据库的sql文件
- SQL 读取csv 文件批量插入数据
- MySQL命令行执行插入sql文件中文乱码
- SQL 为主表的谋一条记录,在中间表中同时插入多条数据
- 通过批处理文件(.bat)执行.sql文件
- 关于LIMIT(超出界限时,SQL执行也没有问题,而且结果集中只会到有数据的最后一条记录,不会出现空,已经过测试)
- C# 执行多条SQL语句,实现数据库事务(通过Hashtable存储数据) .
- C#:30行数据插入到数据库中的效率测试-一行行执行、构造SQL一次执行、SqlBulkCopy
- 写了一条Sybase SQL语句,用于生成一个表中所有数据的插入记录的生成
- 仅通过SQL备份文件将MOSS服务器场及所有网站数据迁移到新的一台服务器上 推荐
- sqlserver中通过osql/ocmd批处理批量执行sql文件的方法
- C#:30行数据插入到数据库中的效率测试-一行行执行、构造SQL一次执行、SqlBulkCopy
- 一条SQL语句 插入多条数据
- [转koumi]一个高效率SQL储存过程分页,执行效率测试通过500万以上的数据
- 通过SqlDataAdapter 插入DataSet中的数据到数据库
- sql读取csv和xls格式的文件,数据源