select mt.from_user, mt.to_user, mt.group_id, g.name, g.created_by as adminuser,
msg.*,
(
SELECT id
from messages
where t.thread_id = thread_id
and id NOT IN (
SELECT message_id from message_deleted
where user_id=275 and status='deleted' )
order by CreatedDate DESC
limit 1
) as msgid,
(
SELECT CreatedDate
from messages
where t.thread_id = thread_id
and id NOT IN (
SELECT message_id from message_deleted
where user_id=275 and status='deleted' )
order by CreatedDate DESC
limit 1
) as msgDate
from user_thread as t
left join message_thread as mt ON t.thread_id = mt.id
left join group_master as g ON mt.group_id = g.id
left join group_member as gm ON gm.group_id = g.id
left join messages as msg ON t.thread_id = msg.thread_id
where ( gm.user_id=275
or msg.from_id=275
or msg.to_id=275
)
and t.status = 'Active'
group by mt.id
order by msgDate DESC
大约需要50秒。
在上面的代码中,我尝试拆分上面的查询并注意下面的子查询需要花费太多时间来执行。我可以将子查询转换为连接。请帮我。我被卡住了。请注意,所有连接的表都是必需的。
(
SELECT id
from messages
where t.thread_id = thread_id
and id NOT IN (
SELECT message_id from message_deleted
where user_id=275 and status='deleted' )
order by CreatedDate DESC
limit 1
) as msgid,
(
SELECT CreatedDate
from messages
where t.thread_id = thread_id
and id NOT IN (
SELECT message_id from message_deleted
where user_id=275 and status='deleted' )
order by CreatedDate DESC
limit 1
) as msgDate
答案 0 :(得分:0)
首先,您正在滥用臭名昭着的MySQL扩展GROUP BY
。这可能会导致您的结果无法预测。读这个。 https://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html
其次,您有几个嵌套的从属子查询。第一个就是这个。
(select id
from messages
where t.thread_id = thread_id
and id NOT IN (select message_id
from message_deleted
where user_id=275
and status='deleted')
order by CreatedDate DESC limit 1) as msgid
这种嵌套的从属子查询表现非常糟糕。当它们包含LIMIT
条款时,它们会更糟糕。修复此问题的途径是重构为独立查询,然后加入它。
这可以作为查询的替代,以在线程上找到最新的未删除消息。
SELECT MAX(m.id) id, m.thread_id
FROM messages m
LEFT JOIN message_deleted d
ON m.id = d.id
AND d.user_id = 275
AND d.status = 'deleted'
WHERE d.id IS NULL
GROUP BY m.thread_id
这使用LEFT JOIN .... IS NULL
模式代替NOT IN
。它更快。它使用MAX(id)
方法在表中查找最近的行来代替ORDER BY CreatedDate DESC LIMIT 1
方法,这也快得多。这很好,因为它保证每thread_id
个值生成0或1行。这意味着您可以在LEFT JOIN ... ON ... thread_id
操作中使用它,而不是在结果集中添加任何行。
您可以通过运行它来测试此子查询。然后你将它加入到查询的其余部分,就像它是一个表一样,就像这样。
SELECT whatever,
q.id, r.CreatedDate
FROM whatever
LEFT JOIN (
SELECT MAX(m.id) id, m.thread_id
FROM messages m
LEFT JOIN message_deleted d
ON m.id = d.id
AND d.user_id = 275
AND d.status = 'deleted'
WHERE d.id IS NULL
GROUP BY m.thread_id
) q ON q.id = t.id
LEFT JOIN messages r ON r.id = q.id
此处的第二个LEFT JOIN
操作用于从消息表中检索最新的未删除消息的CreatedDate
值。