资讯专栏INFORMATION COLUMN

Mysql replace 与 insert on duplicate效率分析

Muninn / 1512人阅读

摘要:第一种方式不说了,和这两种方式,哪中效率更高一些呢,毕竟,我们的执行,追求的就是高效。数据库菜鸟一个,所知有限,如有纰漏,还请指教

导读

我们在向数据库里批量插入数据的时候,会遇到要将原有主键或者unique索引所在记录更新的情况,而如果没有主键或者unique索引冲突的时候,直接执行插入操作。

这种情况下,有三种方式执行:

直接

直接每条select, 判断, 然后insert,毫无疑问,这是最笨的方法了,不断的查询判断,有主键或索引冲突,执行update,否则执行insert. 数据量稍微大一点这种方式就不行了。

稍微高级一些的方式。

replace

这是mysql自身的一个语法,使用 replace 的时候。其语法为:

replace into tablename (f1, f2, f3) values(vf1, vf2, vf3),(vvf1, vvf2, vvf3)

这中语法会自动查询主键或索引冲突,如有冲突,他会先删除原有的数据记录,然后执行插入新的数据。

insert on duplicate key.

这也是一种方式,mysql的insert操作中也给了一种方式,语法如下:

INSERT INTO table (a,b,c) VALUES (1,2,3)
  ON DUPLICATE KEY UPDATE c=c+1;

在insert时判断是否已有主键或索引重复,如果有,一句update后面的表达式执行更新,否则,执行插入。

第一种方式不说了,replace和insert on duplicate key这两种方式,哪中效率更高一些呢,毕竟,我们的执行sql,追求的就是高效。

分析

在最终实践结果中,得到接过如下:
在数据库数据量很少的时候, 这两种方式都很快,无论是直接的插入还是有冲突时的更新,都不错,但在数据库表的内容数量比较大(如百万级)的时候,两种方式就不太一样了,

首先是直接的插入操作,两种的插入效率都略低, 比如直接向表里插入1000条数据(百万级的表(innodb引擎)),二者都差不多需要5,6甚至十几秒。究其原因,我的主机性能是一方面,但在向大数据表批量插入数据的时候,每次的插入都要维护索引的, 索引固然可以提高查询的效率,但在更新表尤其是大表的时候,索引就成了一个不得不考虑的问题了。

其次是更新表,这里的更新的时候是带主键值的(因为我是从另一个表获取数据再插入,要求主键不能变) 同样直接更新1000条数据, replace的操作要比insert on duplicate的操作低太多太多, 当insert瞬间完成(感觉)的时候,replace要7,8s, replace慢的原因我是知道的,在更新数据的时候,要先删除旧的,然后插入新的,在这个过程中,还要重新维护索引,所以速度慢,但为何insert on duplicate的更新却那么快呢。 在向老大请教后,终于知道,insert on duplicate 的更新操作虽然也会更新数据,但其对主键的索引却不会有改变,也就是说,insert on duplicate 更新对主键索引没有影响.因此对索引的维护成本就低了一些(如果更新的字段不包括主键,那就要另说了)。

题外话:

在向数据量大的表里批量插入更新数据的时候,随着插入的数量越来越多,会导致越来越慢,这种情况下,因为我们用的innodb表,可以开启事务, 每次批量执行一批数据更新后提交, 再重新开事务处理下批数据,这样会有效增加效率

还有说明一下: 当我们执行数据库的插入和更新操作很慢的时候,不仅仅是语句,主机性能也很重要, 比如内存和cpu, 如果是虚拟机要相应适当调整, 如果在各种优化了之后效率还是很低, 但cpu和内存的占用却不高,那么就很可能是磁盘的IO性能了,这也会导致数据的更新速度慢。

PS: 数据库菜鸟一个, 所知有限, 如有纰漏, 还请指教

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/46437.html

相关文章

  • TiDB 源码阅读系列文章(十六)INSERT 语句详解

    摘要:在之前的一篇文章源码阅读系列文章四语句概览中,我们已经介绍了语句的大体流程。语句自身都可以连接一个语句作为待插入数据的输入,因此,其又受到了来自的影响关于的部分详见相关的源码阅读文章七基于规则的优化和八基于代价的优化。 在之前的一篇文章 《TiDB 源码阅读系列文章(四)INSERT 语句概览》 中,我们已经介绍了 INSERT 语句的大体流程。为什么需要为 INSERT 单独再写一篇...

    elliott_hu 评论0 收藏0
  • TiDB 源码阅读系列文章(十六)INSERT 语句详解

    摘要:在之前的一篇文章源码阅读系列文章四语句概览中,我们已经介绍了语句的大体流程。语句自身都可以连接一个语句作为待插入数据的输入,因此,其又受到了来自的影响关于的部分详见相关的源码阅读文章七基于规则的优化和八基于代价的优化。 在之前的一篇文章 《TiDB 源码阅读系列文章(四)INSERT 语句概览》 中,我们已经介绍了 INSERT 语句的大体流程。为什么需要为 INSERT 单独再写一篇...

    Null 评论0 收藏0
  • mysql自增id超大问题查询

    摘要:下图中的值对应的是自增主键,用作为唯一索引后来过了很久,小给小指了个方向,小开始怀疑自己的插入更新语句了,查了许久,果然是这里除了问题。解决方案将设置为肯定可以解决问题,但这样的话,插入的并发性可能会受很大影响,因此小自己想着也不会同意。 引言 小A正在balabala写代码呢,DBA小B突然发来了一条消息,快看看你的用户特定信息表T,里面的主键,也就是自增id,都到16亿了,这才多久...

    meislzhua 评论0 收藏0
  • mysql自增id超大问题查询

    摘要:下图中的值对应的是自增主键,用作为唯一索引后来过了很久,小给小指了个方向,小开始怀疑自己的插入更新语句了,查了许久,果然是这里除了问题。解决方案将设置为肯定可以解决问题,但这样的话,插入的并发性可能会受很大影响,因此小自己想着也不会同意。 引言 小A正在balabala写代码呢,DBA小B突然发来了一条消息,快看看你的用户特定信息表T,里面的主键,也就是自增id,都到16亿了,这才多久...

    dmlllll 评论0 收藏0
  • MySql避免重复插入记录方法(ignore,Replace,ON DUPLICATE KEY UP

    摘要:返回值语句会返回一个数,来指示受影响的行的数目。换句话说,如果没有发生重复关键字冲突,则子句中的可以引用被插入的的值。本函数特别适用于多行插入。只关注主键对应记录是不存在,无则添加,有则忽略。 案一:使用ignore关键字 如果是用主键primary或者唯一索引unique区分了记录的唯一性,避免重复插入记录可以使用: INSERT IGNORE INTO table_name (e...

    Gu_Yan 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<