对于一些数据量较大的系统,数据库面临的问题除了查询效率低下,还有就是数据入库时间长。特别像报表系统,每天花费在数据导入上的时间可能会长达几个小时或十几个小时之久。因此,优化数据库插入性能是很有意义的。
经过对MySQL innodb的一些性能测试,发现一些可以提高insert效率的方法,供大家参考参考。

1. 一条SQL语句插入多条数据。
常用的插入语句如:

 
1
2
3
4
INSERT INTO `insert_table` (`datetime`, `uid`, `content`, `type`)
    VALUES ('0', 'userid_0', 'content_0', 0);
INSERT INTO `insert_table` (`datetime`, `uid`, `content`, `type`)
    VALUES ('1', 'userid_1', 'content_1', 1);

修改成:

 
1
2
INSERT INTO `insert_table` (`datetime`, `uid`, `content`, `type`)
    VALUES ('0', 'userid_0', 'content_0', 0), ('1', 'userid_1', 'content_1', 1);

修改后的插入操作能够提高程序的插入效率。这里第二种SQL执行效率高的主要原因是合并后日志量(MySQL的binlog和innodb的事务让日志)减少了,降低日志刷盘的数据量和频率,从而提高效率。通过合并SQL语句,同时也能减少SQL语句解析的次数,减少网络传输的IO。
这里提供一些测试对比数据,分别是进行单条数据的导入与转化成一条SQL语句进行导入,分别测试1百、1千、1万条数据记录。

2. 在事务中进行插入处理。
把插入修改成:

 
1
2
3
4
5
6
7
START TRANSACTION;
INSERT INTO `insert_table` (`datetime`, `uid`, `content`, `type`)
    VALUES ('0', 'userid_0', 'content_0', 0);
INSERT INTO `insert_table` (`datetime`, `uid`, `content`, `type`)
    VALUES ('1', 'userid_1', 'content_1', 1);
...
COMMIT;

使用事务可以提高数据的插入效率,这是因为进行一个INSERT操作时,MySQL内部会建立一个事务,在事务内才进行真正插入处理操作。通过使用事务可以减少创建事务的消耗,所有插入都在执行后才进行提交操作。
这里也提供了测试对比,分别是不使用事务与使用事务在记录数为1百、1千、1万的情况。

3. 数据有序插入。
数据有序的插入是指插入记录在主键上是有序排列,例如datetime是记录的主键:

 
1
2
3
4
5
6
INSERT INTO `insert_table` (`datetime`, `uid`, `content`, `type`)
    VALUES ('1', 'userid_1', 'content_1', 1);
INSERT INTO `insert_table` (`datetime`, `uid`, `content`, `type`)
    VALUES ('0', 'userid_0', 'content_0', 0);
INSERT INTO `insert_table` (`datetime`, `uid`, `content`, `type`)
    VALUES ('2', 'userid_2', 'content_2',2);

修改成:

 
1
2
3
4
5
6
INSERT INTO `insert_table` (`datetime`, `uid`, `content`, `type`)
    VALUES ('0', 'userid_0', 'content_0', 0);
INSERT INTO `insert_table` (`datetime`, `uid`, `content`, `type`)
    VALUES ('1', 'userid_1', 'content_1', 1);
INSERT INTO `insert_table` (`datetime`, `uid`, `content`, `type`)
    VALUES ('2', 'userid_2', 'content_2',2);

由于数据库插入时,需要维护索引数据,无序的记录会增大维护索引的成本。我们可以参照innodb使用的B+tree索引,如果每次插入记录都在索引的最后面,索引的定位效率很高,并且对索引调整较小;如果插入的记录在索引中间,需要B+tree进行分裂合并等处理,会消耗比较多计算资源,并且插入记录的索引定位效率会下降,数据量较大时会有频繁的磁盘操作。
下面提供随机数据与顺序数据的性能对比,分别是记录为1百、1千、1万、10万、100万。

从测试结果来看,该优化方法的性能有所提高,但是提高并不是很明显。

性能综合测试:
这里提供了同时使用上面三种方法进行INSERT效率优化的测试。

从测试结果可以看到,合并数据+事务的方法在较小数据量时,性能提高是很明显的,数据量较大时(1千万以上),性能会急剧下降,这是由于此时数据量超过了innodb_buffer的容量,每次定位索引涉及较多的磁盘读写操作,性能下降较快。而使用合并数据+事务+有序数据的方式在数据量达到千万级以上表现依旧是良好,在数据量较大时,有序数据索引定位较为方便,不需要频繁对磁盘进行读写操作,所以可以维持较高的性能。

注意事项:
1. SQL语句是有长度限制,在进行数据合并在同一SQL中务必不能超过SQL长度限制,通过max_allowed_packet配置可以修改,默认是1M,测试时修改为8M。
2. 事务需要控制大小,事务太大可能会影响执行的效率。MySQL有innodb_log_buffer_size配置项,超过这个值会把innodb的数据刷到磁盘中,这时,效率会有所下降。所以比较好的做法是,在数据达到这个这个值前进行事务提交。

