0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

讲讲关于SQL大表删除的问题

jf_ro2CN3Fa 来源:yes的练级攻略 2023-02-03 15:19 次阅读

今天来讲讲关于大表删除 的问题。

比如,你现在需要删除一张一共有 5 亿数据的表里面的 2021 年数据,假设这张表叫 yes。

我相信你脑子在 1s 内肯定会蹦出这条 SQL :

deletefromyeswherecreate_date>"2020-12-31"andcreate_date< "2022-01-01";

如果直接执行这条 SQL 会发生什么问题呢?

长事务

我们需要关注到一个前提:这张表有 5 亿的数据,所以它是一张超大表,因此这个 where 条件可能涉及非常多的数据,所以我们可以从离线数仓或者备库查下数据量,然后我们发现这条 SQL 会删除 3 亿左右的数据。

那么一次性 delete 完的方案是不行的,因为这会涉及到长事务的问题

长事务涉及到加锁,只会在事务执行完毕后才会释放锁,由于长事务锁了很多数据,如果期间有频繁的 DML 想要操作这些数据,那么就会造成阻塞。

连接都阻塞住了,业务线程自然就阻塞了,也就是说你的服务线程都在等待数据库的响应,然后可能还会影响到别的服务,可能产生雪崩,于是就 GG 了。

长事务可能会造成主从延迟,你想想主库执行了好久,才执行完给从库,从库又要重放好久,期间可能有很长一段时间数据是不同步的。

还有一种情况,业务都有个特殊停机窗口,你觉得你可以为所欲为,然后开始执行长事务了,然后执行了 5 小时之后,不知道啥情况抛错了,事务回滚了,于是浪费了 5 个小时,还得重新开始。

综上,我们需要避免长事务的发生。

那面对可能发生长事务的 SQL 我们怎么拆 呢?

拆 SQL

我们就以上面这条 SQL 为例:

deletefromyeswherecreate_date>"2020-12-31"andcreate_date< "2022-01-01";

看到这条 SQL,如果要拆分,想必很多小伙伴会觉得很简单,按日期拆不就完事了?

deletefromyeswherecreate_date>"2020-12-31"andcreate_date< "2021-02-01";
delete from yes where create_date >="2021-02-01"andcreate_date< "2021-03-01";

......

这当然可以,恭喜你,你已经拆分成功了,没错就这么简单。

但是,如果 create_date 没有索引怎么办?

没索引的话,上面这就全表扫描了啊?

影响不大,没有索引我们就给他创造索引条件,这个条件就是主键。

我们直接一个 select min(id)... 和 select max(id).... 得到这张表的主键最小值和最大值,假设答案是 233333333 和 666666666。

然后我们就可以开始操作了:

deletefromyeswhere(id>=233333333andid< 233433333) and create_date >"2020-12-31"andcreate_date< "2022-01-01";
delete from yes where (id >=233433333andid<233533333) and create_date >"2020-12-31"andcreate_date< "2022-01-01";

......

deletefromyeswhere(id>=666566666andid<=666666666) and create_date >"2020-12-31"andcreate_date< "2022-01-01";

当然你也可以再精确些,通过日期筛选来得到 maxId,这影响不大(不满足条件的 SQL 执行很快,不会耗费很多时间)。

这样一来 SQL 就满足了分批的操作,且用得上索引。

如果哪条语句执行出错,只会回滚小部分数据,我们重新排查下就好了,影响不大。

而且拆分 SQL 之后还可以并行提高执行效率

当然,并行可能有锁竞争的情况,导致个别语句等待超时。不过影响不大,只要机器状态好,执行得快,因为锁竞争导致的等待并不一定会超时,如果个别 SQL 超时的话,重新执行就好了。

有时候要转换思路

关于大表删除有时候要转换思路,把删除转成插入

假设还是有一张 5 亿的数据表,此时你需要删除里面 4.8 亿的数据,那这时候就不要想着删除了,要想着插入。

道理很简单,删除 4.8 亿的数据,不如把要的 2000W 插入到新表中,我们后面业务直接用新表就好了。

这两个数据量对比,时间效率差异不言而喻了吧?

具体操作也简单:

创建一张新表,名为 yes_temp;

将 yes 表的 2000W 数据 select into 到 yes_temp 中;

将 yes 表 rename 成 yes_233;

将 yes_temp 表 rename 成 yes。

狸猫换太子,大功告成啦!

之前有个记录表我们就是这样操作的,就 select into 近一个月的数据到新表中,以前老数据就不管了,然后 rename 一下,执行得非常快。

本来预估 2 小时的 SQL 操作,1 分钟就搞定了。

这种类似的操作是有工具的,比如 pt-online-schema-change 等,不过我没用过,有兴趣的小伙伴可以自己去看看,道理是一样的,多了几个触发器,这里不多赘述了。

