SELECT DISTINCT非常慢

时间:2012-05-29 23:28:05

标签: sql performance sql-server-2008 distinct sql-optimization

我的查询执行时间为48秒,如下所示:

SELECT count(DISTINCT tmd_logins.userID) as totalLoginsUniqueLast30Days 
FROM tmd_logins
join tmd_users on tmd_logins.userID = tmd_users.userID 
where tmd_users.isPatient = 1 AND loggedIn > '2011-03-25' 
and tmd_logins.userID in 
    (SELECT userID as accounts30Days FROM tmd_users
    where isPatient = 1 AND created > '2012-04-29' AND computerID is null)

当我删除DISTINCT关键字时,它只需不到1秒钟,因此瓶颈似乎就在其中。

每次用户登录系统时,数据库都会向tmd_logins表添加一个条目。我试图获得所有用户的总数,这些用户是在给定时间段内创建并登录的患者,例如在过去30天内。

我尝试删除DISTINCT关键字并在语句中添加group by tmd_logins.userID,但性能问题仍然存在。

tmd_logins有大约300,000条记录,tmd_users大约有40,000条

有更好的方法吗?

1 个答案:

答案 0 :(得分:4)

您遇到的问题是执行计划。我的猜测是“in”子句可能会让人感到困惑。你可以试试:

SELECT count(DISTINCT tmd_logins.userID) as totalLoginsUniqueLast30Days 
FROM tmd_logins join
     tmd_users
     on tmd_logins.userID = tmd_users.userID join
     (SELECT distinct userID as accounts30Days
      FROM tmd_users
      where isPatient = 1 AND
            created > '2012-04-29' AND
            computerID is null
     ) t
     on tmd_logins.userID = t.accounts30Days
where tmd_users.isPatient = 1 AND
      loggedIn > '2011-03-25' 

这可能会也可能不会奏效。但是,我想知道查询本身的结构。似乎UserID在名为tmd_users的表中应该是不同的。如果是这样,那么您可以将所有条件包装成一个:

SELECT count(DISTINCT tmd_logins.userID) as totalLoginsUniqueLast30Days 
FROM tmd_logins join
     tmd_users
     on tmd_logins.userID = tmd_users.userID 
where tmd_users.isPatient = 1 AND
      loggedIn > '2011-03-25' and
      created > '2012-04-29' AND
      computerID is null

如果我的猜测是真的,那么这肯定会跑得更快。