如何高效删除 MySQL 日志表中的历史数据?实战指南

        在处理高并发的物联网平台或者其他日志密集型应用时,数据库中的日志表往往会迅速增长,数据量庞大到数百GB甚至更高,严重影响数据库性能。如何有效管理这些庞大的日志数据,特别是在不影响在线业务的情况下,成为了一项技术难题。本文将分享如何高效删除MySQL日志表中的历史数据,并且按月分区管理日志,以提升数据库的读写性能。

一 问题背景:300GB 日志表如何清理?

        国庆假期节前检查数据库,发现正在维护一张名为 ali_iot_log 的设备日志表,数据量已经膨胀到380GB,表中的历史数据占据了大量存储,并且严重拖慢了查询和插入的速度。为了优化性能,目标是删除只保留最近3个月的数据。

设备日记表占用385G,如下图:

在MySQL 5.7中,如果这张表没有分区,直接使用delete条件删除历史数据会耗时很较长,并且可能会锁表,影响在线系统的使用。也不能直接清空表,业务系统要求保留最近几个月的数据。那么,如何快速高效地清理数据,并为后续的日志管理奠定基础呢?

二 常用的方案有哪些?

方案一:表分区(推荐)

步骤:

  1. 确认表的结构和时间字段: 确保日记表中有一个用于时间的字段(例如created_atdate),这是进行分区的基础。

  2. 备份数据: 在进行任何结构性更改之前,务必备份当前表以防止数据丢失。

    mysqldump -u username -p your_database diary_table > diary_table_backup.sql
  3. 添加分区: 使用按月分区的方法。假设时间字段为created_at,可以使用以下SQL语句为表添加分区:

    ALTER TABLE diary_table PARTITION BY RANGE (TO_DAYS(created_at)) ( PARTITION p0 VALUES LESS THAN (TO_DAYS('2024-01-01')), PARTITION p1 VALUES LESS THAN (TO_DAYS('2024-02-01')), PARTITION p2 VALUES LESS THAN (TO_DAYS('2024-03-01')), ... PARTITION pN VALUES LESS THAN MAXVALUE );

    注意:为每个月创建一个分区。可以根据具体需要调整分区策略。

  4. 删除旧分区: 一旦表被分区,可以通过丢弃早期的分区来快速删除大量数据,而无需逐行删除。

    ALTER TABLE diary_table DROP PARTITION p0, p1, p2, ..., pM;

    其中,p0pM代表要删除的旧月份分区。

优点:

  • 高效:分区操作是元数据级别的,速度非常快。
  • 维护简单:通过分区可以更方便地管理和查询数据。

缺点:

  • 预先规划:如果表未分区,初次分区可能需要时间和资源。
  • 复杂性增加:需要持续关注,在数据持续增长时,要为以后的时间节点手工增加分区。

方案二:创建新表并交换(适用已存有大量数据)

如果表当前未分区,且无法立即进行分区,可以考虑以下步骤:

步骤:

  1. 创建新表: 创建一个新的日记表,结构与原表相同,建议在创建时添加适当的索引以提高插入效率。

    CREATE TABLE diary_table_new LIKE diary_table;
  2. 插入需要保留的数据: 将最近一个月的数据插入新表。可以使用INSERT INTO ... SELECT语句。

    INSERT INTO diary_table_new SELECT * FROM diary_table WHERE created_at >= DATE_SUB(NOW(), INTERVAL 1 MONTH);

    注意:此步骤可能需要一些时间,具体取决于数据量和服务器性能。

  3. 重命名表: 为确保操作的原子性,使用RENAME TABLE进行表交换。

    RENAME TABLE diary_table TO diary_table_old, diary_table_new TO diary_table;
  4. 删除旧表: 确认新表数据无误后,删除旧表以释放空间。

    DROP TABLE diary_table_old;

优点:

  • 较快:相比逐行删除,创建新表并插入所需数据更快。
  • 简单:操作步骤相对简单,易于执行。

缺点:

  • 需要双倍存储空间:需要额外的存储空间来容纳新表。
  • 短时间内锁定:在重命名表期间,可能会有短暂的表锁定,影响应用程序。

方案三:分批删除数据(定时任务实现)

如果上述方法不可行,可以考虑分批删除数据,以减少对数据库性能的影响。

步骤:

  1. 确定删除的时间范围: 例如,删除超过一个月的数据。

  2. 分批执行删除操作: 使用DELETE语句配合LIMIT,逐步删除数据。

    DELETE FROM diary_table WHERE created_at < DATE_SUB(NOW(), INTERVAL 1 MONTH) LIMIT 100000;

    重复执行上述语句,直到满足删除条件。

  3. 优化删除过程:

    • 禁用二级索引(如果适用):在删除前暂时禁用非必要的索引可以提高删除速度,删除后再重建索引。
    • 监控事务日志大小:确保删除过程不会导致事务日志过大。

