【问题标题】:MySQL partitioning or deleting older data?MySQL 分区或删除旧数据?
【发布时间】:2020-07-25 04:01:52
【问题描述】:

我在 mySQL 上有一个最近的活动表,它的 MyISAM 包含大约 4600 万条记录。它已正确编入索引,并且所有这些都已完成。但有些查询仍然需要几秒钟的时间来执行。

所以我想知道,在这个数据库上提高查询性能的最佳方法是什么。我应该对表进行分区还是删除旧数据?我主要对这个月的数据进行一些计算来查询,另一个用途是向用户展示他们最近的活动,以及我们不得不不时手动监控他们的活动。

我一直在考虑删除所有早于今年的数据,这应该会删除大约 2400 万行。 (因为从本月初开始已经 4 个月了,所以旧的数据应该不那么重要了)。

或者我可以按月份进行分区,但我不知道在 laravel 中如何实现,我是否每次都必须更改分区才能获取比当前月份更早的数据?

编辑: 这 1 个查询是一个重要的查询,它是在用户的特定活动之后执行的,此特定查询需要 8 秒才能执行,并且使用 user_id 索引经过了 40,000 行。 如果它使用多个索引,将有助于我改进此查询,因为这样查询将被缩小到非常少的行。或者,如果我删除旧数据,那么完成计算所需的行数就会减少。

select  *
    from  `recent_activites`
    where  `id` > 20443580
      and  `user_id` = 20580
      and  `updated_at` > '2020-04-01 00:00:00'
      and  `type` in (?, ?, ?, ?, ?, ?, ?, ?, ?) ```

编辑: 询问 : 此查询在 1 次执行时花费了 8.72 毫秒,但似乎总是花费超过 1 毫秒 时间存在是因为它减少了行数

这些是索引

【问题讨论】:

  • 你也可以考虑在 laravel 中使用缓存想想 redis。
  • 是的,我也有很多缓存要做,但是这些数据必须经常更新。缓存运行得非常好,它使我们的 cpu 使用率从 50% 降低到 20%,但我仍然每 3 小时为用户更新一次。但是对于第一次数据刷新它仍然很慢
  • 您在此处公开的两种方法都可以使用,您也可以进行复制,但您应该考虑如果不是,则删除数据是否是个好主意,您有答案。你也可以重新考虑你的数据库设计,避免像连接这样的事情。这取决于您在此处尝试实现的目标,但您甚至可以使用多个数据库。也许你应该更具体
  • 我对分区没有直接经验,但我的一位 MySQL 专家同事说分区是邪恶的。我会改为使用复制或缓存解决方案。
  • 在您进行一般设置更改(除了从 MyISAM 移走)或删除您可能仍需要的数据之前,我会质疑您的前提 “它已被正确索引并且所有这些都已完成。”。例如。从您的描述和查询性能来看,听起来您只有单列索引,而您的给定查询需要复合索引,(user_id, updated_at) 可能就足够了。如果您需要这方面的帮助,您应该始终提供查询、表结构 (show create table ... ) 和执行计划(在查询前写上 explain )和时间。

标签: mysql laravel myisam


【解决方案1】:

您可以将一些数据移动到存档数据库,我的意思是将旧数据存储在单独的数据库(存档)中,并将实际数据存储在当前数据库中。在这种情况下,对于实际(新)数据和同时访问旧数据的可能性仍然很好。

要处理这个问题,您需要在 Laravel 系统中设置 2 个连接 - 在 config/database.php 中创建新连接。

现在您应该可以像这样访问您的存档数据了:

$archive_data = DB::connection('name_of_archive_connection')->table('table_name')->select('*')...
$actual_data = DB::connection('name_of_main_connection')->table('table_name')->select('*')...

您还可以通过插入/删除 mysql 函数(如上例)轻松地在数据库之间移动数据。

【讨论】:

    【解决方案2】:
    • 删除这么多表时,复制要保留的行会更快。
    • 您应该从 MyISAM 迁移到 InnoDB。
    • PARTITIONing 将有助于将来清除旧数据。
    • 添加PARTITIONing 将花费时间。任何删除旧数据的技术也是如此。哪个更重要?减少堵塞?或者完成任务的速度。
    • PARTITIONing 本身不会加快查询速度。但是,您似乎需要一个“二维”索引。
    • 进行分区时必须重新考虑索引。
    • 汇总表可能会显着提高性能。

    上述几个步骤可以同时完成——切换到 InnoDB、添加分区、删除旧数据、更改索引。 (汇总表是一项单独的任务。)我建议在处理您的实时系统之前进行试验。

    参考资料:

    【讨论】:

    • 我切换到 InnoDB,但现在我对这个表的查询速度变慢了。关于如何提高速度的任何想法?
    • 行数也减半,现在是 8800 万,现在增加到 4000 万。最后,还添加了 2D 和 3D 索引。还没有对数据库进行分区。我不认为汇总表会有帮助吗?因为我主要是想获取特定user_id的最后10行
    • @SahaabZahid - “特定 user_id 的最后 10 行”应该很快。如果没有,让我们看看查询。
    • 这需要 8.72 毫秒 select * from recent_activites where user_id = 326 and updated_at > '2020-08-26 16:59:25' order by id desc limit 10 I设置 updated_at 时间,因为由于索引,它减少了浏览的总行数,它动态更改为 1 个月前我将在主帖子中添加解释和查询的图像和索引
    • @SahaabZahid - (re Your Comment above) 有足够的差异,你应该开始一个新的问题。请包括SHOW CREATE TABLEEXPLAIN SELECT 等。省略“1 个月前”,除非它确实影响问题。请使用文字,而不是图片。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-14
    • 2010-11-26
    • 1970-01-01
    • 2021-12-17
    • 1970-01-01
    • 2020-05-31
    • 2019-05-13
    相关资源
    最近更新 更多