【问题标题】:MySQL slow subquery, should I use JOIN?MySQL慢子查询,我应该使用JOIN吗?
【发布时间】:2021-05-26 19:15:07
【问题描述】:

我正在跟踪网站上发生的用户事件(登录、注销、页面加载等)。

我想运行一个查询以获取以下用户:

  • 已登录
  • 尚未登出
  • 90 分钟前未登录

在下面的示例中,我创建了一些数据,应该只返回一个使用user_id = 3 登录的用户,因为

  • user_id 1 已登出
  • user_id 2 超时
  • user_id 3 已登录且未超时或手动注销

假设现在时间是 2021-02-24 12:15:00

id user_id description created_at
19954 3 log in 2021-02-24 12:00:00
16085 1 log out 2021-02-24 12:00:00
11844 2 log in 2021-02-24 10:00:00
16850 1 log in 2021-02-24 10:00:00

我当前的查询是这样的,但它运行得很慢。

SELECT DISTINCT(user_id), id, created_at
FROM events e1
WHERE id = (
            SELECT id
            FROM events e2
            WHERE e2.user_id = e1.user_id
            AND description IN ('log in', 'log out')
            ORDER BY created_at desc
            LIMIT 1
           )
AND description = 'log in'
AND created_at > NOW() - INTERVAL 90 MINUTE
ORDER BY created_at desc

我的索引如下。

PRIMARY BTREE TRUE id
description_index BTREE FALSE description
user_desc_created_index BTREE FALSE user_id,description,created_at
user_id_description_index BTREE FALSE user_id,description

我想我可能需要一个联接而不是子查询,但我不确定具体如何。有人可以帮忙吗?

【问题讨论】:

标签: mysql join subquery query-optimization


【解决方案1】:

您可以尝试将 joi 与 subqiery 一起用于 user_id 的最大日期组

SELECT DISTINCT user_id , id, created_at
FROM events e1 
INNER JOIN (
       select user_id, max(created_at) max_date
       from events 
       WHERE  description IN ('log in', 'log out')
       group by user_id 
) t1 
inner join events  t2 ON t1.user_id = t2.user_id and  t1.max_date = t2.created_at
WHERE t2-description = 'log in'
AND t2.created_at > NOW() - INTERVAL 90 MINUTE
ORDER BY t2.created_at desc

【讨论】:

  • 注意,DISTINCT 不是函数。
  • 这很好用。谢谢! 7000 毫秒到 35 毫秒 - 太棒了。
  • @scaisEdge 嗯,没有。你的意思是count(distinct user_id)?见db-fiddle.com/f/rYktE6CTZKHSVV8tKHmsx6/2
猜你喜欢
  • 1970-01-01
  • 2015-03-16
  • 1970-01-01
  • 2014-03-15
  • 1970-01-01
  • 2019-08-02
  • 1970-01-01
  • 2015-06-04
  • 1970-01-01
相关资源
最近更新 更多