本文共 3577 字,大约阅读时间需要 11 分钟。
在处理大规模数据插入任务时,直接使用JDBC
批量插入虽然能够提高效率,但如果没有正确配置事务设置,可能会导致性能瓶颈。以下是优化方法:
将多次提交合并为一次
通过设置setAutoCommit(false)
,禁用自动提交模式,这样可以将多条插入语句合并为一个事务,减少数据库对日志的频繁写入操作。 使用预编译语句集和批量操作
使用PreparedStatement
对象和preparedStatement.addBatch()
方法,可以将多个插入操作批量添加到数据库中,最后通过preparedStatement.executeBatch()
批量执行。 事务控制
在批量插入完成后,手动调用commit()
来提交事务,这样可以保证所有数据同时写入数据库,避免部分数据丢失。 public static void insert() { Long begin = new Date().getTime(); String prefix = "INSERT INTO tb_big_data (count, create_time, random) VALUES "; try { conn.setAutoCommit(false); PreparedStatement pst = conn.prepareStatement(""); for (int i = 1; i < 100; i++) { for (int j = 1; j < 10000; j++) { suffix.append("(" + j * i + ", SYSDATE(), " + j * i * Math.random() + ")"); } String sql = prefix + suffix.substring(0, suffix.length() - 1); pst.addBatch(sql); pst.executeBatch(); conn.commit(); suffix = new StringBuffer(); } pst.close(); conn.close(); } catch (SQLException e) { e.printStackTrace(); } Long end = new Date().getTime(); System.out.println("cast : " + (end - begin) / 1000 + " ms");}
测试结果:耗时23ms,效率最高。
public static void insertRelease() { Long begin = new Date().getTime(); String sql = "INSERT INTO tb_big_data (count, create_time, random) VALUES (?, SYSDATE(), ?)"; try { conn.setAutoCommit(false); PreparedStatement pst = conn.prepareStatement(sql); for (int i = 1; i < 100; i++) { for (int j = 1; j < 10000; j++) { pst.setLong(1, j * i); pst.setLong(2, j * i); pst.addBatch(); } pst.executeBatch(); conn.commit(); } pst.close(); conn.close(); } catch (SQLException e) { e.printStackTrace(); } Long end = new Date().getTime(); System.out.println("cast : " + (end - begin) / 1000 + " ms");}
测试结果:耗时111ms,效率较低。
总结:两种方法在原理上相似,但方法一通过动态拼接和批量添加数据,性能更优。建议优先采用方法一。
为了处理大规模数据存储和查询需求,MySQL数据库优化可以从以下几个方面入手:
索引合理设计
LIKE
和FULLTEXT
索引,减少全表扫描。LIMIT
和OFFSET
,减少查询性能损耗。JOIN
操作,减少锁竞争和逻辑开销。分表技术
缓存技术
Memcache
等内存缓存系统,减少数据库读取压力。Squid
代理服务器,缓存静态资源和常用数据。主从分离
减少查询次数
SELECT
语句,减少不必要的列选择和排序操作。EXPLAIN
工具分析慢查询,找出性能瓶颈。分页优化
LIMIT
和OFFSET
,改用OFFSET
和FETCH
的组合方式。使用PreparedStatement
对象,可以有效防止SQL注入
攻击。通过参数占位符传递动态值,避免直接拼接字符串。
示例代码:
String sql = "SELECT * FROM users WHERE username=? AND password=?";PreparedStatement pre = conn.prepareStatement(sql);pre.setString(1, userName);pre.setString(2, password);ResultSet rs = pre.executeQuery();
原理:预编译语句集会自动对参数值进行转义处理,避免特殊字符注入。
如果需要拼接查询语句,可以使用正则表达式替换特殊字符。
防注入函数示例:
public static String TransactSQLInjection(String str) { return str.replaceAll(".*([';]+|(--)+).*", " ");}
使用示例:
String sql = TransactSQLInjection("'或' 1='1'") + " WHERE username='";sql += TransactSQLInjection(userName) + "'";
在Ibatis
框架中,通过参数引用符号#
和$
来控制参数引用方式。
示例:
SELECT * FROM t_user WHERE name LIKE '%#name#%'
注意事项:#
方式会自动转义,$
方式需要谨慎使用,避免注入攻击。
以上优化方法可以有效提升数据库性能和安全性。在实际应用中,建议根据具体场景选择合适的优化方案,并通过持续监控和测试不断优化数据库配置和查询执行计划。
转载地址:http://uxpmz.baihongyu.com/