我有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条记录,查询花了很长时间,我不知道它是否成功。 :)
如何优化上述查询。此查询还会查找从不尝试登录的用户。
答案 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
的输出与两个查询进行比较。