近千万的数据怎么删除

记录下

MySQL表,每天大概新增3000万条记录,存储周期为1天,超过1天的数据需要在新增记录前老化。连续运行9天以后,删除一天的数据大概需要3个半小时

最初的方案(因为未预料到删除会如此慢),代码如下(最简单和朴素的方法):

delete from table_name where cnt_date <= target_date

最终实现了飞一般的速度删除3000多万条数据,单张表总数据量在4600万上下,优化过程的方案层层递进,详细记录如下:

批量删除(每次限定一定数量),然后循环删除直到全部数据删除完毕;同时key_buffer_size 由默认的8M提高到512M

运行效果:删除时间大概从3个半小时提高到了3小时

(1)通过limit(具体size 请酌情设置)限制一次删除的数据量,然后判断数据是否删除完

(2)增加key_buffer_size

mysqlcur.execute("SET GLOBAL key_buffer_size = 536870912")

DELETE QUICK + OPTIMIZETABLE

适用场景:MyISAM Tables

Why: MyISAM删除的数据维护在一个链表中,这些空间和行的位置接下来会被Insert的数据复用。 直接的delete后,mysql会合并索引块,涉及大量内存的拷贝移动;而OPTIMIZE TABLE直接重建索引,即直接把数据块情况,再重新搞一份(联想JVM垃圾回收算法)。

运行效果:删除时间大3个半小时提高到了1小时40分

表分区,直接删除过期日期所在的分区(最终方案—秒杀)

MySQL表分区有几种方式,包括RANGE、KEY、LIST、HASH,具体参见官方文档。因为这里的应用场景日期在变化,所以不适合用RANGE设置固定的分区名称,HASH分区更符合此处场景

(1)分区表定义,SQL语句如下:

ALTER TABLE table_name PARTITION BY HASH(TO_DAYS(cnt_date)) PARTITIONS 7;

TO_DAYS将日期(必须为日期类型,否则会报错:Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed)转换为天数(年月日总共的天数),然后HASH;建立7个分区。实际上,就是 days MOD 7。

(2)查询出需要老化的日期所在的分区,SQL语句如下:

(3)OPTIMIZE or REBUILD partition,SQL语句如下:

"ALTER TABLE g_visit_relation_asset OPTIMIZE PARTITION '%s'" % partition

如果删除的数据超过表数据的百分之50,建议拷贝所需数据到临时表,然后删除原表,再重命名临时表为原表,附MySQL如下:

可通过: ALTER TABLE table_name REMOVE PARTITIONING 删除分区,而不会删除相应的数据

你可能感兴趣的:(java)