繁体   English   中英

MySQL 删除一堆记录后查询仍然很慢

[英]MySQL queries still slow after deleting bunch of records

我需要一些帮助来解决一些 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;

谢谢!

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

(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 )

UNION需要: INDEX(recipient_id)INDEX(sender_id)

(3)

JOIN ( SELECT ... )

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

(4)

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

ORDER BY将被忽略。 ONLY_FULL_GROUP_BY

(5)

SELECT *

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM