三表轮换实现清理MySQL大表数据

应用背景

先了解下MySQL可以删除表格数据的方法

  1. 使用DORP TABLE删除整个表
DROP TABLE IF EXISTS <table>

特点:

  • 会删除整个表格(包括表的结构包括依赖的约束,触发器,索引等)及其数据
  • 仅将该SQL记录到MySQL日志文件中,因此删掉的数据无法找回。
  • 执行速度非常快
  1. 使用TRUNCATE TABLE清空整个表
TRUNCATE TABLE <table>

特点:

  • 会保留表结构
  • 会清空表中所有数据
  • 会重建索引
  • 仅将该SQL记录到MySQL日志文件中,因此清空的数据无法找回。
  • 执行速度比较快
  1. 使用DELETE FROM TABLE删除表格中的相应数据
DELETE FROM  <table> WHERE C=?

特点:

  • 会保留表结构
  • 仅会删除符合条件的数据
  • 不会删除索引
  • 会将删除每条数据的SQL记录到日志文件中,因此够找回被删除的每一条数据。
  • 受查询条件与删除数据量的影响,执行速度非常慢

如果仅是在少量数据的表中,删除几条数据,常规操作使用DELETE FROM <table>即可,而且还相对其它两种方式比较安全,因为删错了可以从日志中回滚。但是在大数据表中用这种常规删除方式会面临如下问题:

  • 如果使用where按条件删除数据,查询相应数据非常耗时,甚至查询超时。
  • 因为每删除一条数据就会写一条记录到日志文件中,如果执行会删除十万条数据,就会逐一将这十万条删除语句写入日志文件中,这就需要很长的执行时间,甚至将导致磁盘容量不足。主要磁盘IO增加,会造成执行超时。
  • 主实例的DDL语句执行时间较长,会造成主备数据库同步延时。

应对场景

数据库存储容量一定是有限的,太多的表数据不仅会造成存储成本高昂,甚至会查询超时,影响数据的应用。通常会将大数据划分几个阶段来应对,比如简单地按日期将数据分为热数据与冷数据。怎样区分,在此不再展开讨论了。回到主题,如果热数据保存,冷数据为过期数据,那么只要删除过期的冷数据即可回收容量且不影响数据正常应用。一个应用的日志表,假设每天十多万条数据落库,应用中仅需要查询其最近七天的数据来计算报表,这种情况下,超过了七天的数据就是过期数据,如果要快速删除这种过期数据就不能用DELETE来操作了。大道至简,如上所述,删除大表数据最快的方式就是删除整个表。如果能将过期的数据分离存储到一个表里,那么只要一条DORP TABLE语句就能轻松清理成千上万的过期数据。

实现方式

将原来的数据表按月的天数拆分为a,b,c三个表,这三个表按月份中的天数轮流切换读写,因此过期的数据就自动隔离在过期的数据表里了,只要删除表即删除了过期数据。拆分规则如下:

/*计算绿表名*/
function getGreenTableName(int $day):string
{
        if ($day < 11) {
            $table = "a";
        } else if ($day < 21) {
            $table = "b";
        } else {
            $table = "c";
        }
        return $table;
}
/*计算蓝表名*/
function getBlueTableName(int $day, string $green):?string
{
        $days = date("t");//当月总天数,可以固定该值模拟大小月,平年二月28天或闰年二月29天
        $x = ($day + 6) % $days;
        if ($x == 0) $x = $days;
        $day = $x;
        if ($day < 1 || $day > $days) return null;
        $table = getGreenTableName($day);
        if ($table == $green) return null;
        return $table;
 }
 /*计算红表名*/
function getRedTableName(string $green):?string
{
        if ($green == "a") {
            $table = "c";
        } else if ($green == "b") {
            $table = "a";
        } else if ($green == "c") {
            $table = "b";
        } else {
            $table = null;
        }
        return $table;
 }

三个表的R,G,B状态是通过当天日期动态计算所得。在删除数据或者读写数据时,以当天在月份中的天数来计算该使用哪个表来操作。
R:红色状态,当天已经过期的数据表,该表可删除了。
G:绿色状态,当天应用读写的数据表。
B:蓝色状态,当天应用要写的冗余数据表,如果当前G等于B,也就是同一个表;此时就不能写冗余数据,否则在蓝色状态表里写入相同的数据。冗余表的作用是当某天来临,该表由蓝色切换为绿色状态时,就已存储了前6天的数据,避免了多表查询,且让前一个表转换成红色状态后的数据可以删除。

