我的查询是否存在选择中间行的效率问题?

时间:2019-04-05 22:00:57

标签: sql sql-server performance tsql

我正在尝试选择第3-5行:

SELECT * 
FROM Finance_User 
ORDER BY email DESC

我原来只有:

SELECT 
    ROW_NUMBER() OVER (ORDER BY email DESC) AS RowNum, * 
FROM 
    Finance_User 
WHERE 
    RowNum BETWEEN 3 AND 5

但这无效,因为RowNum是无效的列。

相反,我做了以下事情:

WITH OrderedUsers AS 
(
    SELECT 
        ROW_NUMBER() OVER (ORDER BY email DESC) AS RowNum, * 
    FROM 
        Finance_User
)
SELECT *  
FROM OrderedUsers 
WHERE RowNum BETWEEN 3 AND 5

这很好用。但是,我担心这可能会导致性能问题,因为它似乎是两次从表中选择?

2 个答案:

答案 0 :(得分:5)

带有CTE(或子查询)的

ROW_NUMBER()不会扫描表两次。但是,使用窗口功能可能会对RDBMS进行额外的处理。

您可以使用ORDER BY ... OFFSET ... FETCH ...(从SQL Server 2012开始可用)获得相同的结果,这些结果专门用于分页结果集:

SELECT *
FROM Finance_User
ORDER BY email DESC
OFFSET 2 ROWS FETCH NEXT 3 ROWS ONLY

从文档中:

  

我们建议您使用OFFSET和FETCH子句代替TOP子句来实现查询分页解决方案并限制发送到客户端应用程序的行数。

答案 1 :(得分:3)

您的查询很好。
WITH AS子句是Common Table Expression,这意味着此查询以后可以重用,并且在需要和可能的情况下应缓存。因此,“两次从表中选择”应该没有任何问题。

通过此查询可以获得相同的结果:

SELECT * from 
   (SELECT ROW_NUMBER() OVER (ORDER BY email DESC) AS RowNum, * FROM Finance_User) 
where RowNum between 3 and 5

最后,您始终可以检查执行计划并确保执行计划。