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

本文介绍了MySQL中Insert的四种语法:普通插入、插入或更新、插入或替换、插入或忽略,重点讨论了在数据已存在时的不同处理方式。同时,针对大量数据插入,对比了单条循环插入、批量插入和分批量插入的效率,并提供了优化途径。文章还提及了REPLACE INTO语句的潜在影响和注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天,我来给小伙伴们从这两方面分享一下搬砖心得,如果你有疑问或好的想法,记得在评论区给我留言,我会在搬砖之余和大家一起吃瓜喔~

目录

  • 一、Insert的几种语法

    • 1-1.普通插入语句

    • 1-2.插入或更新

    • 1-3.插入或替换

    • 1-4.插入或忽略

  • 二、大量数据插入

    • 2-1、三种处理方式

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

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

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

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

  • 三、REPLACE INTO语法的“坑”

一、Insert的几种语法

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

1-1.普通插入语句



INSERT INTO table (`a`, `b`, `c`, ……) VALUES ('a', 'b', 'c', ……); 

这里不再赘述,注意顺序即可,不建议小伙伴们去掉前面括号的内容,别问为什么,容易被同事骂。

在这里插入图片描述

1-2.插入或更新


如果我们希望插入一条新记录(INSERT),但如果记录已经存在,就更新该记录,此时,可以使用"INSERT INTO … ON DUPLICATE KEY UPDATE …"语句:

情景示例:这张表存了用户历史充值金额,如果第一次充值就新增一条数据,如果该用户充值过就累加历史充值金额,需要保证单个用户数据不重复录入。

这时可以使用"INSERT INTO … ON DUPLICATE KEY UPDATE …"语句。

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


-- 用户陈哈哈充值了30元买会员

INSERT INTO total_transaction (t_transId,username,total_amount,last_transTime,last_remark) 

   VALUES (null, 'chenhaha', 30, '2020-06-11 20:00:20', '充会员') 

   ON DUPLICATE KEY UPDATE  total_amount=total_amount + 30, last_transTime='2020-06-11 20:00:20', last_remark ='充会员';

 

-- 用户陈哈哈充值了100元买瞎子至高之拳皮肤

INSERT INTO total_transaction (t_transId,username,total_amount,last_transTime,last_remark) 

   VALUES (null, 'chenhaha', 100, '2020-06-11 20:00:20', '购买盲僧至高之拳皮肤') 

   ON DUPLICATE KEY UPDATE total_amount=total_amount + 100, last_transTime='2020-06-11 21:00:00', last_remark ='购买盲僧至高之拳皮肤'; 

若username='chenhaha'的记录不存在,INSERT语句将插入新记录,否则,当前username='chenhaha'的记录将被更新,更新的字段由UPDATE指定。

对了,ON DUPLICATE KEY UPDATE为MySQL特有语法,比如在MySQL迁移Oracle或其他DB时,类似的语句要改为MERGE INTO语法,兼容性让人想骂街。但没办法,就像用WPS写的xlsx用Office无法打开一样。

1-3.插入或替换


如果我们想插入一条新记录(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<User> list= new ArrayList<User>();

		

        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> user); 

mybatis Mapper中的sql写法:


<insert id="insertListUser" parameterType="java.util.List">



# 总结

谈到面试,其实说白了就是刷题刷题刷题,天天作死的刷。。。。。

为了准备这个“金三银四”的春招,狂刷一个月的题,狂补超多的漏洞知识,像这次美团面试问的算法、数据库、Redis、设计模式等这些题目都是我刷到过的

**[CodeChina开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频】](https://codechina.youkuaiyun.com/m0_60958482/java-p7)**

**并且我也将自己刷的题全部整理成了PDF或者Word文档(含详细答案解析)**

![我的美团offer凉凉了?开发工程师(Java岗)三面结束等通知...](https://img-blog.csdnimg.cn/img_convert/770d2ba0dacfa221245720f94143747b.png)

66个Java面试知识点

**架构专题(MySQL,Java,Redis,线程,并发,设计模式,Nginx,Linux,框架,微服务等)+大厂面试题详解(百度,阿里,腾讯,华为,迅雷,网易,中兴,北京中软等)**

![我的美团offer凉凉了?开发工程师(Java岗)三面结束等通知...](https://img-blog.csdnimg.cn/img_convert/4b2512d8637836fb6581d4c9134d0acc.png)

**算法刷题(PDF)**

的题,狂补超多的漏洞知识,像这次美团面试问的算法、数据库、Redis、设计模式等这些题目都是我刷到过的

**[CodeChina开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频】](https://codechina.youkuaiyun.com/m0_60958482/java-p7)**

**并且我也将自己刷的题全部整理成了PDF或者Word文档(含详细答案解析)**

[外链图片转存中...(img-8OhY6WK2-1630835908309)]

66个Java面试知识点

**架构专题(MySQL,Java,Redis,线程,并发,设计模式,Nginx,Linux,框架,微服务等)+大厂面试题详解(百度,阿里,腾讯,华为,迅雷,网易,中兴,北京中软等)**

[外链图片转存中...(img-BPPQwFAu-1630835908311)]

**算法刷题(PDF)**

![我的美团offer凉凉了?开发工程师(Java岗)三面结束等通知...](https://img-blog.csdnimg.cn/img_convert/2ba1bf4a59eb3579867ebfb6dafbdc0c.png)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值