• batch insert 1 million datas into mysql


    最近尝试插入1百万条数据进db,以mysql为例。

    1. 顺序insert

    先写了个无脑的for循环作为base-line,插1万条耗时1m53s,根本不敢插1百万。

    foreach(var student in students){
        var sql = string.Format("insert into student ... ");
        cmd.CommandText = sql;
        cmd.ExecuteNonQuery();
    }
    

    2. batch insert

    上面这种方式有2个问题:

    1. 在DB端,每次执行都会以1个单独的事务执行;
    2. 在网络上,传输的次数过多、每次传输的效率较差。

    相应的解决方法是:

    1. 在执行前后套BeginTransaction/Commit,保证所有的insert都是在一个大事务里; // 光是这样,1万条只要不到2s,1百万条只要75s

    2. 每1万条数据,拼接成1个大sql,只要不超过 max_allowed_packet=1M 的默认限制即可。具体多少行拼成1条,视字段多少而定,拼成的sql如下。 // 这样的效果也很显著,1百万条只要13s

       insert into table (fields...) values (1...), (2...), ... , (10000...);
      
    3. 可以修改mysql的默认设置,在my.ini里添加如下配置。但试下来效果并不明显,改成10M、每次拼接10万条数据,总时间仍为13s,可以想见这时瓶颈已经不是传输时间了,而是对表的操作。

       [mysqld]
       max_allowed_packet=10M // 1M default
      

    3. MultiThread insert

    试了下在方法2(batch insert)的基础上,采用4个线程同时insert,1百万条数据耗时16s,反而慢了。估计时间都耗在创建connection、单表加锁上了。在这个场景下,MultiThread对解决问题无益。

    4. ibdata1无限增长的问题

    每个Student对象大约是50字节,每insert1百万大约是50M。多insert几次后执行删除操作,发现ibdata1文件反而接近翻倍的增长。解决方法如下:

    • 关闭mysqld服务
    • 删除ibdata1、ib_logfile0/1、对应的database文件夹
    • my.ini的[mysqld]里添加 innodb_file_per_table=1 ,这样就会给每个表创建一个单独的ibd文件

    最后是Demo的源码,如果你有更快的方法,不妨留言~

  • 相关阅读:
    jquery.cookie.js
    CSS实现三角形
    关于seajs模块化的搭建
    浏览器版本类型及版本
    js || 和 &&
    bootstraps字体图标无法显示
    Thymeleaf的一些操作
    C语言I博客作业02
    C语言I博客作业03
    20169306《网络攻击与防范》第二周学习总结
  • 原文地址:https://www.cnblogs.com/AlexanderYao/p/5330634.html
Copyright © 2020-2023  润新知