【问题标题】:MySQL queries still slow after deleting bunch of records删除一堆记录后 MySQL 查询仍然很慢
【发布时间】:2021-07-20 07:25:24
【问题描述】:

我需要一些帮助来解决一些 mysql 问题。自上周以来,我的网站一直运行缓慢,在联系我的主机后,我发现一些查询花费的时间太长,主要是因为表锁。 我是一名开发人员,但不是 mysql/数据库专家。我的主人建议我删除和/或将有问题的两个表更改为 innoDB。因此,由于这些表有很多垃圾数据,我决定删除一堆记录。我会说这两个表大约是这个问题开始时大小的 25%。 问题是,它仍然没有任何区别。 所以我的问题:

  1. 是否需要清除缓存或优化表才能看到 效果?我的主人仍然建议我将这些表更改为 innoDB 这很好,但我不知道为什么删除这么多记录 没有什么不同。
  2. 另外我读到最好 重新创建表而不仅仅是优化?如果需要,我可以聘请 数据库管理员来帮助我,但我想至少尝试一些 如果这很简单的话。有人可以指导我吗 通过这个。

要补充一点,它是一个运行在 php 5.4 和 mysql 5.6 上的遗留网站

这是锁定表的示例查询之一。

SELECT `m`.`message_id`, COUNT(`m`.`message_id`) AS `mails_count`, `m`.`sender_id`, `m`.`recipient_id`, 
            `m`.`text`, `m`.`is_readable`, `m`.`time_stamp` AS `last_message_ts`, `c`.`conversation_id`, `c`.*, `ms`.`is_replied`
            FROM `mailbox_conversation` AS `c` 
            INNER JOIN (
                SELECT * FROM `mailbox_message` 
                WHERE `recipient_id`=67404  AND IF (`sender_id`!=67404, `status`='a', 1) ORDER BY `time_stamp` DESC  
            ) AS `m` ON(`m`.`conversation_id`=`c`.`conversation_id`) 
            INNER JOIN (
                SELECT `conversation_id`, IF(`sender_id`=67404,'yes','no') AS `is_replied` FROM `mailbox_message` 
                WHERE (`recipient_id`=67404 OR `sender_id`=67404) ORDER BY `time_stamp` DESC 
            ) AS `ms` ON(`ms`.`conversation_id`=`c`.`conversation_id`)
            WHERE (`c`.`initiator_id`=67404 OR `interlocutor_id`=67404)
            AND `c`.`bm_deleted` NOT IN (IF(`c`.`initiator_id`=67404, '1, 3','2, 3'))           
             AND IF (`sender_id`!=67404, `status`='a', 1)
            GROUP BY `c`.`conversation_id`
            ORDER BY `m`.`time_stamp` DESC  LIMIT 0,15;

谢谢!

【问题讨论】:

  • 表锁不会影响选择查询,只会影响插入和更新。你在做插入和更新吗?您的代码实际上是在获取表锁吗?
  • 请发布您正在使用的查询以及该查询的执行计划。如果您不确定那是什么,请在此站点中搜索 MySQL 执行计划
  • @TimRoberts 我还没有编写该代码,所以不确定。从我在日志中看到的情况来看,主要是选择查询。
  • 还要补充一点,它是一个在 php 5.4 和 mysql 5.6 上运行的遗留网站
  • 如果您正在寻求优化数据库性能的帮助,而不是优化代码,那么您最好在 Database Administrators 上提问

标签: mysql sql innodb myisam


【解决方案1】:

以下是拖慢复杂查询的因素:

(1)

    GROUP BY  `c`.`conversation_id`
    ORDER BY  `m`.`time_stamp` DESC
    LIMIT  0,15;

如果它只能读取 15 行就好了。但这是不可能的,因为 GROUP BYORDER BY 不匹配。此外,它们涉及多个表,因此无需使用索引。 (INDEX 只能引用一个表。)

(2)

AND  IF (`sender_id`!=67404, `status`='a', 1)

(`recipient_id`=67404  OR  `sender_id`=67404)

(`c`.`initiator_id`=67404  OR  `interlocutor_id`=67404)

这两个都太复杂了,无法使用任何索引。 OR 是性能杀手;它有时可以变成UNION。 (但是你需要嵌套的UNIONs 来处理这里的所有事情。)如果可以写成sender_id = 67404 or status='a'——它不会更快,但它会更清晰(对我来说)。

一个案例:

( SELECT ... from mailbox_message WHERE `recipient_id`=67404 )
UNION ALL
( SELECT ... from mailbox_message WHERE `sender_id`=67404 )

需要UNIONINDEX(recipient_id)INDEX(sender_id)

(3)

JOIN ( SELECT ... )

这通常是不可优化的,尤其是当有多个这样的时候。

(4)

JOIN ( SELECT ... ORDER BY ... )

ORDER BY 将被忽略。参见ONLY_FULL_GROUP_BY

(5)

SELECT *

如果您最终不需要任何庞大的列,* 可能会降低一些性能。拼出所需的列。

【讨论】:

  • 谢谢。最初,我打开这张票是为了不更改查询,而是用我在帖子中提到的其他方法进行改进,但这有点像是一个创可贴,没有解决根本问题。感谢您提出更改建议。我会考虑这些。
  • @sayayin - 唉,我认为任何配置更改或任何索引都不会帮助该查询。在回答问题时,我会考虑索引、配置、重构、架构更改,甚至重新架构。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-06-05
  • 1970-01-01
  • 2019-06-14
  • 1970-01-01
  • 1970-01-01
  • 2019-04-21
  • 1970-01-01
相关资源
最近更新 更多