前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >关于MySQL中insert ignore,insert on duplicate和replace into,你可能没想过区别

关于MySQL中insert ignore,insert on duplicate和replace into,你可能没想过区别

作者头像
jeanron100
发布2020-02-13 08:41:45
1.5K0
发布2020-02-13 08:41:45
举报
文章被收录于专栏:杨建荣的学习笔记

读完需要10分钟

速读仅需5分钟

在数据流转中或者日常的数据操作中,势必会有数据写入的过程,如果把一些数据写入一张数据库表中,如果写入量有100万,而重复的数据有90万,那么如何让这10%的数据能够更高更高效的写入。

在MySQL方向提供了Insert ignore into,insert into on duplicate,replace into这几种写入的方式,看起来好像都差不多,但是实际上在一些场景下的差异还比较大,如果使用不当,恰恰是性能的瓶颈。

整体上我分为两个大的部分,会分别测试这三种数据写入场景。

第一部分基于id,name的数据列,其中id为主键,自增

第二部分基于id,xid,name的数据列,其中id为主键,自增,xid为唯一性索引

至于为什么要这么分,我们可以先看结果再做讨论。

1

基于id,name的数据列,其中id为主键,自增

为了三种测试场景的基准对等,数据初始化会按照如下的三种方式来进行。

数据初始化

create table test_data(id int primary key auto_increment,name varchar(30)) engine=innodb;

insert into test_data values(1,'aa'),(2,'bb'),(3,'cc');

show create table test_data\G Table: test_dataCreate Table: CREATE TABLE `test_data` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(30) DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8

insert ignore

insert ignore into test_data values(1,'aa');Query OK, 0 rows affected, 1 warning (0.00 sec)>>show warnings;+---------+------+---------------------------------------+| Level | Code | Message |+---------+------+---------------------------------------+| Warning | 1062 | Duplicate entry '1' for key 'PRIMARY' |+---------+------+---------------------------------------+1 row in set (0.00 sec)

show create table test_data\G Table: test_dataCreate Table: CREATE TABLE `test_data` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(30) DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8

insert ignore into test_data values(1,'aaa');Query OK, 0 rows affected, 1 warning (0.01 sec)>>show warnings;+---------+------+---------------------------------------+| Level | Code | Message |+---------+------+---------------------------------------+| Warning | 1062 | Duplicate entry '1' for key 'PRIMARY' |+---------+------+---------------------------------------+1 row in set (0.00 sec)

insert ignore into test_data values(4,'cc');Query OK, 1 row affected (0.01 sec)

select * from test_data;+----+------+| id | name |+----+------+| 1 | aa || 2 | bb || 3 | cc || 4 | cc |+----+------+4 rows in set (0.00 sec)

replace into场景

>>replace into test_data values(1,'aa');Query OK, 1 row affected (0.01 sec)

show create table test_data\G Table: test_dataCreate Table: CREATE TABLE `test_data` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(30) DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8

replace into test_data values(1,'aaa');Query OK, 2 rows affected (0.00 sec)

replace into test_data values(4,'cc');Query OK, 1 row affected (0.00 sec)

select *from test_data;+----+------+| id | name |+----+------+| 1 | aaa || 2 | bb || 3 | cc || 4 | cc |+----+------+4 rows in set (0.00 sec)

insert into on duplicate场景

insert into test_data values(1,'aa') on duplicate key update id=id;Query OK, 0 rows affected (0.00 sec)insert into test_data values(1,'aa') on duplicate key update id=id, name=name;Query OK, 0 rows affected (0.00 sec)

show create table test_data\G Table: test_dataCreate Table: CREATE TABLE `test_data` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(30) DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8

insert into test_data values(1,'aaa') on duplicate key update id=id;Query OK, 0 rows affected (0.00 sec)insert into test_data values(1,'aaa') on duplicate key update id=id,name=name;Query OK, 0 rows affected (0.00 sec)

insert into test_data values(4,'cc') on duplicate key update id=id;Query OK, 1 row affected (0.01 sec)insert into test_data values(4,'ccc') on duplicate key update id=id, name=name;Query OK, 0 rows affected (0.00 sec)

select * from test_data;+----+------+| id | name |+----+------+| 1 | aa || 2 | bb || 3 | cc || 4 | cc |+----+------+4 rows in set (0.00 sec)

小结:这三种场景的结果从自增列的处理方式来看是完全对等的,但是对于重复数据的处理方式还是存在差异。

相比而言,replace into和insert into on duplicate存在本质的区别,replace into是覆盖写,即删除原来的,写入新的。不光是主键列,其他列也会保持一致

insert into on duplicate则可以根据自己的需求来定制重复数据的处理策略,不会主动改变数据。

insert ignore into 在这种场景下最为通用,而且对于数据的侵入性最小。

