【发布时间】:2013-02-22 21:49:44
【问题描述】:
这个(为简单起见进行了修改)查询是更大查询的一部分,并与其他选择在日期上连接。但是,我已将此部分固定为狗慢。假设我有一个 UserLoginHistory-table 记录用户的每次登录。对于每个用户,我想要他们首次登录的日期。(稍后在查询中,我按 LogDate 分组以获取每天有多少首次登录。)
select
LogDate, --(this value is only date, no time)
UserId
from
UserLoginHistory ul
where
not exists
(
select
*
from
UserLoginHistory ulPrevious
where
ulPrevious.LogDate < ul.LogDate
and ul.UserId = ulPrevious.UserId
)
group by ul.LogDate, ul.UserId
显然不存在部分是慢的。但我不知道如何用更有效的方法来代替它。
使用较小的 UserLogHistory-count,性能没有问题。当我达到 15 000 左右时,它开始变慢。也许我应该将每天的结果批处理到另一个表中,但我想为这个查询找到一个更好的解决方案,因为那里应该有一个......
感谢您的宝贵时间!
【问题讨论】:
-
根据定义,NOT EXISTS 必须执行表扫描。调整其性能的关键是使必须扫描的关系尽可能小,最好是非聚集索引。在不知道您的表上存在哪些索引的情况下,无法提供更具体的建议。
-
在大多数情况下,这是
not in和left outer join where key is null之间的最佳方法:Aaron Bertrand has tested it。 -
性能问题往往与平台相关,您使用的是哪个数据库:SQL Server 还是 Sybase?你有什么索引? 15,000 行并不是很多,因此您的索引可能不是最佳的。
标签: sql performance tsql group-by not-exists