在SELECT查询中使用TOP 1的性能影响

时间:2009-09-16 20:43:42

标签: sql sql-server tsql

我有一个User表,其中有Username和Application列。用户名可能重复,但用户名+应用程序的组合是唯一的,但我没有在表上设置唯一约束(性能)

问题::

之间是否存在任何差异(性能方面)
SELECT * FROM User where UserName='myuser' AND Application='myapp'

AND -

SELECT TOP 1 * FROM User where UserName='myuser' AND Application='myapp'

由于Username + Application的组合是唯一的,因此两个查询总是返回不超过一条记录,因此TOP 1不会影响结果。我一直认为添加TOP 1会真正加快速度,因为sql server会停止查找它找到一个匹配,但我最近在一篇文章中读到使用TOP实际上会减慢速度并且建议避免,尽管它们没有解释了原因。

有任何意见吗?

谢谢! 安德烈

4 个答案:

答案 0 :(得分:17)

如果结果中有多行且没有ORDER BY子句,则“TOP 1”会为服务器保存 ton 的工作。如果有一个order by子句,服务器仍然必须实现整个结果集,如果只有一行,它实际上并没有改变任何东西。

答案 1 :(得分:14)

使用top可能会产生一些性能差异,但使用索引可以获得真正的性能。

如果您有UserName和Application字段的索引,则数据库甚至不必触及该表,直到它隔离了单个记录。此外,它已经从表统计中知道值是唯一的,因此使用top没有区别。

答案 2 :(得分:5)

我认为这取决于SQL生成的查询执行计划...在过去的SQL Server早期版本中,我已经看到使用多余的“TOP”可以为具有许多连接的复杂查询提供明确的性能优势。但绝对不是在所有情况下。

我想我能给出的最好的建议是逐个尝试。

答案 3 :(得分:2)

你说你没有强制执行约束,转换为(UserName,Application)或(Application,UserName)上没有唯一索引。查询是否可以使用在UserNameApplication上搜索的访问路径?换句话说,这两列中的任何一列都被索引了吗?如果是,那么计划将选择索引最具选择性的一个并进行范围扫描,如果索引是非聚集的,可能是带书签查找的嵌套循环,然后是过滤器。在匹配第一个过滤器后,前1将停止查询,但这是否有所不同取决于数据的基数(范围扫描找到多少记录以及满足过滤器的数量)。

如果没有索引,则无论如何都会执行完整的群集扫描。 Top 1将在第一场比赛时停止扫描,无论是在处理1记录之后还是在处理999 mil之后。记录以实际用户名和应用程序为准......

唯一可以产生真正的差异的是允许查询对两个值进行搜索,即。有覆盖指数。约束将通过这样的覆盖索引来实施。换句话说:通过关闭约束,大概是为了写性能,准备在读取时付出代价。这读得很重要吗?您是否进行了任何测量以确认约束的额外索引写入会严重抑制性能?