zoukankan      html  css  js  c++  java
  • 你向 Mysql 数据库插入 100w 条数据用了多久?

    阅读本文大概需要 2 分钟。

    ▌目录

    多线程插入(单表)

    多线程插入(多表)

    预处理 SQL

    多值插入 SQL

    事务( N 条提交一次)

    ▌多线程插入(单表)

    问:为何对同一个表的插入多线程会比单线程快?同一时间对一个表的写操作不应该是独占的吗?

    答:在数据里做插入操作的时候,整体时间的分配是这样的:

    • 链接耗时 (30%)

    • 发送 query 到服务器 (20%)

    • 解析 query (20%)

    • 插入操作 (10% * 词条数目)

    • 插入 index (10% * Index的数目)

    • 关闭链接 (10%)

    从这里可以看出来,真正耗时的不是操作,而是链接,解析的过程。

    MySQL 插入数据在写阶段是独占的,但是插入一条数据仍然需要解析、计算、最后才进行写处理,比如要给每一条记录分配自增 id,校验主键唯一键属性,或者其他一些逻辑处理,都是需要计算的,所以说多线程能够提高效率。

    ▌多线程插入(多表)

    分区分表后使用多线程插入。

    ▌预处理 SQL

    • 普通 SQL,即使用 Statement 接口执行 SQL

    • 预处理 SQL,即使用 PreparedStatement 接口执行 SQL

    使用 PreparedStatement 接口允许数据库预编译 SQL 语句,以后只需传入参数,避免了数据库每次都编译 SQL 语句,因此性能更好。

    String sql = "insert into testdb.tuser (name, remark, createtime, updatetime) values (?, ?, ?, ?)"; for (int i = 0; i < m; i++) {     //从池中获取连接     Connection conn = myBroker.getConnection();     PreparedStatement pstmt = conn.prepareStatement(sql);     for (int k = 0; k < n; k++) {             pstmt.setString(1, RandomToolkit.generateString(12));             pstmt.setString(2, RandomToolkit.generateString(24));             pstmt.setDate(3, new Date(System.currentTimeMillis()));             pstmt.setDate(4, new Date(System.currentTimeMillis()));             //加入批处理             pstmt.addBatch();     }     pstmt.executeBatch();    //执行批处理     pstmt.close();     myBroker.freeConnection(conn); //连接归池 }

     

    ▌多值插入 SQL

    • 普通插入 SQL:INSERT INTO TBL_TEST (id) VALUES(1)

    • 多值插入 SQL:INSERT INTO TBL_TEST (id) VALUES (1), (2), (3)

    使用多值插入 SQL,SQL 语句的总长度减少,即减少了网络 IO,同时也降低了连接次数,数据库一次 SQL 解析,能够插入多条数据。

    ▌事务( N 条提交一次)

    在一个事务中提交大量 INSERT 语句可以提高性能。

    1、将表的存储引擎修改为 myisam

    2、将 sql 拼接成字符串,每 1000 条左右提交事务。

    /// <summary>          /// 执行多条SQL语句,实现数据库事务。          /// </summary>mysql数据库          /// <param name="SQLStringList">多条SQL语句</param>          public void ExecuteSqlTran(List<string> SQLStringList)        {            using (MySqlConnection conn = new MySqlConnection(connectionString))            {                if (DBVariable.flag)                {                    conn.Open();                    MySqlCommand cmd = new MySqlCommand();                    cmd.Connection = conn;                    MySqlTransaction tx = conn.BeginTransaction();                    cmd.Transaction = tx;                    try                    {                        for (int n = 0; n < SQLStringList.Count; n++)                        {                            string strsql = SQLStringList[n].ToString();                            if (strsql.Trim().Length > 1)                            {                                cmd.CommandText = strsql;                                cmd.ExecuteNonQuery();                            }                            //后来加上的                              if (n > 0 && (n % 1000 == 0 || n == SQLStringList.Count - 1))                            {                                tx.Commit();                                tx = conn.BeginTransaction();                            }                        }                        //tx.Commit();//原来一次性提交                      }                    catch (System.Data.SqlClient.SqlException E)                    {                        tx.Rollback();                        throw new Exception(E.Message);                    }                }            }        }

    10w 条数据大概用时 10s!

    ·END·

    程序员的成长之路

    路虽远,行则必至

    本文原发于 同名微信公众号「程序员的成长之路」,回复「1024」你懂得,给个赞呗。

    回复 [ 520 ] 领取程序员最佳学习方式

    回复 [ 256 ] 查看 Java 程序员成长规划

  • 相关阅读:
    2020年. NET Core面试题
    java Context namespace element 'component-scan' and its parser class ComponentScanBeanDefinitionParser are only available on JDK 1.5 and higher 解决方法
    vue 淡入淡出组件
    java http的get、post、post json参数的方法
    vue 父子组件通讯案例
    Vue 生产环境解决跨域问题
    npm run ERR! code ELIFECYCLE
    Android Studio 生成apk 出现 :error_prone_annotations.jar (com.google.errorprone:error) 错误
    记忆解析者芜青【总集】
    LwIP应用开发笔记之十:LwIP带操作系统基本移植
  • 原文地址:https://www.cnblogs.com/gdjk/p/11162838.html
Copyright © 2011-2022 走看看