优点:

  • 控制删除速度:避免一次性大量删除导致的性能问题。
  • 灵活性:可以根据服务器负载调整删除批次大小和频率。

缺点:

  • 耗时较长:相比直接删除,分批删除可能需要更长的时间完成全部删除操作。
  • 复杂性增加:需要编写脚本或程序来自动化批量删除过程。

三 在线实战操作

        当前状态不可能影在线业务,由于日志表主要是开发与运维查询问题时查看,只要保证数据不丢失即可,所以这里使用创建新表分区表比较合适。这个方案可以做到清理旧数据并保持系统稳定。

操作步骤:

1 创建分区表并迁移数据

        如果你的原始日志表还没有分区,可以通过创建新表的方式实现按月分区。创建新表时,我们可以设计好分区结构,然后将旧表中的数据迁移到新表中。

-- 创建与原来结构一样的新表
CREATE TABLE ali_iot_log_n LIKE ali_iot_log;

 创建表 如下图:


-- 为新表分区(按月份)ALTER TABLE ali_iot_log_n
PARTITION BY RANGE (TO_DAYS(ctime)) (PARTITION p0 VALUES LESS THAN (TO_DAYS('2024-01-01')),PARTITION p1 VALUES LESS THAN (TO_DAYS('2024-02-01')),PARTITION p2 VALUES LESS THAN (TO_DAYS('2024-03-01')),PARTITION p3 VALUES LESS THAN (TO_DAYS('2024-04-01')),PARTITION p4 VALUES LESS THAN (TO_DAYS('2024-05-01')),PARTITION p5 VALUES LESS THAN (TO_DAYS('2024-06-01')),PARTITION p6 VALUES LESS THAN (TO_DAYS('2024-07-01')),PARTITION p7 VALUES LESS THAN (TO_DAYS('2024-08-01')),PARTITION p8 VALUES LESS THAN (TO_DAYS('2024-09-01')),PARTITION p9 VALUES LESS THAN (TO_DAYS('2024-10-01')),PARTITION p10 VALUES LESS THAN (TO_DAYS('2024-11-01')),PARTITION p11 VALUES LESS THAN (TO_DAYS('2024-12-01')),PARTITION pp0 VALUES LESS THAN (TO_DAYS('2025-01-01')),PARTITION pp1 VALUES LESS THAN (TO_DAYS('2025-02-01')),PARTITION pp2 VALUES LESS THAN (TO_DAYS('2025-03-01')),PARTITION pp3 VALUES LESS THAN (TO_DAYS('2025-04-01')),PARTITION pp4 VALUES LESS THAN (TO_DAYS('2025-05-01')),PARTITION pp5 VALUES LESS THAN (TO_DAYS('2025-06-01')),PARTITION pp6 VALUES LESS THAN (TO_DAYS('2025-07-01')),PARTITION pp7 VALUES LESS THAN (TO_DAYS('2025-08-01')),PARTITION pp8 VALUES LESS THAN (TO_DAYS('2025-09-01')),PARTITION pp9 VALUES LESS THAN (TO_DAYS('2025-10-01')),PARTITION pp10 VALUES LESS THAN (TO_DAYS('2025-11-01')),PARTITION pp11 VALUES LESS THAN (TO_DAYS('2025-12-01')),PARTITION pN VALUES LESS THAN MAXVALUE
);

为表创建分区如下图:

2 旧表数据插入新表(重要

   然后将旧表中的需要保留的数据插入新表,这里一定要注意性能,查询条件尽量小批量进行,:

INSERT INTO ali_iot_log_n SELECT * FROM ali_iot_log WHERE ctime BETWEEN '2024-09-01 00:00:00' AND '2024-09-10 23:59:59';

我这边线上环境保存到数据库是使用队列,负责消费的处理保存的可以停下,数据都放在队列先,后面启动会继续使用,所以下面以条件10天数据量大概1亿条数据转存数据到新表,如下图:

每次迁移1亿条数据,分三次即可以1个月数据了,如果线上不间断运行保存就要考虑把最后某个时间点的数据不迁移先(可以改完表后再迁移) 。

3 重命名表,快速切换到新表

 确认数据迁移完成,可以通过以下SQL实现旧表与新表的快速切换:

RENAME TABLE ali_iot_log TO ali_iot_log_old, ali_iot_log_n TO ali_iot_log;

 该操作是原子性的,几乎不会影响业务的连续性,因为RENAME TABLE 是元数据操作,时间消耗极少,但是数据多的情况下还是需要几分钟时间,这里涉及30亿条数据量,如下图:

如果之前还有未迁完数据,迁完旧表即可。

迁移完后检查数据,确认没问题直接清空旧表即可

TRUNCATE TABLE ali_iot_log_old

4 定期删除旧分区数据

通过分区表管理日志后,删除旧数据变得非常简单。可以按月删除不再需要的分区,以释放存储空间。

比如删除1个月的数据,指定数据所在的分区即可:

ALTER TABLE ali_iot_log DROP PARTITION p0;

这比直接删除数据要高效得多,因为它只需要在元数据层面进行操作,避免了全表扫描和锁定。

操作建议

  1. 分批迁移数据
    对于大型表的数据迁移操作,建议分批进行。可以通过LIMIT关键字对数据进行分块插入,避免对数据库造成过大的压力。

  2. 选择低峰时段进行操作
    大规模数据操作对性能有一定影响,建议在业务低峰时段进行操作,以最小化对用户的影响。

  3. 备份重要数据
    在执行重大操作之前,建议对数据库进行备份。即便是删除旧数据或重命名表这样看似简单的操作,也应当做好应急恢复的准备。

四 总结

通过分区表的管理,可以极大提升MySQL在处理大规模日志表时的性能,特别是按时间维度划分分区后,数据的清理和查询将更加高效。结合重命名表和按月分区的方式,我们可以轻松应对日志表膨胀的问题,而不会对在线业务造成严重影响。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/880930.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【LeetCode HOT 100】详细题解之二叉树篇

【LeetCode HOT 100】详细题解之二叉树篇 94 二叉树的中序遍历方法一&#xff1a;递归方法二&#xff1a;迭代 104 二叉树的最大深度方法一&#xff1a;递归方法二&#xff1a;迭代 226 翻转二叉树方法一&#xff1a;递归方法二&#xff1a;迭代 101 对称二叉树方法一&#xff…

小程序-使用npm包

目录 Vant Weapp 安装 Vant 组件库 使用 Vant 组件 定制全局主题样式 API Promise化 1. 基于回调函数的异步 API 的缺点 2. 什么是 API Promise 化 3. 实现 API Promise 化 4.调用 Promise 化之后的异步 API 小程序对 npm 的支持与限制 目前&#xff0c;小程序中已经…

Java 之深入理解 String、StringBuilder、StringBuffer

前言 由于发现 String、StringBuilder、StringBuffer 面试的时候会经常问到&#xff0c;这里就顺便总结一下&#xff1a;本文重点会以这三个字符串类的性能、线程安全、存储结构这三个方面进行分析 ✨上期回顾&#xff1a;Java 哈希表 ✨目录 前言 String 介绍 String 的不可变…

全局安装cnpm并设置其使用淘宝镜像的仓库地址(地址最新版)

npm、cnpm和pnpm基本概念 首先介绍一下npm和cnpm是什么&#xff0c;顺便说一下pnpm。 npm npm&#xff08;Node Package Manager&#xff09;是Node.js的默认包管理器&#xff0c;用于安装、管理和分享JavaScript代码包。它是全球最大的开源库生态系统之一&#xff0c;提供了数…

如何使用ssm实现基于HTML的中国传统面食介绍网站的搭建+vue

TOC ssm758基于HTML的中国传统面食介绍网站的搭建vue 第1章 绪论 1.1选题动因 当前的网络技术&#xff0c;软件技术等都具备成熟的理论基础&#xff0c;市场上也出现各种技术开发的软件&#xff0c;这些软件都被用于各个领域&#xff0c;包括生活和工作的领域。随着电脑和笔…

微服务SpringGateway解析部署使用全流程

官网地址&#xff1a; Spring Cloud Gateway 目录 1、SpringGateway简介 1、什么是网关 2、为什么用网关【为了转发】 2、应用&#xff1a; 1.启动nacos 2.创建网关项目 3.网关配置1 4.网关配置2【了解】 5.过滤器配置【了解】 1、SpringGateway简介 核心功能有三个&…

Webpack模式-Resolve-本地服务器

目录 ResolveMode配置搭本地服务器区分环境配置 Resolve 前面学习时使用了各种各样的模块依赖&#xff0c;这些模块可能来自于自己编写的代码&#xff0c;也可能来自第三方库&#xff0c;在 Webpack 中&#xff0c;resolve 是用于解析模块依赖的配置项&#xff0c;它决定了 We…

每日OJ题_牛客_DP13[NOIP2002 普及组]过河卒_路径dp_C++_Java

目录 牛客_DP13[NOIP2002 普及组]过河卒_路径dp 题目解析 C代码1 C代码2 Java代码 牛客_DP13[NOIP2002 普及组]过河卒_路径dp [NOIP2002 普及组] 过河卒_牛客题霸_牛客网 (nowcoder.com) 描述&#xff1a; 棋盘上 A点有一个过河卒&#xff0c;需要走到目标 B点。卒行走的…

业务封装与映射 -- 业务映射路径

为什么需要封装映射 OTN网络客户业务种类繁多&#xff08;例如SDH、以太网、视频&#xff09;&#xff0c;且业务大小不一&#xff08;例如STM-1、STM-4、STM-16&#xff09;&#xff0c;为了便于传输、管理客户业务&#xff0c;保证设备间互联互通&#xff0c;ITU-T定义了OTN接…

《深度学习》OpenCV 角点检测、特征提取SIFT 原理及案例解析

目录 一、角点检测 1、什么是角点检测 2、检测流程 1&#xff09;输入图像 2&#xff09;图像预处理 3&#xff09;特征提取 4&#xff09;角点检测 5&#xff09;角点定位和标记 6&#xff09;角点筛选或后处理&#xff08;可选&#xff09; 7&#xff09;输出结果 3、邻域…

物联网智能项目全面解析

目录 引言 一、物联网概述 1.1 什么是物联网 1.2 物联网的历史与发展 二、物联网智能项目分类 三、关键组件与技术 3.1 传感器和执行器 3.2 连接技术 3.3 数据处理与分析 3.4 用户界面 四、物联网智能项目案例分析 4.1 智能家居 4.2 智慧城市 4.3 工业物联网 4.4…

前端编程艺术(2)----CSS

目录 1.CSS 2.CSS引入 3.选择器 1.标签选择器 2.类选择器 3.id选择器 4.属性选择器 5.后代选择器 5.直接子元素选择器 6.伪类选择器 链接相关 动态伪类 结构化伪类 否定伪类 其他伪类 UI元素状态伪类 4.字体 1.font-family 2.font-size 3.font-style 4.fo…

C++之多线程

前言 多线程和多进程是并发编程的两个核心概念,它们在现代计算中都非常重要,尤其是在需要处理大量数据、提高程序性能和响应能力的场景中。 多线程的重要性: 资源利用率:多线程可以在单个进程中同时执行多个任务,这可以更有效地利用CPU资源,特别是在多核处理器上。 性…

奔驰EQS450suv升级增强AR抬头显示HUD案例分享

以下是奔驰 EQS450 SUV 升级增强版 AR 抬头显示的一般改装案例步骤及相关信息&#xff1a; 配件&#xff1a;通常包括显示屏、仪表模块、饰板等。 安装步骤&#xff1a; 1. 拆下中控的仪表。 2. 在仪表上预留位置切割出合适的孔位&#xff0c;用于安装显示器。 3. 将显示器…

(IDEA)spring项目导入本地jar包方法和项目打包时找不到引入本地jar包的问题解决方案

系列文章目录 文章目录 系列文章目录一、&#xff08;IDEA&#xff09;spring项目导入本地jar包方法和项目打包时找不到引入本地jar包的问题解决方案1.资料 一、&#xff08;IDEA&#xff09;spring项目导入本地jar包方法和项目打包时找不到引入本地jar包的问题解决方案 1.资料…

Python案例--水仙花数的探索之旅

一、引言 水仙花数&#xff0c;也称为阿姆斯特朗数&#xff0c;是一种特殊的三位数&#xff0c;其各位数字的立方和等于其本身。例如&#xff0c;153就是一个水仙花数&#xff0c;因为 135333153135333153。这种数字的发现不仅展示了数字的内在美&#xff0c;也激发了人们对数…

大学学校用电安全远程监测预警系统

1.概述&#xff1a; 该系统是基于移动互联网、云计算技术&#xff0c;通过物联网传感终端&#xff0c;将办公建筑、学校、医院、工厂、体育场馆、宾馆、福利院等人员密集场所的电气安全数据&#xff0c;实时传输至安全用申管理服务器&#xff0c;为用户提供不间断的数据跟踪&a…

五子棋双人对战项目(4)——匹配模块(解读代码)

目录 一、约定前后端交互接口的参数 1、websocket连接路径 2、构造请求、响应对象 二、用户在线状态管理 三、房间管理 1、房间类&#xff1a; 2、房间管理器&#xff1a; 四、匹配器(Matcher) 1、玩家实力划分 2、加入匹配队列&#xff08;add&#xff09; 3、移除…

解决ModuleNotFoundError: No module named ‘torchcrf‘

运行深度学习程序时候&#xff0c;出现报错&#xff1a;ModuleNotFoundError: No module named torchcrf 将 from torchcrf import CRF 改为 from TorchCRF import CRF

C#案例 | 基于C#语言在Excel中进行二次开发(一):简单系统搭建:打印输出“Hello Excel C#”

基于C#语言在Excel中进行二次开发&#xff08;一&#xff09;&#xff1a;简单系统搭建&#xff1a;打印输出”Hello Excel & C#” 实现效果第一步&#xff1a;前期准备第二步&#xff1a;打开VS 2022&#xff0c;创建项目第三步&#xff1a;程序界面设计 实现效果 在Exce…