所以如果要保证源端的数据基于主键完全一致,不管非主键列的数据是否一致,都需要完全覆盖,选择replace into是一种好的方法。

否则采用insert into on duplcate或者insert ignore into

2

基于id,xid,name的数据列,其中id为主键,自增,xid为唯一性索引

为了三种测试场景的基准对等,数据初始化会按照如下的三种方式来进行。

数据初始化

create table test_data(id int primary key auto_increment,xid int unique key,name varchar(30)) engine=innodb;

insert into test_data(xid,name) values(1,'aa'),(2,'bb'),(3,'cc');Query OK, 3 rows affected (0.01 sec)Records: 3 Duplicates: 0 Warnings: 0

select *from test_data;+----+------+------+| id | xid | name |+----+------+------+| 1 | 1 | aa || 2 | 2 | bb || 3 | 3 | cc |+----+------+------+3 rows in set (0.00 sec)

insert ignore into

insert ignore into test_data(xid,name) values(1,'aa');Query OK, 0 rows affected, 1 warning

CREATE TABLE `test_data` ( `id` int(11) NOT NULL AUTO_INCREMENT, `xid` int(11) DEFAULT NULL, `name` varchar(30) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `xid` (`xid`)) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8

insert ignore into test_data(xid,name) values(1,'aaa');Query OK, 0 rows affected, 1 warning (0.01 sec)mysql--root@localhost:test 18:58:13>>show warnings;+---------+------+-----------------------------------+| Level | Code | Message |+---------+------+-----------------------------------+| Warning | 1062 | Duplicate entry '1' for key 'xid' |+---------+------+-----------------------------------+

insert ignore into test_data(xid,name) values(4,'dd');Query OK, 1 row affected (0.00 sec)

Create Table: CREATE TABLE `test_data` ( `id` int(11) NOT NULL AUTO_INCREMENT, `xid` int(11) DEFAULT NULL, `name` varchar(30) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `xid` (`xid`)) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8

>select * from test_data;+----+------+------+| id | xid | name |+----+------+------+| 1 | 1 | aa || 2 | 2 | bb || 3 | 3 | cc || 6 | 4 | dd |+----+------+------+4 rows in set (0.00 sec)

replace into

replace into test_data(xid,name) values(1,'aa');Query OK, 2 rows affected (0.00 sec)

+----+------+------+| id | xid | name |+----+------+------+| 2 | 2 | bb || 3 | 3 | cc || 4 | 1 | aa |+----+------+------+3 rows in set (0.00 sec)

replace into test_data(xid,name) values(1,'aaa');Query OK, 2 rows affected (0.01 sec)

select *from test_data;+----+------+------+| id | xid | name |+----+------+------+| 2 | 2 | bb || 3 | 3 | cc || 5 | 1 | aaa |+----+------+------+

replace into test_data(xid,name) values(4,'cc');Query OK, 1 row affected (0.00 sec)

select *from test_data;+----+------+------+| id | xid | name |+----+------+------+| 2 | 2 | bb || 3 | 3 | cc || 5 | 1 | aaa || 6 | 4 | dd |+----+------+------+4 rows in set (0.00 sec)

insert into on duplicate

insert into test_data(xid,name) values(1,'aa') on duplicate key update xid=xid;Query OK, 0 rows affected (0.00 sec)insert into test_data(xid,name) values(1,'aa') on duplicate key update xid=xid, name=name;Query OK, 0 rows affected (0.01 sec)

+----+------+------+| id | xid | name |+----+------+------+| 1 | 1 | aa || 2 | 2 | bb || 3 | 3 | cc |+----+------+------+3 rows in set (0.00 sec)

insert into test_data(xid,name) values(1,'aaa') on duplicate key update xid=xid;Query OK, 0 rows affected (0.01 sec)insert into test_data(xid,name) values(1,'aaa') on duplicate key update xid=xid,name=name;Query OK, 0 rows affected (0.00 sec)

insert into test_data(xid,name) values(4,'cc') on duplicate key update xid=xid;Query OK, 1 row affected (0.01 sec)insert into test_data(xid,name) values(4,'ccc') on duplicate key update xid=xid, name=name;Query OK, 0 rows affected (0.00 sec)

select * from test_data;+----+------+------+| id | xid | name |+----+------+------+| 1 | 1 | aa || 2 | 2 | bb || 3 | 3 | cc || 8 | 4 | cc |+----+------+------+4 rows in set (0.00 sec)

小结:在这个场景里面,可以看到三种场景的变化真是很大,而且区别也很明显。

insert ignore into如果不指定自增列,尽管没有写入数据,但是自增列依然会自增

replace into如果不指定自增列,会看到数据重新写入的效果已经非常明显,而且自增列始终会自动维护。

insert into on duplicate对于重复数据依然会消耗自增列值,实现相对更加灵活。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-01-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 杨建荣的学习笔记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 MySQL
腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档