如果我们想插入一条新记录(INSERT),但如果记录已经存在,就先删除原记录,再插入新记录。

情景示例:这张表存的每个客户最近一次交易订单信息,要求保证单个用户数据不重复录入,且执行效率最高,与数据库交互最少,支撑数据库的高可用。

此时,可以使用"REPLACE INTO"语句,这样就不必先查询,再决定是否先删除再插入。

"REPLACE INTO"语句是基于唯一索引或主键来判断唯一(是否存在)的。

"REPLACE INTO"语句是基于唯一索引或主键来判断唯一(是否存在)的。

"REPLACE INTO"语句是基于唯一索引或主键来判断唯一(是否存在)的。

注意事项:如下SQL所示,需要在username字段上建立唯一索引(Unique),transId设置自增即可。

– 20点充值

REPLACE INTO last_transaction (transId,username,amount,trans_time,remark)

VALUES (null, ‘chenhaha’, 30, ‘2020-06-11 20:00:20’, ‘会员充值’);

– 21点买皮肤

REPLACE INTO last_transaction (transId,username,amount,trans_time,remark)

VALUES (null, ‘chenhaha’, 100, ‘2020-06-11 21:00:00’, ‘购买盲僧至高之拳皮肤’);

若username='chenhaha’的记录不存在,REPLACE语句将插入新记录(首次充值),否则,当前username='chenhaha’的记录将被删除,然后再插入新记录。

id不要给具体值,不然会影响SQL执行,业务有特殊需求除外。

小tips:

ON DUPLICATE KEY UPDATE:如果插入行出现唯一索引或者主键重复时,则执行旧的update;如果不会导致唯一索引或者主键重复时,就直接添加新行。

REPLACE INTO:如果插入行出现唯一索引或者主键重复时,则delete老记录,而录入新的记录;如果不会导致唯一索引或者主键重复时,就直接添加新行。

replace into 与 insert on deplicate udpate 比较:

  • 1、在没有主键或者唯一索引重复时,replace into 与 insert on deplicate udpate 相同。

  • 2、在主键或者唯一索引重复时,replace是delete老记录,而录入新的记录,所以原有的所有记录会被清除,这个时候,如果replace语句的字段不全的话,有些原有的比如c字段的值会被自动填充为默认值(如Null)。

  • 3、细心地朋友们会发现,insert on deplicate udpate只是影响一行,而REPLACE INTO可能影响多行,为什么呢?写在文章最后一节咯~

[](

)1-4.插入或忽略


如果我们希望插入一条新记录(INSERT),但如果记录已经存在,就啥事也不干直接忽略,此时,可以使用INSERT IGNORE INTO …语句:情景很多,不再举例赘述。

注意事项:同上,"INSERT IGNORE INTO …"语句是基于唯一索引或主键来判断唯一(是否存在)的,需要在username字段上建立唯一索引(Unique),transId设置自增即可。

– 用户首次添加

INSERT IGNORE INTO users_info (id, username, sex, age ,balance, create_time)

VALUES (null, ‘chenhaha’, ‘男’, 26, 0, ‘2020-06-11 20:00:20’);

– 二次添加,直接忽略

INSERT IGNORE INTO users_info (id, username, sex, age ,balance, create_time)

VALUES (null, ‘chenhaha’, ‘男’, 26, 0, ‘2020-06-11 21:00:20’);

[](

)二、大量数据插入

=======================================================================

[](

)2-1、三种处理方式


[](

)2-1-1、单条循环插入

我们取10w条数据进行了一些测试,如果插入方式为程序遍历循环逐条插入。在mysql上检测插入一条的速度在0.01s到0.03s之间。

逐条插入的平均速度是0.02*100000,也就是33分钟左右。

下面代码是测试例子:

1普通循环插入100000条数据的时间测试

@Test

public void insertUsers1() {

User user = new User();

user.setUserName(“提莫队长”);

user.setPassword(“正在送命”);

user.setPrice(3150);

user.setHobby(“种蘑菇”);

for (int i = 0; i < 100000; i++) {

user.setUserName(“提莫队长” + i);

// 调用插入方法

userMapper.insertUser(user);

}

}

执行速度是30分钟也就是0.018*100000的速度。可以说是很慢了

发现逐条插入优化成本太高。然后去查询优化方式。发现用批量插入的方法可以显著提高速度。

将100000条数据的插入速度提升到1-2分钟左右↓

[](

)2-1-2、修改SQL语句批量插入

insert into user_info (user_id,username,password,price,hobby)