转自:http://tech.uc.cn/?p=634

MySQL批量SQL插入性能优化的更多相关文章

  1. 【转】MySQL批量SQL插入各种性能优化

    原文:http://mp.weixin.qq.com/s?__biz=MzA5MzY4NTQwMA==&mid=403182899&idx=1&sn=74edf28b0bd29 ...

  2. MySQL批量SQL插入各种性能优化

    对于一些数据量较大的系统.数据库面临的问题除了查询效率低下,还有就是数据入库时间长.特别像报表系统,每天花费在数据导入上的时间可能会长达几个小时或十几个小时之久.因此.优化数据库插入性能是非常有意义的 ...

  3. mysql批量sql插入优化

    对于一些数据量较大的系统,数据库面临的问题除了查询效率低下,还有就是数据入库时间长.特别像报表系统,每天花费在数据导入上的时间可能会长达几个小时或十几个小时之久.因此,优化数据库插入性能是很有意义的. ...

  4. mysql批量更新数据(性能优化) 第一种方式

    首先想到的是,一条一条更新的速度太慢了,然后就想批量更新,一次更新N条数据.实践是检验真理的唯一标准,不一会儿,代码就敲完了,重新试了一下,效果依旧不理想.啊哦,真是要崩溃!后面又想到了利用异步,我一 ...

  5. mysql批量更新数据(性能优化)--第二种方式

    Spring+Mybatis 手动控制事务 参考: https://blog.csdn.net/qq_41750175/article/details/87621170 public boolean ...

  6. MySQL插入性能优化

    目录 MySQL插入性能优化 代码优化 values 多个 一个事务 插入字段尽量少,尽量用默认值 关闭 unique_checks bulk_insert_buffer_size 配置优化 inno ...

  7. 52 条 SQL 语句性能优化策略,建议收藏

    本文会提到 52 条 SQL 语句性能优化策略. 1.对查询进行优化,应尽量避免全表扫描,首先应考虑在where及order by涉及的列上建立索引. 2.应尽量避免在where子句中对字段进行nul ...

  8. SQL SERVER性能优化综述

    SQL SERVER性能优化综述 一个系统的性能的提高,不单单是试运行或者维护阶段的性能调优的任务,也不单单是开发阶段的事情,而是在整个软件生命周期都需要注意,进行有效工作才能达到的.所以我希望按照软 ...

  9. Mybatis动态sql及性能优化-3

    内容简介 1.回顾 2.动态sql 3.性能优化 懒加载机制 一级缓存 二级缓存 一.回顾 1.config文件常用标签 properties标签:引入外部properties文件资源. settin ...

随机推荐

  1. Leetcode 257 Binary Tree Paths 二叉树 DFS

    找到所有根到叶子的路径 深度优先搜索(DFS), 即二叉树的先序遍历. /** * Definition for a binary tree node. * struct TreeNode { * i ...

  2. hdu 1087 动态规划之最长上升子序列

    http://acm.hdu.edu.cn/showproblem.php?pid=1087 Online Judge Online Exercise Online Teaching Online C ...

  3. 运行(WIN+R)中能使用的命令:ms-settings:,shell:,cpl,mmc...

    ms-settings: --- DESC --- --- CMD --- Battery Saver ms-settings:batterysaver Battery Saver Settings ...

  4. svn 403 Forbidden

    用svn client的时候出现这么一个问题,客户端能正常check out,但是在check in(commit,mkdir等)的时候出错了: Server sent unexpected retu ...

  5. Windows Server 2008 R2 备份和恢复 (转)

    Windows Server Backup : 1.安装Windows Server Backup的方法: 通过"服务器管理器"中的"添加功能"向导进行安装. ...

  6. 【干货】个人工作文档节选:XAML MVVM 框架易用性细节优化Tips

    1    易用性细节优化 1.1 代码片段 在ViewModel内,会有大量重复性的在Property set中激发 INotifyPropertyChanged.PropertyChanged 事件 ...

  7. MySQL执行计划中key_len详解

    (1).索引字段的附加信息:可以分为变长和定长数据类型讨论,当索引字段为定长数据类型,比如char,int,datetime,需要有是否为空的标记,这个标记需要占用1个字节:对于变长数据类型,比如:v ...

  8. nodejs express 框架解密4-路由

    本文档是基于express3.4.6 express 的路由是自己去实现的,没有使用connect中的路由中间件模块. 1.在如何创建一个app那篇中,我们提到了路由, //router //路由 t ...

  9. 判断big endian和little endian的方法

    http://blog.sina.com.cn/s/blog_6ab0b9a80101awzr.html   不同体系的CPU在内存中的数据存储往往存在着差异.例如,Intel的x86系列处理器将低序 ...

  10. 1.C#中几个简单的内置Attribute

    阅读目录 一:Obsolete 二:Conditional 一:Obsolete      这个内置属性是说这个方法废弃了不可用,它有两个参数,第一个参数message是说废弃的原因,第二个参数err ...