文章目录
- 三、 扩展
零、前言
今天是学习 SQL 打卡的第 9 天,每天我会提供一篇文章供群成员阅读
希望大家先自己思考,如果实在没有想法,再看下面的解题思路,自己再实现一遍。在小虚竹JAVA社区 中对应的 【打卡贴】打卡,今天的任务就算完成了,养成每天学习打卡的好习惯。
虚竹哥会组织大家一起学习同一篇文章,所以有什么问题都可以在群里问,群里的小伙伴可以迅速地帮到你,一个人可以走得很快,一群人可以走得很远,有一起学习交流的战友,是多么幸运的事情。
我的学习策略很简单,题海策略+ 费曼学习法。如果能把这些题都认认真真自己实现一遍,那意味着 SQL 已经筑基成功了。后面的进阶学习,可以继续跟着我,一起走向架构师之路。
今天的学习内容是:SQL进阶-删除记录
一、练习题目
题目链接 | 难度 |
★☆☆☆☆ | |
★★☆☆☆ |
二、SQL思路
删除记录:SQL115 删除记录(一)
初始化数据
解法
要求处理:
- 请删除exam_record表中作答时间小于5分钟整且分数不及格(及格线为60分)的记录;
- 后台会执行您的SQL,然后通过 SELECT * FROM exam_record; 语句来筛选出剩下的数据,与正确数据进行对比。
分析:
- 删除exam_record表中作答时间小于5分钟整,作答时间的时间差,是由开始时间start_time与提交时间submit_time的时间差来算的
- 这里要用到timestampdiff()函数
语法:timestampdiff(unit,datetime_expr1,datetime_expr2)
返回datetime_expr1与datetime_expr2之间的整数差。
unit参数可以是:FRAC_SECOND。毫秒;SECOND。秒;MINUTE。分钟;HOUR。小时;DAY。天;WEEK。星期;MONTH。月;QUARTER。季度;YEAR。年
- 先查询,后面再替换删除语句
- 且分数不及格(及格线为60分)的记录,那就是score<60
- 确认查询的数据就是要删除时,就替换删除语句
删除记录:SQL116 删除记录(二)
初始化数据
解法
要求处理:
- 请删除exam_record表中未完成作答或作答时间小于5分钟整的记录中,开始作答时间最早的3条记录。
- 后台会通过 SELECT * FROM exam_record 语句来对比结果。
分析:
- 作答记录表exam_record:start_time是试卷开始时间;submit_time 是交卷时间,即结束时间,如果未完成的话,则为空
- 先查询,后面再替换删除语句
- 查询exam_record表中未完成作答
- 或作答时间小于5分钟整的记录也一样查询出来,作答时间的时间差,是由开始时间start_time与提交时间submit_time的时间差来算的
- 这里要用到timestampdiff()函数
语法:timestampdiff(unit,datetime_expr1,datetime_expr2)
返回datetime_expr1与datetime_expr2之间的整数差。
unit参数可以是:FRAC_SECOND。毫秒;SECOND。秒;MINUTE。分钟;HOUR。小时;DAY。天;WEEK。星期;MONTH。月;QUARTER。季度;YEAR。年
- 开始作答时间最早的3条记录,这里包含两层意思:1、 按作答时间升序排序;2、取前3条记录
- 替换成删除语句
- 这里会报错,是因为delete 后面是支持 limit 关键字的,但仅支持单个参数,也就是 [limit row_count],用于告知服务器在控制命令被返回到客户端前被删除的行的最大值。
正确的写法:
三、 扩展
- 在 delete 后加 limit 是个好习惯。原因如下:
- 1、delete from是全表查找的,如果加上limit 时,删除指定的条数后,就会return了。效率提高不少。
- 2、降低写错 SQL 的代价,即使删错了,例如limit 100,也就删除了100条数据,也能通过binlog找回数据
- 3、避免长事务,delete执行时,涉及的行是会加锁,如果删除的数据量大,那业务功能都要不能用了
- 4、加锁都是基于索引的,如果查询字段没有加索引,那会扫描到主键索引上,那么就算查询出来的只有一条记录,也会锁表
- 5、delete数据量大时,容易占用cpu,导致越删除越慢
- delete limit 最佳实践:
MySQL 大佬丁奇有一道题
如果你要删除一个表里面的前 10000 行数据,有以下三种方法可以做到:
第一种,直接执行 delete from T limit 10000;
第二种,在一个连接中循环执行 20 次 delete from T limit 500;
第三种,在 20 个连接中同时执行 delete from T limit 500。
先说答案:第二种会比较好。
第一种limit 10000 ,单个语句占用的时间长,锁的时间会比较长,会造成长事务问题,影响业务功能的使用。
第三种,20个连接同时执行limit 500,delete 是会加锁的,会造成锁冲突的问题。
总结:delete limit的最佳实践:删除数据时尽量加limit,同时减少加锁的范围,limit的值不要太大。
- 清空表数据建议直接用 truncate,效率上 truncate 远高于 delete,因为 truncate 不走事务,不会锁表,也不会生产大量日志写入日志文件;truncate table table_name 后立刻释放磁盘空间,并重置 auto_increment 的值。
我是虚竹哥,我们明天见~