$ret='';
for ($i = 1; $i <= 31; $i++) {//假设从1号到31号
            $g = getGreenTableName($prefix, $i);
            $b = getBlueTableName($prefix, $i, $g);
            $r = getRedTableName($prefix, $g);
            $ret. = "第".$i."天 R:" . $r . " G:" . $g." B:" . $b."<br/>";
}
echo $ret;

执行结果

平年二月28天
第1天 R:c G:a B:
第2天 R:c G:a B:
第3天 R:c G:a B:
第4天 R:c G:a B:
第5天 R:c G:a B:b
第6天 R:c G:a B:b
第7天 R:c G:a B:b
第8天 R:c G:a B:b
第9天 R:c G:a B:b
第10天 R:c G:a B:b
第11天 R:a_A G:b B:
第12天 R:a_A G:b B:
第13天 R:a_A G:b B:
第14天 R:a_A G:b B:
第15天 R:a_A G:b B:c
第16天 R:a_A G:b B:c
第17天 R:a_A G:b B:c
第18天 R:a_A G:b B:c
第19天 R:a_A G:b B:c
第20天 R:a_A G:b B:c
第21天 R:b G:c B:
第22天 R:b G:c B:
第23天 R:b G:c B:a
第24天 R:b G:c B:a
第25天 R:b G:c B:a
第26天 R:b G:c B:a
第27天 R:b G:c B:a
第28天 R:b G:c B:a

润年二月29天
第1天 R:c G:a B:
第2天 R:c G:a B:
第3天 R:c G:a B:
第4天 R:c G:a B:
第5天 R:c G:a B:b
第6天 R:c G:a B:b
第7天 R:c G:a B:b
第8天 R:c G:a B:b
第9天 R:c G:a B:b
第10天 R:c G:a B:b
第11天 R:a_A G:b B:
第12天 R:a_A G:b B:
第13天 R:a_A G:b B:
第14天 R:a_A G:b B:
第15天 R:a_A G:b B:c
第16天 R:a_A G:b B:c
第17天 R:a_A G:b B:c
第18天 R:a_A G:b B:c
第19天 R:a_A G:b B:c
第20天 R:a_A G:b B:c
第21天 R:b G:c B:
第22天 R:b G:c B:
第23天 R:b G:c B:
第24天 R:b G:c B:a
第25天 R:b G:c B:a
第26天 R:b G:c B:a
第27天 R:b G:c B:a
第28天 R:b G:c B:a
第29天 R:b G:c B:a

小月
第1天 R:c G:a B:
第2天 R:c G:a B:
第3天 R:c G:a B:
第4天 R:c G:a B:
第5天 R:c G:a B:b
第6天 R:c G:a B:b
第7天 R:c G:a B:b
第8天 R:c G:a B:b
第9天 R:c G:a B:b
第10天 R:c G:a B:b
第11天 R:a_A G:b B:
第12天 R:a_A G:b B:
第13天 R:a_A G:b B:
第14天 R:a_A G:b B:
第15天 R:a_A G:b B:c
第16天 R:a_A G:b B:c
第17天 R:a_A G:b B:c
第18天 R:a_A G:b B:c
第19天 R:a_A G:b B:c
第20天 R:a_A G:b B:c
第21天 R:b G:c B:
第22天 R:b G:c B:
第23天 R:b G:c B:
第24天 R:b G:c B:
第25天 R:b G:c B:a
第26天 R:b G:c B:a
第27天 R:b G:c B:a
第28天 R:b G:c B:a
第29天 R:b G:c B:a
第30天 R:b G:c B:a

大月
第1天 R:c G:a B:
第2天 R:c G:a B:
第3天 R:c G:a B:
第4天 R:c G:a B:
第5天 R:c G:a B:b
第6天 R:c G:a B:b
第7天 R:c G:a B:b
第8天 R:c G:a B:b
第9天 R:c G:a B:b
第10天 R:c G:a B:b
第11天 R:a_A G:b B:
第12天 R:a_A G:b B:
第13天 R:a_A G:b B:
第14天 R:a_A G:b B:
第15天 R:a_A G:b B:c
第16天 R:a_A G:b B:c
第17天 R:a_A G:b B:c
第18天 R:a_A G:b B:c
第19天 R:a_A G:b B:c
第20天 R:a_A G:b B:c
第21天 R:b G:c B:
第22天 R:b G:c B:
第23天 R:b G:c B:
第24天 R:b G:c B:
第25天 R:b G:c B:
第26天 R:b G:c B:a
第27天 R:b G:c B:a
第28天 R:b G:c B:a
第29天 R:b G:c B:a
第30天 R:b G:c B:a
第31天 R:b G:c B:a
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值