详解MySQL批量SQL插入的性能优化


本文摘自PHP中文网,作者coldplay.xixi,侵删。

mysql教程栏目介绍批量SQL插入

推荐(免费):mysql教程

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

一条SQL语句插入多条数据

1

2

3

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语句进行导入。
b641447c748b91105ac52ce0f1d9ff9.png

在事务中进行插入处理

1

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内部都会建立一个事务,在事务内才进行真正插入处理操作。
  • 通过使用事务减少创建事务的消耗,所有插入都在执行后才进行提交操作

测试对比数据,分笔试不适用事务和使用事务操作

38679a3d3102f32db7e43b1a7629fa9.png

数据有序插入

数据有序的插入是插入记录在主键上的有序排序

1

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

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进行分裂合并等处理,会消耗比较多计算资源,并且插入记录的索引定位效率会下降,数据量较大时会有频繁的磁盘操作。

测试对比数据,随机数据与顺序数据的性能对比

24d56e0846e0bd4c3eb2d58b5c26e80.png

先删除索引,插入完成后重建索引

性能综合测试

e868db118874175bc7ad1c69283aff2.png

  • 合并数据+事务的方法在较少数据量时,性能提升很明显,数据量较大时,性能急剧下降,这是由于此时数据量超过了innodb_buffer的容量,每次定位索引涉及较多的磁盘读写操作,性能下降较快。
  • 合并数据+事务+有序的方法在数据量达到千万级以上表现依然良好,在数据量较大时,有序数据索引定位较为方便,不需要频繁对磁盘进行读写操作,可以维持较高

注意事项

  • SQL语句是有长度限制,在进行数据合并在同一SQL中务必不能超过SQL长度限制,通过max_allowed_packet配置可以修改,默认1M,测试时可以修改为8M

  • 事务需要控制大小,事物太大可能影响执行的效率。MySQL有innodb_log_buffer_size配置项,超过这个值会把innodb的数据刷到磁盘中,这时,效率会有所下降。所以较好的做法是,在数据达到这个值前执行事务提交。

以上就是详解MySQL批量SQL插入的性能优化的详细内容,更多文章请关注木庄网络博客

相关阅读 >>

怎么用cmd进入mysql

mysql分区表管理命令汇总

mysql中表锁和行锁有什么区别

mysql存储过程 游标 错误处理的示例代码

mysql表如何设置读写

安装mysql后没有看到服务怎么办?

redhat下mysql的基本使用方法分享

上篇 mysql 语句加锁分析

mysql查询优化详解

mysql是什么

更多相关阅读请进入《mysql》频道 >>


数据库系统概念 第6版
书籍

数据库系统概念 第6版

机械工业出版社

本书主要讲述了数据模型、基于对象的数据库和XML、数据存储和查询、事务管理、体系结构等方面的内容。



打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在

评论

管理员已关闭评论功能...