简体   繁体   English

MySQL 慢子查询,我应该使用JOIN吗?

[英]MySQL slow subquery, should I use JOIN?

I am tracking user events ( log in, log out, page load, etc) that happen on a website.我正在跟踪网站上发生的用户事件(登录、注销、页面加载等)。

I want to run a query that gets users that:我想运行一个查询,让用户:

  • are logged in已登录
  • haven't logged out没有登出
  • didn't log in more than 90 minutes ago超过 90 分钟前没有登录

In the example below I have created some data that should return just one logged in user with the user_id = 3 , because在下面的示例中,我创建了一些数据,这些数据应该只返回一个user_id = 3的登录用户,因为

  • user_id 1 has logged out user_id 1已注销
  • user_id 2 timed out user_id 2超时
  • user_id 3 logged in and hasn't timed out or manually logged out user_id 3已登录且未超时或手动注销

Assume the time now is 2021-02-24 12:15:00假设现在时间是 2021-02-24 12:15:00

id ID user_id用户身份 description描述 created_at created_at
19954 19954 3 3 log in登录 2021-02-24 12:00:00 2021-02-24 12:00:00
16085 16085 1 1 log out登出 2021-02-24 12:00:00 2021-02-24 12:00:00
11844 11844 2 2 log in登录 2021-02-24 10:00:00 2021-02-24 10:00:00
16850 16850 1 1 log in登录 2021-02-24 10:00:00 2021-02-24 10:00:00

My current query is this, but it runs really slowly.我目前的查询是这样的,但它运行得非常慢。

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

My indexes are as follows.我的索引如下。

PRIMARY基本的 BTREE BTREE TRUE真的 id ID
description_index描述索引 BTREE BTREE FALSE错误的 description描述
user_desc_created_index user_desc_created_index BTREE BTREE FALSE错误的 user_id,description,created_at user_id,描述,created_at
user_id_description_index user_id_description_index BTREE BTREE FALSE错误的 user_id,description用户 ID,描述

I think I might need a join rather than subquery but I'm not sure exactly how.我想我可能需要一个连接而不是子查询,但我不确定具体如何。 Could anyone lend a hand?有人可以帮忙吗?

You could try using joi with subqiery for max date group by user_id您可以尝试将 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

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

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