最后

咱们开发还是得多学一些数据库的操作和原理,因为好多数据库的操作都需要亲力亲为,小公司没 DBA 的话就不说了,大公司的话咱也不知道 DBA 到底会关心到哪个程度,还是得靠自己靠谱。






审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • SQL
    SQL
    +关注

    关注

    1

    文章

    740

    浏览量

    43507
  • DBA
    DBA
    +关注

    关注

    0

    文章

    18

    浏览量

    7848

原文标题:2 小时的 SQL 操作,1 分钟就搞定?!

文章出处:【微信号:芋道源码,微信公众号:芋道源码】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    SQL语句生成器

    SQL语句生成器SQL数据库语句生成及分析器(支持结构、索引、所有记录到SQL脚本)可用于数据数的备份和恢复!功能不用多说,试试就知道了
    发表于 06-12 16:15

    SQL删除出错

    用labveiw在SQL数据库里建了一个,想删除列,却总是出错,所有的列删除都会出相似的错误信息。错误代码:-2147217900,信息:NI_Database_API.lvlib:
    发表于 07-09 11:15

    labview实时数据采集存入SQL内,SQL定时新建文件组和文件

    如题labview连入SQL已建好的数据内,0.8秒采集一次。我想做的是labview定时采集数据,存入SQL需要实现自动新建(每月
    发表于 09-23 11:00

    请教关于AssociatedDevList满后删除的问题!

    芯片:cc2530协议栈:ZStack-CC2530-2.5.1现象:仿真器带coordinator,添加新router至coordinator的AssociatedDevList满了,所有
    发表于 08-10 06:24

    SQL与NoSQL数据库入门基础知识详解

    比较麻烦。(4)数据耦合性 :SQL中不允许删除已经被使用的外部数据,例如审核人中的"熊三"已经被分配给了借阅人熊大,那么在审核人中将不允许删除
    发表于 12-19 13:56

    Linux环境下oracle创建和删除空间及用户

    #su - oracle $ sqlplus /nolog SQL> connect / as sysdba --//创建临时空间 create temporary tablespace
    发表于 07-05 07:12

    请教用LabVIEW的Database创建SQL数据

    各位,我用LabVIEW的Database创建SQL数据时,数据类型只有字符串、数值、日期,没有布尔型的数据类型,没有能够对应到SQL的bit的数据类型,请问该如何解决呢,欢迎交流
    发表于 11-30 17:57

    如何去使用嵌入式SQL

    删除多个记录。必须首先对SQL游标进行DECLARE,并为其命名。在DECLARE语句中,提供了SELECT
    发表于 12-15 09:01

    Labview写一个SQL Server 数据同步的程序

    各位前辈有个问题想请教一下:我要实现的功能是利用Labview编写一个程序实现两个不同的SQL Server数据库里俩表格内数据同步(例如:A数据里的a是有数据的,B数据库里的b是没有数据的,我
    发表于 12-30 22:25

    单片机使用本地SQL数据库功能

    分享LS10串口数据库模块实现单片机存取sql数据库功能。 关系型数据库功能:1, 创建;2, 插入数据;3, 修改数据;4, 查询数据;5, 删除数据;6, 删除
    发表于 07-01 16:57

    Transact-SQL课程

      本章要点       T-SQL语言用于管理SQL Server Database Engine实例,创建和管理数据库对象,以及插入、检索、修改和删除数据。T-
    发表于 04-14 15:59 0次下载

    什么是复杂的SQL条件Nutz.Dao 中的复杂SQL条件的资料和编程说明

    什么是 Nutz.Dao 中的复杂SQL条件 · 对于 Nutz.Dao 来说,它本质上就是将你的 Java 对象转化成 SQL,然后交给 JDBC 去执行。 · 而 SQL 中,当执行数据
    发表于 09-26 17:41 2次下载

    如何才能删除SQL数据局镜像

    SQLSERVER删除数据库镜像 SQLServer删除数据库镜像,其实这之前有个很诡异的问题。..在数据库镜像断开后,如何从新建立镜像的连接呢?
    发表于 09-26 17:51 18次下载

    SQL后悔药,SQL性能优化和SQL规范优雅

    =10086orage=18; 2、操作delete或者update语句,加个limit(SQL后悔药) 在执行删除或者更新语句,尽量加上limit,以下面的这条 SQL 为例吧: deletefromeuse
    的头像 发表于 11-14 09:54 1615次阅读

    数据库数据恢复-数据库文件被删除/分区被格式化的SQL SERVER数据恢复方案

    数据库数据恢复-数据库文件被删除/分区被格式化的SQL SERVER数据恢复方案
    的头像 发表于 09-21 14:34 503次阅读