【发布时间】:2018-07-23 14:12:27
【问题描述】:
我在 Galera 集群(3 个服务器)中有一个 MariaDB 表 subject_message_new,用于注册用户已阅读消息。我们有31000 用户和数百万条消息,所以表非常大(现在多达 150 万条记录)。如果更新消息,则必须删除所有带有$id_message 的读取条目。
用户还可以将消息复制到另一个主题,以便消息 ($id_message) 引用原始消息 (id_message_org),同时必须删除连接的原始消息中的 the-read-entry。
这是我的 MySQL 表:
Kolom Type Commentaar
id bigint(20) Auto nummering
id_message int(11)
id_subject int(11) NULL
nr_user int(11)
datetime datetime
Indexen
PRIMARY id
INDEX nr_user
INDEX id_message
INDEX id_subject
Foreign keys
id_message subject_message(id_message) CASCADE CASCADE
nr_user users(nr_user) CASCADE CASCADE
id_subject subject(id_subject) CASCADE CASCADE
我有一个在消息更改后调用的 PHP 函数
function message_new($id_message,$id_subject){
global $conn;
mysqli_query($conn,"DELETE FROM subject_message_new WHERE (id_message='$id_message' AND id_subject='$id_subject') OR id_message IN(SELECT id_message FROM subject_message WHERE id_message_org='$id_message')");
}
如果我将子查询拆分为2 x DELETE-查询,则需要2 x 6-12 秒...
此功能(查询)在生产中花费的时间太长,最长可达 6-12 秒。 有人可以给我建议如何调整吗?或者让它更好地工作?
【问题讨论】:
-
OR和IN都很贵
-
看看
EXPLAIN DELETE ...(见dev.mysql.com/doc/refman/5.6/en/explain.html)。这应该告诉你慢的部分在哪里 -
您的问题在于您的子选择。您必须找到一种方法来忽略它或优化它。首先,您需要确保“subject_message.id_message”被编入索引。然后为了清楚起见将它们分开。执行“OR”之前的所有内容,然后执行它之后的所有内容。然后我将专注于优化我的子选择(“OR”之后的查询)。尝试减少记录,添加索引等。确实,OR 和 IN 很昂贵,但并不禁止,您只是没有奢侈在查询中抛出任何您想要的东西,您实际上需要“彻底考虑并优化”它。
-
提示:DELETE 查询也可能受到 SQL 注入攻击,即所谓的基于时间的 SQL 注入(通过滥用 MySQL 的 SLEEP() 函数)
标签: php mysql query-optimization mariadb