优化 mysql table 1.5m 记录,其中大部分被软删除

optimizing mysql table with 1.5m records where most are soft deleted

我有一个 MySQL table 大约有 150 万条记录,table 大小为 1.3GB

我在 table 中使用软删除机制,这意味着我有一个列 deleted_at 指示该行是否已被删除以及何时删除。如果记录没有被删除那么 deleted_at 值为 NULL

在这150万条记录中,只有3万条没有被软删除。这意味着它们经常被访问,而其他记录几乎不被访问,但在某些情况下它们是。

所以这个 table 被大量使用并查询 none 已删除的记录,有时还查询软删除的记录。

我有 deleted_at 记录的 BTREE 索引类型(基数为 35K)。 table 随着时间的推移变得越来越重,显然它不是一个可扩展的解决方案。

table 引擎是 MyISAM。大多数其他 table 都是 InnoDB,但是这个 table 被 STORED PROCEDURE 大量查询,当我更改为 InnoDB 时,查询速度变慢了。

我正在寻找不涉及硬件更改的解决方案。当前的硬件足以让 table 获得良好的性能,但是一旦 table 增长得更多,情况就不会如此了。

我想到的事情:

我还有哪些其他选择?我可以优先考虑 table 和 MySQL 中的某些行吗?内存明智。

我有 10.3.20-MariaDB 和 32GB 内存

MyISAM 不缓存行,它只缓存索引。它依赖于文件系统缓存来缓冲行。

因此您可以尝试确保至少将索引完全加载到缓存中:

  1. 增加 key_buffer_size,使其至少与此 table 的 MyISAM 索引一样大。使用 SHOW TABLE STATUS 找出索引大小。
  2. 如果您有多个 MyISAM table,您可能需要专门为此 table 提供一个密钥缓存。参见 CACHE INDEX
  3. 在启动时将索引预加载到键缓存中。参见 LOAD INDEX INTO CACHE

您可能还想考虑为您的查询量身定制的多列索引。就像如果您有一个查询 WHERE user_id = 1234 AND deleted_at IS NULL,您应该在 (user_id, deleted_at) 上创建一个索引。

您需要哪些索引取决于您要优化的查询。

坦率地说,我会拆分 table 所以删除的行在一秒钟内 table。这将使您的 table 大小减少 98%,并且可能使查询 运行 足够快,以至于您不再需要使用 MyISAM。