mysql的insert on duplicate与replace into的一些研究
2015-08-21 15:04
666 查看
mysql的innodb引擎是以主键为聚集索引的表结构,在日常的开发运维中经常会遇到duolicate key(重复主键)的报错
为了避免这一问题,mysql提供了replace into与insert into onduplicate的语法,但这两个语法在实现上是不同的
实验如下:
mysql> show create table wzy;
+-------+------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+------------------------------------------------------------------------------------------------------------------------------------+
| wzy | CREATE TABLE `wzy` (
`id` int(11) NOT NULL,
`mark` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+-------+------------------------------------------------------------------------------------------------------------------------------------+
1 row in set
mysql> desc wzy;
+-------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| mark | int(11) | YES | | NULL | |
+-------+---------+------+-----+---------+-------+
2 rows in set
以上是这次作为测试的表结构
mysql> desc wzy_test;
+-------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
+-------+---------+------+-----+---------+-------+
1 row in set
这是用于批量插入做的辅助表
mysql> select count(*) from wzy_test;
+----------+
| count(*) |
+----------+
| 579 |
+----------+
1 row in set
可以看到辅助表中有579条数据
向测试表wzy中插入300条,并mark为1
mysql> replace into wzy(id,mark)
select id,1 from wzy_test limit 300;
Query OK, 300 rows affected
Records: 300 Duplicates: 0 Warnings: 2
插入300条
我们此时将整个579条都使用replace into进去
mysql> replace into wzy(id,mark)
select id,2 from wzy_test;
Query OK, 879 rows affected
Records: 579 Duplicates: 300 Warnings: 1
可见一共操作了879行数据,即579+300,之前插入的300条都进行了删除,再插入
清空wzy
mysql> truncate table wzy;
Query OK, 0 rows affected
同样构造300条进wzy
mysql> replace into wzy(id,mark)
select id,1 from wzy_test limit 300;
Query OK, 300 rows affected
Records: 300 Duplicates: 0 Warnings: 2
这次使用insert into duplicate插入全部579条
mysql> insert into wzy(id,mark)
select id,2 from wzy_test
on DUPLICATE key UPDATE mark=2;
Query OK, 879 rows affected
Records: 579 Duplicates: 300 Warnings: 1
一共影响了879条,也是579+300
这次是全部重复数据进行插入
mysql> replace into wzy(id,mark)
select id,2 from wzy_test;
Query OK, 579 rows affected
Records: 579 Duplicates: 0 Warnings: 1
可见replace into要操作全部数据,哪怕本身没有任何变化.
再来看insert into duplicate的场景
mysql> insert into wzy(id,mark)
select id,2 from wzy_test
on DUPLICATE key UPDATE mark=2;
Query OK, 0 rows affected
Records: 579 Duplicates: 0 Warnings: 1
没有影响哪怕一行数据!
总结分析:replace into的机制是发现重复主键的情况下,删除该行,再插入新的数据,而在数据一致的情况下,做了一个不变的操作,所以操作的行数只会比预计插入的量多,
insert into duplicate则是先对表中的数据与要插入的数据进行对比,在不一样的场合,再进行操作,而这个操作就跟replace一样,先删除再插入
为了验证这一点,又进行了一点补充实验
mysql> insert into wzy(id,mark)
select id,2 from wzy_test limit 300
on DUPLICATE key UPDATE mark=3;
Query OK, 600 rows affected
Records: 300 Duplicates: 300 Warnings: 2
这里改变了mark的值,只用insert into duplicate更新前300条数据,总共影响600即为删300插300
mysql> insert into wzy(id,mark)
select id,2 from wzy_test limit 300
on DUPLICATE key UPDATE mark=2;
Query OK, 600 rows affected
Records: 300 Duplicates: 300 Warnings: 2
再将前300的mark值改回2,也是删300再插入300
mysql> insert into wzy(id,mark)
select id,2 from wzy_test limit 300
on DUPLICATE key UPDATE mark=2;
Query OK, 0 rows affected
Records: 300 Duplicates: 0 Warnings: 2
重复上次的操作,这次0 rows affected
总结:在使用insert on duplicate与replace into时,对不一致的数据2个方法采取了相同的方式,先删除再插入,而对于相同的数据,insert on duplicate只做了一次比较,没有操作,而replace into则有了一次不发生变化的操作,这个操作实际上还是要消耗性能的.
所以在这里推荐使用insert on duplicate的形式来处理重复主键的问题.
为了避免这一问题,mysql提供了replace into与insert into onduplicate的语法,但这两个语法在实现上是不同的
实验如下:
mysql> show create table wzy;
+-------+------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+------------------------------------------------------------------------------------------------------------------------------------+
| wzy | CREATE TABLE `wzy` (
`id` int(11) NOT NULL,
`mark` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+-------+------------------------------------------------------------------------------------------------------------------------------------+
1 row in set
mysql> desc wzy;
+-------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| mark | int(11) | YES | | NULL | |
+-------+---------+------+-----+---------+-------+
2 rows in set
以上是这次作为测试的表结构
mysql> desc wzy_test;
+-------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
+-------+---------+------+-----+---------+-------+
1 row in set
这是用于批量插入做的辅助表
mysql> select count(*) from wzy_test;
+----------+
| count(*) |
+----------+
| 579 |
+----------+
1 row in set
可以看到辅助表中有579条数据
向测试表wzy中插入300条,并mark为1
mysql> replace into wzy(id,mark)
select id,1 from wzy_test limit 300;
Query OK, 300 rows affected
Records: 300 Duplicates: 0 Warnings: 2
插入300条
我们此时将整个579条都使用replace into进去
mysql> replace into wzy(id,mark)
select id,2 from wzy_test;
Query OK, 879 rows affected
Records: 579 Duplicates: 300 Warnings: 1
可见一共操作了879行数据,即579+300,之前插入的300条都进行了删除,再插入
清空wzy
mysql> truncate table wzy;
Query OK, 0 rows affected
同样构造300条进wzy
mysql> replace into wzy(id,mark)
select id,1 from wzy_test limit 300;
Query OK, 300 rows affected
Records: 300 Duplicates: 0 Warnings: 2
这次使用insert into duplicate插入全部579条
mysql> insert into wzy(id,mark)
select id,2 from wzy_test
on DUPLICATE key UPDATE mark=2;
Query OK, 879 rows affected
Records: 579 Duplicates: 300 Warnings: 1
一共影响了879条,也是579+300
这次是全部重复数据进行插入
mysql> replace into wzy(id,mark)
select id,2 from wzy_test;
Query OK, 579 rows affected
Records: 579 Duplicates: 0 Warnings: 1
可见replace into要操作全部数据,哪怕本身没有任何变化.
再来看insert into duplicate的场景
mysql> insert into wzy(id,mark)
select id,2 from wzy_test
on DUPLICATE key UPDATE mark=2;
Query OK, 0 rows affected
Records: 579 Duplicates: 0 Warnings: 1
没有影响哪怕一行数据!
总结分析:replace into的机制是发现重复主键的情况下,删除该行,再插入新的数据,而在数据一致的情况下,做了一个不变的操作,所以操作的行数只会比预计插入的量多,
insert into duplicate则是先对表中的数据与要插入的数据进行对比,在不一样的场合,再进行操作,而这个操作就跟replace一样,先删除再插入
为了验证这一点,又进行了一点补充实验
mysql> insert into wzy(id,mark)
select id,2 from wzy_test limit 300
on DUPLICATE key UPDATE mark=3;
Query OK, 600 rows affected
Records: 300 Duplicates: 300 Warnings: 2
这里改变了mark的值,只用insert into duplicate更新前300条数据,总共影响600即为删300插300
mysql> insert into wzy(id,mark)
select id,2 from wzy_test limit 300
on DUPLICATE key UPDATE mark=2;
Query OK, 600 rows affected
Records: 300 Duplicates: 300 Warnings: 2
再将前300的mark值改回2,也是删300再插入300
mysql> insert into wzy(id,mark)
select id,2 from wzy_test limit 300
on DUPLICATE key UPDATE mark=2;
Query OK, 0 rows affected
Records: 300 Duplicates: 0 Warnings: 2
重复上次的操作,这次0 rows affected
总结:在使用insert on duplicate与replace into时,对不一致的数据2个方法采取了相同的方式,先删除再插入,而对于相同的数据,insert on duplicate只做了一次比较,没有操作,而replace into则有了一次不发生变化的操作,这个操作实际上还是要消耗性能的.
所以在这里推荐使用insert on duplicate的形式来处理重复主键的问题.
相关文章推荐
- mysql游标错误
- 解决ubuntu server mysql load data infile 导入本地文件ERROR 1148 (42000)错误。
- MySQL5.5主从同步配置及问题
- mysql语句在node.js中的写法
- MySQL不支持的特性
- MySQL 远程连接配置和排
- mac使用终端运行mysql,mysql终端,mysql mac,mysql目录,mysql路径
- mysql 修改root密码 admin数据库消失解决方法
- mysql 命令大全
- mysql主从备份读写分享
- 1130 - Host ‘win7' is not allowed to connect to this mysql server
- 关于mysql inner join 连接查询的优化
- 配置免安装版的mysql
- MySQL 批量导入 csv 文件
- mac系统mysql配置环境变量(转)
- mysql如何处理大量数据
- Ubuntu 安装mysql和简单操作
- MySQL中视图
- 【sql】mysql left join,right join,inner join超详细用法解析
- Importing/Indexing database (MySQL or SQL Server) in Solr using Data Import Handler--转载