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

本文共 3577 字,大约阅读时间需要 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/

    你可能感兴趣的文章
    MVC 区域功能
    查看>>
    MySQL FEDERATED 提示
    查看>>
    mysql generic安装_MySQL 5.6 Generic Binary安装与配置_MySQL
    查看>>
    Mysql group by
    查看>>
    MySQL I 有福啦,窗口函数大大提高了取数的效率!
    查看>>
    mysql id自动增长 初始值 Mysql重置auto_increment初始值
    查看>>
    MySQL in 太多过慢的 3 种解决方案
    查看>>
    MySQL InnoDB 三大文件日志,看完秒懂
    查看>>
    Mysql InnoDB 数据更新导致锁表
    查看>>
    Mysql Innodb 锁机制
    查看>>
    MySQL InnoDB中意向锁的作用及原理探
    查看>>
    MySQL InnoDB事务隔离级别与锁机制深入解析
    查看>>
    Mysql InnoDB存储引擎 —— 数据页
    查看>>
    Mysql InnoDB存储引擎中的checkpoint技术
    查看>>
    Mysql InnoDB存储引擎中缓冲池Buffer Pool、Redo Log、Bin Log、Undo Log、Channge Buffer
    查看>>
    MySQL InnoDB引擎的锁机制详解
    查看>>
    Mysql INNODB引擎行锁的3种算法 Record Lock Next-Key Lock Grap Lock
    查看>>
    mysql InnoDB数据存储引擎 的B+树索引原理
    查看>>
    mysql innodb通过使用mvcc来实现可重复读
    查看>>
    mysql insert update 同时执行_MySQL进阶三板斧(三)看清“触发器 (Trigger)”的真实面目...
    查看>>