科帮网-Java论坛、Java社区、JavaWeb毕业设计

登录/注册
您现在的位置:论坛 资料库 数据库开发 > MySQL大数据量下优化插入
总共48085条微博

动态微博

查看: 1994|回复: 3

MySQL大数据量下优化插入

[复制链接]
admin    

1244

主题

544

听众

1万

金钱

管理员

  • TA的每日心情

    2021-2-2 11:21
  • 签到天数: 36 天

    [LV.5]常住居民I

    管理员

    跳转到指定楼层
    楼主
    发表于 2015-03-12 08:45:56 |只看该作者 |倒序浏览
    不管是日常业务数据处理中,还是数据库的导入导出,都可能遇到需要处理大量数据的插入。插入的方式和数据库引擎都会对插入速度造成影响,这篇文章旨在从理论和实践上对各种方法进行分析和比较,方便以后应用中插入方法的选择。

    插入分析

    MySQL中插入一个记录需要的时间由下列因素组成,其中的数字表示大约比例:
    连接:(3)
    发送查询给服务器:(2)
    分析查询:(2)
    插入记录:(1x记录大小)
    插入索引:(1x索引)
    关闭:(1)

    如果我们每插入一条都执行一个SQL语句,那么我们需要执行除了连接和关闭之外的所有步骤N次,这样是非常耗时的,优化的方式有一下几种:
    1.在每个insert语句中写入多行,批量插入
    2.将所有查询语句写入事务中
    3.利用Load Data导入数据

    每种方式执行的性能如下。

    Innodb引擎

    InnoDB 给 MySQL 提供了具有事务(commit)、回滚(rollback)和崩溃修复能力(crash recovery capabilities)的事务安全(transaction-safe (ACID compliant))型表。InnoDB 提供了行锁(locking on row level)以及外键约束(FOREIGN KEY constraints)。

    InnoDB 的设计目标是处理大容量数据库系统,它的 CPU 利用率是其它基于磁盘的关系数据库引擎所不能比的。在技术上,InnoDB 是一套放在 MySQL 后台的完整数据库系统,InnoDB 在主内存中建立其专用的缓冲池用于高速缓冲数据和索引。

    测试环境

    Macbook Air 12mid apache2.2.26 php5.5.10 mysql5.6.16

    总数100W条数据

    插入完后数据库大小38.6MB(无索引),46.8(有索引)
    无索引单条插入 总耗时:229s 峰值内存:246KB
    有索引单条插入 总耗时:242s 峰值内存:246KB
    无索引批量插入 总耗时:10s 峰值内存:8643KB
    有索引批量插入 总耗时:16s 峰值内存:8643KB
    无索引事务插入 总耗时:78s 峰值内存:246KB
    有索引事务插入 总耗时:82s 峰值内存:246KB
    无索引Load Data插入 总耗时:12s 峰值内存:246KB
    有索引Load Data插入 总耗时:11s 峰值内存:246KB

    MyIASM引擎

    MyISAM 是MySQL缺省存贮引擎。设计简单,支持全文搜索。

    测试环境

    Macbook Air 12mid apache2.2.26 php5.5.10 mysql5.6.16

    总数100W条数据

    插入完后数据库大小19.1MB(无索引),38.6(有索引)
    无索引单条插入 总耗时:82s 峰值内存:246KB
    有索引单条插入 总耗时:86s 峰值内存:246KB
    无索引批量插入 总耗时:3s 峰值内存:8643KB
    有索引批量插入 总耗时:7s 峰值内存:8643KB
    无索引Load Data插入 总耗时:6s 峰值内存:246KB
    有索引Load Data插入 总耗时:8s 峰值内存:246KB

    总结

    我测试的数据量不是很大,不过可以大概了解这几种插入方式对于速度的影响,最快的必然是Load Data方式。这种方式相对比较麻烦,因为涉及到了写文件,但是可以兼顾内存和速度。



    科帮网-Java论坛、Java社区、JavaWeb毕业设计 1、本主题所有言论和图片纯属会员个人意见,与本社区立场无关
    2、本站所有主题由该帖子作者发表,该帖子作者与科帮网-Java论坛、Java社区、JavaWeb毕业设计享有帖子相关版权
    3、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者和科帮网-Java论坛、Java社区、JavaWeb毕业设计的同意
    4、帖子作者须承担一切因本文发表而直接或间接导致的民事或刑事法律责任
    5、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责
    6、如本帖侵犯到任何版权问题,请立即告知本站,本站将及时予与删除并致以最深的歉意
    7、科帮网-Java论坛、Java社区、JavaWeb毕业设计管理员和版主有权不事先通知发贴者而删除本文


    JAVA爱好者①群:JAVA爱好者① JAVA爱好者②群:JAVA爱好者② JAVA爱好者③ : JAVA爱好者③

    admin    

    1244

    主题

    544

    听众

    1万

    金钱

    管理员

  • TA的每日心情

    2021-2-2 11:21
  • 签到天数: 36 天

    [LV.5]常住居民I

    管理员

    沙发
    发表于 2015-03-12 09:05:15 |只看该作者
    1. <?php
    2. $dsn = 'mysql:host=localhost;dbname=test';
    3. $db = new PDO($dsn,'root','',array(PDO::ATTR_PERSISTENT => true));
    4. //删除上次的插入数据
    5. $db->query('delete from `test`');
    6. //开始计时
    7. $start_time = time();
    8. $sum = 1000000;
    9. // 测试选项
    10. $num = 1;

    11. if ($num == 1){
    12.     // 单条插入
    13.     for($i = 0; $i < $sum; $i++){
    14.         $db->query("insert into `test` (`id`,`name`) values ($i,'tsetssdf')");
    15.     }
    16. } elseif ($num == 2) {
    17.     // 批量插入,为了不超过max_allowed_packet,选择每10万插入一次
    18.     for ($i = 0; $i < $sum; $i++) {
    19.         if ($i == $sum - 1) { //最后一次
    20.             if ($i%100000 == 0){
    21.                 $values = "($i, 'testtest')";
    22.                 $db->query("insert into `test` (`id`, `name`) values $values");
    23.             } else {
    24.                 $values .= ",($i, 'testtest')";
    25.                 $db->query("insert into `test` (`id`, `name`) values $values");
    26.             }
    27.             break;
    28.         }
    29.         if ($i%100000 == 0) { //平常只有在这个情况下才插入
    30.             if ($i == 0){
    31.                 $values = "($i, 'testtest')";
    32.             } else {
    33.                 $db->query("insert into `test` (`id`, `name`) values $values");
    34.                 $values = "($i, 'testtest')";
    35.             }
    36.         } else {
    37.             $values .= ",($i, 'testtest')";   
    38.         }
    39.     }
    40. } elseif ($num == 3) {
    41.     // 事务插入
    42.     $db->beginTransaction();
    43.     for($i = 0; $i < $sum; $i++){
    44.         $db->query("insert into `test` (`id`,`name`) values ($i,'tsetssdf')");
    45.     }
    46.     $db->commit();
    47. } elseif ($num == 4) {
    48.     // 文件load data
    49.     $filename = dirname(__FILE__).'/test.sql';
    50.     $fp = fopen($filename, 'w');
    51.     for($i = 0; $i < $sum; $i++){
    52.         fputs($fp, "$i,'testtest'\r\n");   
    53.     }
    54.     $db->exec("load data infile '$filename' into table test fields terminated by ','");
    55. }

    56. $end_time = time();
    57. echo "总耗时", ($end_time - $start_time), "秒\n";
    58. echo "峰值内存", round(memory_get_peak_usage()/1000), "KB\n";

    59. ?>
    复制代码


    回复

    使用道具 举报

    3

    主题

    0

    听众

    384

    金钱

    三袋弟子

    该用户从未签到

    板凳
    发表于 2015-04-01 18:11:06 |只看该作者
    感谢分享,学习学习。。。。。。
    回复

    使用道具 举报

    13

    主题

    9

    听众

    4517

    金钱

    八袋长老

    该用户从未签到

    地板
    发表于 2015-10-25 21:45:58 |只看该作者
    感谢分享,学习学习。。。。。。
    回复

    使用道具 举报

    快速回复
    您需要登录后才可以回帖 登录 | 立即注册

       

    发布主题 快速回复 返回列表 联系我们 官方QQ群 科帮网手机客户端
    快速回复 返回顶部 返回列表