MySQL 删除一堆记录后查询仍然很慢
MySQL queries still slow after deleting bunch of records
我需要一些帮助来解决一些 mysql 问题。自上周以来,我的网站一直 运行 缓慢,在联系我的主机后,我发现一些查询花费的时间太长,主要是因为 table 锁定。
我是一名开发人员,但不是 mysql/database 专家。我的主人建议我删除 and/or 将有问题的两个 table 更改为 innoDB。因此,由于这些 table 有很多垃圾数据,我决定删除一堆记录。我会说这两个 table 大约是这个问题开始时大小的 25%。
问题是,它仍然没有任何区别。
所以我的问题:
- 我是否需要清除缓存或优化 table 才能看到
影响?我的主人仍然建议我将那些 tables 更改为 innoDB
这很好,但我不确定为什么要删除那么多记录
没有影响。
- 我也读到最好
重新创建 table 而不仅仅是优化?如果需要我可以雇一个
数据库管理员帮助我,但我想至少尝试一些
如果这是简单的事情。有人可以指导我吗
通过这个。
还有一件重要的事情要补充,它是 运行 在 php 5.4 和 mysql 5.6
上的遗留网站
这是锁定 table.
的示例查询之一
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 BY
和 ORDER BY
不匹配。此外,它们涉及多个 table,从而消除了使用索引。 (一个 INDEX
只能引用一个 table。)
(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 *
如果有任何您最终不需要的庞大列,*
可能会降低一些性能。拼出所需的列。
我需要一些帮助来解决一些 mysql 问题。自上周以来,我的网站一直 运行 缓慢,在联系我的主机后,我发现一些查询花费的时间太长,主要是因为 table 锁定。 我是一名开发人员,但不是 mysql/database 专家。我的主人建议我删除 and/or 将有问题的两个 table 更改为 innoDB。因此,由于这些 table 有很多垃圾数据,我决定删除一堆记录。我会说这两个 table 大约是这个问题开始时大小的 25%。 问题是,它仍然没有任何区别。 所以我的问题:
- 我是否需要清除缓存或优化 table 才能看到 影响?我的主人仍然建议我将那些 tables 更改为 innoDB 这很好,但我不确定为什么要删除那么多记录 没有影响。
- 我也读到最好 重新创建 table 而不仅仅是优化?如果需要我可以雇一个 数据库管理员帮助我,但我想至少尝试一些 如果这是简单的事情。有人可以指导我吗 通过这个。
还有一件重要的事情要补充,它是 运行 在 php 5.4 和 mysql 5.6
上的遗留网站这是锁定 table.
的示例查询之一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 BY
和 ORDER BY
不匹配。此外,它们涉及多个 table,从而消除了使用索引。 (一个 INDEX
只能引用一个 table。)
(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 *
如果有任何您最终不需要的庞大列,*
可能会降低一些性能。拼出所需的列。