笑看天下无敌手 发表于 2024-11-25 23:43:08

MySQL 批量删除海量数据的几种方法

目次
一、问题分析
二、批量删除海量数据的几种方法
方法 1:利用 LIMIT 分批删除
方法 2:通过主键范围分批删除
方法 3:通过自定义批量删除存储过程
方法 4:创建暂时表替换旧表
三、性能优化发起
总结
        在数据库的日常维护中,我们经常遇到必要删除大量数据的场景。例如,删除过期日记、清算汗青数据等。但如果一次性删除大量数据,大概会导致锁表、事件日记暴增、影响数据库性能等问题。本文将先容几种高效批量删除 MySQL 海量数据的方法。
一、问题分析

一次性删除大量数据的重要问题在于:

[*]长时间锁表:大量删除操纵会导致数据库长时间加锁,影响其他事件的正常操纵。
[*]事件日记暴增:MySQL 在删除数据时会记录事件日记,大量删除操纵大概导致日记文件过大,乃至撑满磁盘。
[*]影响性能:一次性删除大量数据会占用大量的 CPU 和 IO 资源,对数据库团体性能产生严重影响。
为制止这些问题,可以考虑分批删除等策略来淘汰对数据库的压力。
二、批量删除海量数据的几种方法

方法 1:利用 LIMIT 分批删除

LIMIT 分批删除是一种常用的处置惩罚海量数据的方式。每次删除固定数量的数据,循环执行,直至删除完毕。
示例 SQL:

假设我们要删除 logs 表中创建时间在某个日期之前的所有数据:
-- 设置每批删除的行数
SET @BATCH_SIZE = 1000;

-- 分批删除符合条件的数据
DELETE FROM logs
WHERE create_time < '2023-01-01'
LIMIT @BATCH_SIZE; 可以将上述语句放入存储过程或在应用层循环调用。每次删除 BATCH_SIZE 行数据,淘汰锁表时间和日记生成量。
优点:



[*]控制单次删除的量,淘汰锁表时间和日记生成量。
缺点:



[*]必要循环多次操纵,逻辑稍复杂。
注意:



[*]分批删除的 LIMIT 值可以根据实际环境调解。通常 500 到 5000 是较合理的选择。
方法 2:通过主键范围分批删除

如果要删除的数据在主键上是一连的(如自增 ID),可以按主键范围分批删除。如许能够制止 LIMIT 的偏移开销,提高删除效率。
示例 SQL:

假设 logs 表的主键是 id:
-- 设置每批删除的范围
SET @start_id = 0;
SET @end_id = 1000;

WHILE (@start_id < (SELECT MAX(id) FROM logs WHERE create_time < '2023-01-01')) DO
    DELETE FROM logs
    WHERE id BETWEEN @start_id AND @end_id
    AND create_time < '2023-01-01';

    -- 更新删除范围
    SET @start_id = @end_id + 1;
    SET @end_id = @end_id + 1000;
END WHILE;
优点:



[*]主键范围分批制止了 LIMIT 偏移带来的开销。
缺点:



[*]必要知道主键范围,且适用于有一连主键的数据表。
方法 3:通过自定义批量删除存储过程

可以将批量删除逻辑封装成存储过程,利用存储过程自动控制批量删除过程。
示例 SQL:

DELIMITER $$

CREATE PROCEDURE batch_delete_logs()
BEGIN
    DECLARE done INT DEFAULT FALSE;
    DECLARE batch_size INT DEFAULT 1000;

    WHILE NOT done DO
      DELETE FROM logs
      WHERE create_time < '2023-01-01'
      LIMIT batch_size;

      -- 检查是否还有剩余数据
      IF ROW_COUNT() < batch_size THEN
            SET done = TRUE;
      END IF;
    END WHILE;
END $$

DELIMITER ;
执行存储过程:
CALL batch_delete_logs(); 优点:



[*]存储过程实现自动化,逻辑清晰,制止多次手动执行 SQL。
缺点:



[*]适用于支持存储过程的场景,对小批量删除非常适合。
方法 4:创建暂时表替换旧表

在某些环境下,删除大表中的大量数据可以通过创建新表的方法完成。即先将必要保留的数据转移到新表,再删除旧表。这种方法可以淘汰锁表时间和日记开销。
步骤:


[*]创建一个新表(结构与旧表雷同)。
[*]将必要保留的数据插入新表。
[*]删除旧表,重命名新表为原表名。
示例 SQL:

-- 创建新表
CREATE TABLE logs_new LIKE logs;

-- 插入需要保留的数据
INSERT INTO logs_new
SELECT * FROM logs WHERE create_time >= '2023-01-01';

-- 删除旧表并重命名新表
DROP TABLE logs;
RENAME TABLE logs_new TO logs; 优点:



[*]制止了大规模的删除操纵,淘汰了锁表时间和日记。
缺点:



[*]必要额外的磁盘空间来存放新表数据。
[*]在业务量大的环境下,大概必要举行额外的锁机制控制。
三、性能优化发起


[*]制止在业务高峰期举行大规模删除,可以选择在夜间等业务低峰期执行。
[*]得当设置批量大小。批量删除时,LIMIT 的大小必要根据实际环境调解,不宜过大,防止长时间锁表。
[*]关闭不必要的日记。在某些极度环境下,可以关闭 MySQL 的二进制日记(binlog)来淘汰日记开销,但此操纵有风险,应在充分相识后谨慎利用。
总结

方法适用场景优点缺点LIMIT 分批删除必要简单分批删除逻辑简单,淘汰锁表时间需循环操纵主键范围分批删除有一连主键的表高效,无偏移开销需手动指定范围自定义批量删除存储过程小批量删除自动化操纵必要数据库支持存储过程暂时表替换删除数据量非常大制止锁表,淘汰日记开销必要额外磁盘空间 根据不同的业务场景和需求,选择符合的批量删除方式可以提高 MySQL 的删除效率,淘汰对数据库的影响。渴望本文对各人在 MySQL 的数据清算和维护上有所资助!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: MySQL 批量删除海量数据的几种方法