【问题标题】:I want to keep only 5 days data and delete rest of the data if it is less than the retention date. Need to remember each day 2000000 row generate我只想保留 5 天的数据,如果少于保留日期,则删除其余数据。需要记住每天2000000行生成
【发布时间】:2022-01-04 23:06:56
【问题描述】:
DELIMITER $$
CREATE PROCEDURE sp_delete_data()
BEGIN
  DECLARE i INT DEFAULT 0;
  DECLARE loop_counter INT DEFAULT 0;
  DECLARE retain_days datetime;
  DECLARE delete_days datetime;
  SET loop_counter=(SELECT ROUND(count(*)/100,0) FROM data2 WHERE datetime<(SELECT  DATE_ADD(min(datetime),INTERVAL 1 DAY) FROM data2));
  SET retain_days=(SELECT DATE_SUB(now(),INTERVAL 5 DAY)); -- 5 days data will keep
  SET delete_days =(SELECT  DATE_ADD(min(datetime),INTERVAL 1 DAY) FROM data2); -- check old data from table data2
        WHILE i <= loop_counter DO
            IF retain_days>delete_days THEN
                DELETE FROM data2 where datetime<delete_days LIMIT 1000;
            END IF;
            SET i = i + 1;
        END WHILE;  
END$$
DELIMITER ;

我只想保留 5 天的数据,如果少于保留日期,则删除其余数据。由于每天数据生成近 2000000 行,这就是为什么很难一次性删除整个数据的原因。这就是为什么我想在每个循环中删除 100000 个数据。 这里, loop_counter 变量用于查找我们应该为这一天的数据使用多少循环。 retain_days 变量定义以查找保留日期 delete_days 变量定义以查找删除日期。 基于retain_days 和delete_days 的可变数据将保留和删除。 最后,此过程将每 1 天按事件调用一次。

我的代码循环没有按预期工作。需要专家解决方案。 如果删除这样的数据有任何性能问题,请告诉我。提前致谢

【问题讨论】:

  • 您写道您的代码没有按预期工作,但未能解释这意味着什么!您收到错误消息吗?有没有意外的输出?
  • 循环不工作。这些数据只有一次被删除。
  • “不起作用”是什么意思?当你尝试它时发生了什么?你收到错误信息了吗?如果您确实收到错误,请粘贴整个消息而不是解释。你得到不正确的结果吗?您得到 no 结果了吗?如果结果不正确,是什么导致它们不正确?你期待什么?你得到任何正确的结果了吗?如果是这样,它们是什么?不要让我们猜测。
  • 不要这样做。当您在这个巨大的表上执行多个SELECTs 时,您的数据库将有一个数量级的工作要做。只需运行一次删除,这样会快得多。
  • 手动删除很耗时。我有 3-4 个月的数据。我想删除那些自动化的方式。 @Louis您有比这更好的解决方案吗?提前致谢。

标签: mysql sql stored-procedures mariadb


【解决方案1】:

只需创建一个每天运行一次的事件:

CREATE EVENT purge_old_data
    ON SCHEDULE EVERY '1' DAY
    STARTS CURRENT_TIMESTAMP()
    ON COMPLETION PRESERVE
    COMMENT 'Delete rows older than 5 days'
    DO 
BEGIN
  DELETE
    FROM data2
  WHERE `datetime` < DATE_SUB(CURRENT_TIMESTAMP(), INTERVAL 5 DAY);
END;

您不应该使用循环来删除较小的块。在 SQL 数据库中,循环实际上会使性能变差。如果您必须在第一次运行时删除数以百万计的行,这对 MariaDB 来说确实不是问题。

【讨论】:

    【解决方案2】:

    PARTITION BY RANGE 每个分区可以存储 2 小时的数据。然后DROP PARTITION非常快速丢弃数据——DELETE 好很多

    更多关于使用分区:http://mysql.rjweb.org/doc.php/partitionmaint

    替代方案:http://mysql.rjweb.org/doc.php/deletebig

    特别是,第二个链接显示了如何通过PRIMARY KEY“持续”运行数据,一次删除 1000 行。完成后重复。

    注意:以下是有问题的:

    DELETE FROM data2
       where datetime<delete_days LIMIT 1000;
    

    没有INDEX(datetime),它将花费大量时间寻找要删除的行。有了这样的索引,仍然存在索引和数据之间跳动 1000 次的开销。在任何一种情况下,都必须将 1000 行放入重做日志中,以免发生崩溃。

    【讨论】:

    • 但是分区是否支持mariadb/mysql的外键约束?
    • 在这个表中我有一个外键约束,因为它不能做分区。你知道如何对外键约束表进行分区吗?如果有,请分享详细文档。
    • @SheikhWa​​siuAlHasib - 外键 + 分区 - FK 不是必需的。 FK 创建的索引对性能很有用。切换到分区时,您应该重新考虑索引。请提供SHOW CREATE TABLE及主要查询;我会就索引提出建议。
    • @SheikhWa​​siuAlHasib - 使用第二个链接获取有关如何在不使用分区的情况下删除大量数据的建议。
    猜你喜欢
    • 1970-01-01
    • 2023-02-03
    • 2021-05-18
    • 1970-01-01
    • 1970-01-01
    • 2019-09-14
    • 2022-10-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多