代码之家  ›  专栏  ›  技术社区  ›  user2337270

在一个有3000万行的MySQL 5.7.X表中高效地删除条目?

  •  0
  • user2337270  · 技术社区  · 4 年前

    我是SQL新手,需要一些帮助。我有一个MySQL 5.7.X表,用于日志条目。每个日志条目都包含一个系统实体的ID和一些其他crud。目前,该表中大约有3000万行。另一个表保存不同类型的记录,但ID是相同的。例如:

    Table A
    +----------------+
    | ID | Timestamp |
    +----------------+
    + 1  | 2022-...  +
    +----------------+
    
    Table B
    +------------------------------+
    | ID | Timestamp | Logger_name |
    +------------------------------+
    | 1  | 2022-...  + XYZ         |
    +------------------------------+
    

    上面的表B是目前大约有3000万行的表。我想做的是“从表B中删除ID在表A中找不到的所有行”。我们已经使用DELETE尝试过,但这需要很长时间,并且在此期间应用程序被阻止。我读过类似CTAS的方法,以及结合ALTER命令移动行的方法,但问题是,在该操作期间,两个表都需要保持联机和活动状态。

    表B的“行删除”将从Kubernetes中的计划Cron作业中完成,因此肯定会有多个线程/进程向这两个表进行写入/读取。我认为不存在外键约束或索引。

    编辑:

    由于公司政策的原因,我无法公布所有表格的详细信息。表A在任何给定的时间都可能有几百行。表B几乎肯定会有数百万行。对于表A,ID是主键。表B没有显式主键。我猜作为列出的第一列的ID将是主键?在这两种情况下,InnoDB都是引擎。我不认为我们在任何地方都明确使用MyISAM。

    我知道登录数据库并不理想,这也不是我的选择。但我暂时还是坚持这个解决方案,需要充分利用它。

    1 回复  |  直到 4 年前
        1
  •  1
  •   Nick Bailey    4 年前

    如果表A的规模要小得多,你可以从表A中获取所有记录,获得所有id的列表,以某种格式(CSV等)保存,然后编写一个脚本,在列表上循环并删除与每个id匹配的记录 DELETE 查询这样,在删除过程中就不应该锁定任何一个表。

    更一般地说,这是一个很好的例子,说明了为什么日志数据永远不应该进入应用程序数据库。有很多很棒的日志聚合器,即使你不想使用其中的一个,也可以将日志推送到某种外部数据存储中,防止它们膨胀应用程序数据库的大小。