values (null,‘提莫队长1’,‘123456’,3150,‘种蘑菇’),(null,‘盖伦’,‘123456’,450,‘踩蘑菇’);

用批量插入插入100000条数据,测试代码如下:

@Test

public void insertUsers2() {

List list= new ArrayList();

User user = new User();

user.setPassword(“正在送命”);

user.setPrice(3150);

user.setHobby(“种蘑菇”);

for (int i = 0; i < 100000; i++) {

user.setUserName(“提莫队长” + i);

// 将单个对象放入参数list中

list.add(user);

}

userMapper.insertListUser(list);

}

批量插入使用了0.046s 这相当于插入一两条数据的速度,所以用批量插入会大大提升数据插入速度,当有较大数据插入操作是用批量插入优化

批量插入的写法:

dao定义层方法:

Integer insertListUser(List user);

mybatis Mapper中的sql写法:

INSERT INTO db.user_info

( id,

username,

password,

price,

hobby)

values

(null,

#{item.userName},

#{item.password},

#{item.price},

#{item.hobby})

这样就能进行批量插入操作:

注:但是当批量操作数据量很大的时候。例如我插入10w条数据的SQL语句要操作的数据包超过了1M,MySQL会报如下错:

报错信息:

Mysql You can change this value on the server by setting the max_allowed_packet' variable. Packet for query is too large (6832997 > 1048576). You can change this value on the server by setting the max_allowed_packet' variable.

解释:

用于查询的数据包太大(6832997> 1048576)。 您可以通过设置max_allowed_packet的变量来更改服务器上的这个值。

通过解释可以看到用于操作的包太大。这里要插入的SQL内容数据大小为6M 所以报错。

解决方法:

数据库是MySQL57,查了一下资料是MySQL的一个系统参数问题:

max_allowed_packet,其默认值为1048576(1M),

查询:

show VARIABLES like ‘%max_allowed_packet%’;

修改此变量的值:MySQL安装目录下的my.ini(windows)/etc/mysql.cnf(linux) 文件中的[mysqld]段中的

max_allowed_packet = 1M,如更改为20M(或更大,如果没有这行内容,增加这一行),如下图

保存,重启MySQL服务。现在可以执行size大于1M小于20M的SQL语句了。

但是如果20M也不够呢?

[](

)2-1-3、分批量多次循环插入

如果不方便修改数据库配置或需要插入的内容太多时,也可以通过后端代码控制,比如插入10w条数据,分100批次每次插入1000条即可,也就是几秒钟而已;当然,如果每条的内容很多的话,另说。。

[](

)2-2、插入速度慢的其他几种优化途径


A、通过show processlist;命令,查询是否有其他长进程或大量短进程抢占线程池资源 ?看能否通过把部分进程分配到备库从而减轻主库压力;或者,先把没用的进程kill掉一些?(手动挠头o_O)

B、大批量导数据,也可以先关闭索引,数据导入完后再打开索引

关闭:ALTER TABLE user_info DISABLE KEYS;

开启:ALTER TABLE user_info ENABLE KEYS;

[](

)三、REPLACE INTO语法的“坑”

===================================================================================

上面曾提到REPLACE可能影响3条以上的记录,这是因为在表中有超过一个的唯一索引。在这种情况下,REPLACE将考虑每一个唯一索引,并对每一个索引对应的重复记录都删除,然后插入这条新记录。假设有一个table1表,有3个字段a, b, c。它们都有一个唯一索引,会怎么样呢?我们早一些数据测试一下。

– 测试表创建,a,b,c三个字段均有唯一索引

CREATE TABLE table1(a INT NOT NULL UNIQUE,b INT NOT NULL UNIQUE,c INT NOT NULL UNIQUE);

– 插入三条测试数据

INSERT into table1 VALUES(1,1,1);

INSERT into table1 VALUES(2,2,2);

INSERT into table1 VALUES(3,3,3);

此时table1中已经有了3条记录,a,b,c三个字段都是唯一(UNIQUE)索引

mysql> select * from table1;

±–±--±–+

| a | b | c |

±–±--±–+

| 1 | 1 | 1 |

| 2 | 2 | 2 |

| 3 | 3 | 3 |

±–±--±–+

3 rows in set (0.00 sec)

MySQL实战中,Insert语句的使用心得总结相关推荐

  1. mysql中insert语句的五种用法

    文章目录 前言 一.values参数后单行插入 二.values参数后多行插入 三.搭配select插入数据 四.复制旧表的信息到新表 五.搭配set插入数据 总结 前言 insert语句是标准sql ...

  2. mybatis insert 忽略 联合唯一索引_MySQL实战中,Insert语句的使用心得总结

    提到MySQL的Insert语句,你肯定不陌生,或许已经张口就来:不就是insert into table values(xxx,xxx,xxx)嘛!没错,但在实战中,根据不同的需求场景,插入操作在语 ...

  3. mysql insert into values select_mysql中insert语句中,value与values之间的区别?

    你的位置: 问答吧 -> JAVA -> 问题详情 mysql中insert语句中,value与values之间的区别? mysql> select * from tt; +---- ...

  4. mysql 导出insert 语句_mysqldump导出sql中insert语句的问题

    mysqldump导出sql中insert语句的问题 今天有同事问,mysqldump怎么样才能够将导出的sql中,每条记录对应一个insert语句,默认总是导出一个长的insert语句,如下所示: ...

  5. java mysql insert_MySQL中INSERT的一般用法

    INSERT语句是最常见的SQL语句之一,但是MySQL中INSERT语句的用法和标准用法不尽相同,下文就为您详细介绍MySQL中INSERT的一般用法,供您参考. 1用法 在标准的SQL语句中,一次 ...

  6. MySQL实战中,Insert语句的使用心得总结,字节跳动Java金三银四解析

    – 用户陈哈哈充值了100元买瞎子至高之拳皮肤 INSERT INTO total_transaction (t_transId,username,total_amount,last_transTim ...

  7. MySQL实战中,Insert语句的使用心得总结,差点挂在了美团三面

    今天,我来给小伙伴们从这两方面分享一下搬砖心得,如果你有疑问或好的想法,记得在评论区给我留言,我会在搬砖之余和大家一起吃瓜喔~ 目录 一.Insert的几种语法 1-1.普通插入语句 1-2.插入或更 ...

  8. mysql教程中插入语句_mysql中插入数据Insert into语句用法

    在mysql中要向数据库中保存数据我们最常用的一种方法就是直接使用Insert into语句来实现了,下面我来给大家详细介绍Insert into语句用法 INSERT用于向一个已有的表中插入新行.I ...

  9. mysql or_MySQL中or语句用法示例

    1.mysql中or语法的使用,在mysql语法中or使用注意点. 项目遇到坑,遍历发放奖励数据查询错误!!! $sql = 'SELECT * FROM `vvt_spread_doubleegg_ ...

  10. 添加的oracle语句,Oracle中Insert语句的总结

    在oracle中,insert语句的使用: 1.insert into 表1(列名1,列名2,--) values(值1,值2,--) 2.insert into 表1(列名1,列名2,--) sel ...

最新文章

  1. 福特汉姆大学计算机科学专业,没有计算机专业背景可以申请哪些美国名校?
  2. 主成分分析 PCA算法
  3. add-apt-repository:找不到命令_手把手教你使用nodejs编写cli(命令行)
  4. svn版本信息自动更新到源代码
  5. 文档加载完后执行相关事件
  6. 认识Web.config文件
  7. mysq命令行导出sql_mysql 命令行导入导出 sql
  8. ei会议和ei源刊的区别_核心期刊SCI论文发表 | SCI和EI和核心有什么区别
  9. 牛客网算法工程师能力评估
  10. iphone分辨率_QHD 分辨率有必要吗?三个理由告诉你:手机屏幕 FHD 就很好
  11. /31位掩码实验演示
  12. mac系统怎么获取最高权限删除顽固文件?
  13. [Android自定义控件] Android自定义控件
  14. 计算机专业期末试卷分析,计算机期末试卷分析
  15. intel wifi 5100agn linux驱动,intel5100agn驱动
  16. 豆瓣电影数据分析案例
  17. micropython esp32驱动舵机_关于micropython ESP32的MQTT通讯方式控制舵机
  18. scp是什么,有什么用
  19. QT教程 休闲棋牌游戏开发(2)
  20. java 上传图片到图片服务器

热门文章

  1. 1.3.太极平台:15分钟搭建初始后台系统
  2. foreach遍历ArrayList时的不当操作与解决
  3. 前端页面响应慢的问题处理
  4. 【无标题】肖特基二极管(SBD)与普通二极管的区别?
  5. 基于asp.net公司文档资料管理系统
  6. C++基础知识 - 指针引用
  7. 使用【ipad】【带格式带图片】复制CSDN博客笔记的方法记录(其他网页通用)
  8. vue.js三十五—— 从无到有完整的项目实战2
  9. d用户反驳移植到jai的经验
  10. Access denied的解决