SQL查询从两个相当大的表中进行选择

时间:2013-05-24 10:19:50

标签: mysql sql

我有2张桌子: 1)存储用户凭证的用户。它拥有1000多个用户记录。

  

ID | NAME |密码| USERTYPEID

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

  

ID | NAME | DATEOFLOGIN | USERID | LOGINTYPE

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

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条记录,查询花了很长时间,我不知道它是否成功。 :)

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

2 个答案:

答案 0 :(得分:0)

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

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

答案 1 :(得分:0)

这相当于您的查询,但LEFT JOIN NULL检查通常比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的输出与两个查询进行比较。