0

我有 2 个表:1)存储用户凭据的用户。它拥有超过 1000 条用户记录。

身份证 | 姓名 | 密码 | 用户类型ID

2) 捕获登录详细信息的 user_logs。它相当大,即超过100000条记录。

身份证 | 姓名 | 登录日期 | 用户名 | 登录类型

我必须找到在两个给定日期和他们上次登录日期之间不访问系统的用户。

SELECT MAX(userlogs.dateoflogin) AS lastlogindate,
       u1.id AS Id,
       u1.name AS Name
FROM USER u1
LEFT OUTER JOIN user_logs userlogs ON u1.id = userlogs.userid
WHERE u1.id NOT IN
    ( SELECT userid
     FROM user_logs userlogs2
     WHERE userlogs2.logtype='Login'
       AND userlogs2.dateoflogin BETWEEN '2013-05-10' AND '2013-05-20'
       AND userlogs2.userid IS NOT NULL)
GROUP BY u1.id;

如果表包含较小的记录,那么它工作得很好。但是在用户表有超过 1000 条记录和 user_logs 表有超过 100000 条记录的实时系统中,查询花费了很长时间,我不知道它是否成功。:)

如何优化上述查询。此查询还查找从未尝试登录的用户。

4

2 回答 2

0

首先,如果要提高性能,则需要修改该子查询。它们很方便,但它们往往会显着减慢查询速度。

其次,确保在 WHERE 子句中的所有列上都有索引。

于 2013-05-24T10:34:45.267 回答
0

这相当于您的查询,但LEFT JOIN带有NULL检查的 a 通常比NOT IN.

SELECT MAX(userlogs.dateoflogin) as lastlogindate , u1.id as Id , u1.name as Name
FROM user  u1
LEFT OUTER JOIN user_logs userlogs ON u1.id = userlogs.userid 
LEFT OUTER JOIN (SELECT distinct userid
                 FROM user_logs  
                 WHERE logtype='Login' 
                 AND dateoflogin BETWEEN '2013-05-10' AND '2013-05-20' 
                 AND userid IS NOT null) userlogs2 ON u1.id = userlogs2.userid
WHERE userlogs2.userid IS NULL
GROUP BY u1.id

确保您有一个索引,dateoflogin以便子查询能够正常执行。

比较EXPLAIN两个查询的输出。

于 2013-05-24T10:42:40.270 回答