mysql - 优化 1.5m 条记录的 mysql 表,其中大部分被软删除

标签 mysql sql stored-procedures optimization myisam

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

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

在这 150 万条记录中,只有 30K 条记录没有被软删除。这意味着它们会被频繁访问,而其他记录则很少被访问,但在某些情况下确实如此。

因此该表被大量使用并查询未删除的记录,有时还查询软删除的记录。

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

表引擎是MyISAM。大多数其他表都是 InnoDB,但此表使用存储过程进行大量查询,当我更改为 InnoDB 时,查询速度要慢得多。

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

我想到的事情:

  • 分区,但我无法使用分区,因为某些列已建立FULL TEXT索引。
  • 将数据拆分为两个表。一种用于已删除的行,一种用于频繁访问和查询的未删除行。此更改需要大量基础设施更改,因此我并不急于执行此操作。
  • 创建一个新表,每 10/20 分钟与原始表同步一次,而不是拆分,并且仅包含未删除的行。这将需要对基础设施进行小的改动,而且维护也更加容易和安全。拆分成两个表可能会因查询失败而导致记录丢失,因为“DELETE”操作实际上会将行从一个表移动到另一个表,因此需要复杂的机制

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

我有 10.3.20-MariaDB 和 32GB RAM

最佳答案

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

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

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

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

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

坦率地说,我会拆分该表,以便删除的行位于第二个表中。这将使您的表大小减少 98%,并且可能会使查询运行得足够快,以至于您不再需要使用 MyISAM。

关于mysql - 优化 1.5m 条记录的 mysql 表,其中大部分被软删除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60030019/

相关文章:

java - 查询多对多关系中某个值的总和

sql - 如何在plsql中的case语句中使用OR合并多个案例

mysql - SQL 连接和多重计数(*)?

mysql - 从记录中检索字符串值并插入到另一列

mysql - 从 'SELECT' 存储过程返回 INT 值

mysql - WordPress 巨大的数据库大小

python - 如何最适合在网络服务器上运行的API检查其公共(public)可用性/状态

sql - 将多个变量传递到 PL/SQL 存储过程中的 WHERE 条件

mysql - 订单 View 添加不应该存在的项目

mysql - NodeJS -> 错误无法读取未定义的属性 'length'