博客
关于我
面试必问的数据库-4.1:sql-优化
阅读量:658 次
发布时间:2019-03-15

本文共 3525 字,大约阅读时间需要 11 分钟。

关于批量插入数据(100万)数据优化

一、批量插入数据优化思路

在处理大规模数据插入任务时,直接使用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亿级数据优化

    为了处理大规模数据存储和查询需求,MySQL数据库优化可以从以下几个方面入手:

    一、数据库设计优化

  • 索引合理设计

    • 避免使用LIKEFULLTEXT索引,减少全表扫描。
    • 避免使用LIMITOFFSET,减少查询性能损耗。
    • 避免复杂的JOIN操作,减少锁竞争和逻辑开销。
  • 分表技术

    • 垂直分表:将部分字段分离到独立表中,优化查询性能。
    • 水平分表:根据主键值对表记录进行分布式存储,减少锁冲突。
  • 二、服务器和存储优化

  • 缓存技术

    • 使用Memcache等内存缓存系统,减少数据库读取压力。
    • 部署Squid代理服务器,缓存静态资源和常用数据。
  • 主从分离

    • 在读写压力大的场景下,部署主从数据库集群,分离读写操作。
  • 三、查询优化

  • 减少查询次数

    • 优化SELECT语句,减少不必要的列选择和排序操作。
    • 使用EXPLAIN工具分析慢查询,找出性能瓶颈。
  • 分页优化

    • 避免使用LIMITOFFSET,改用OFFSETFETCH的组合方式。
    • 只缓存前后几页数据,减少后续查询压力。

  • 防止SQL注入

    一、预编译语句集

    使用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防注入

    Ibatis框架中,通过参数引用符号#$来控制参数引用方式。

    示例:

    SELECT * FROM t_user WHERE name LIKE '%#name#%'

    注意事项#方式会自动转义,$方式需要谨慎使用,避免注入攻击。

    四、综合防护措施

  • 前端校验:对输入数据进行参数校验,排除恶意输入。
  • 数据库权限控制:严格控制数据库用户权限,减少潜在风险。
  • 定期备份:定期备份数据库,确保数据安全。

  • 以上优化方法可以有效提升数据库性能和安全性。在实际应用中,建议根据具体场景选择合适的优化方案,并通过持续监控和测试不断优化数据库配置和查询执行计划。

    转载地址:http://uxpmz.baihongyu.com/

    你可能感兴趣的文章
    mysql-递归查询(二)
    查看>>
    MySQL5.1安装
    查看>>
    mysql5.5和5.6版本间的坑
    查看>>
    mysql5.5最简安装教程
    查看>>
    mysql5.6 TIME,DATETIME,TIMESTAMP
    查看>>
    mysql5.6.21重置数据库的root密码
    查看>>
    Mysql5.6主从复制-基于binlog
    查看>>
    MySQL5.6忘记root密码(win平台)
    查看>>
    MySQL5.6的Linux安装shell脚本之二进制安装(一)
    查看>>
    MySQL5.6的zip包安装教程
    查看>>
    mysql5.7 for windows_MySQL 5.7 for Windows 解压缩版配置安装
    查看>>
    Webpack 基本环境搭建
    查看>>
    mysql5.7 安装版 表不能输入汉字解决方案
    查看>>
    MySQL5.7.18主从复制搭建(一主一从)
    查看>>
    MySQL5.7.19-win64安装启动
    查看>>
    mysql5.7.19安装图解_mysql5.7.19 winx64解压缩版安装配置教程
    查看>>
    MySQL5.7.37windows解压版的安装使用
    查看>>
    mysql5.7免费下载地址
    查看>>
    mysql5.7命令总结
    查看>>
    mysql5.7安装
    查看>>