代码之家  ›  专栏  ›  技术社区  ›  Code Novice

Top与Rank/Row Number函数-哪个函数的性能更高?

  •  0
  • Code Novice  · 技术社区  · 4 年前

    我试图在谷歌上搜索在查询中使用Top与使用Ranking或Row_Number类型函数的成本。

    每种功能的成本是否取决于情况,或者这两种功能的价格是否可以在所有情况下全面确定?

    下面是一些模拟SQL,使用一个简单的CTE来演示我的问题,如下所示:

    WITH fData AS
    (
        SELECT 1 AS ID, 'John' AS fName, 'Black' AS lName, CAST('05/19/1975' AS DATE) AS birthDate UNION ALL
        SELECT 2 AS ID, 'John' AS fName, 'Black' AS lName, CAST('04/1/1989' AS DATE) AS birthDate UNION ALL
        SELECT 3 AS ID, 'John' AS fName, 'Black' AS lName, CAST('11/16/1995' AS DATE) AS birthDate UNION ALL
        SELECT 4 AS ID, 'John' AS fName, 'Black' AS lName, CAST('01/16/1968' AS DATE) AS birthDate UNION ALL
        SELECT 5 AS ID, 'John' AS fName, 'Black' AS lName, CAST('01/16/1968' AS DATE) AS birthDate
    )   
    
    /* Using TOP 1 vs Row_Number() - Uncomment this and comment the below to VIEW TOP version */
    --SELECT TOP 1 d.ID, d.fName, d.lName, d.birthDate
    --FROM fData d
    --ORDER BY d.birthDate
    
    /* Using the below vs TOP 1 */
    SELECT * FROM
    (   SELECT d.ID, d.fName, d.lName, d.birthDate, Row_Number() OVER (ORDER BY d.birthDate) AS ranker
        FROM fData d
    ) r
    WHERE r.ranker = 1
    

    当使用TOP时,不需要在它周围应用第二个Wrapping查询,它看起来更干净。在应用Row_Number或Ranking函数后,您必须将其包装以告诉查询您现在想要的是哪一行。。。通过应用WHERE ranker=1或ranker>=5以实现与TOP 1或TOP 5相同的效果。

    如果这是可以确定的,哪一个更好更快?

    0 回复  |  直到 4 年前
        1
  •  2
  •   Martin Smith    4 年前

    在您的示例中 TOP 在某种程度上更有效。

    的执行计划 顶部 在以下

    enter image description here

    这个 TOP N 排序方式 N=1 只需要跟踪最低的行 birthDate 它所看到的。

    对于row_number查询,它识别出行号始终是升序,并自己添加 TOP 1 计划,但它没有结合分离的 顶部 SORT 变成 TOP N Sort -所以它对所有5行进行了完整的排序。

    enter image description here

    如果索引按所需顺序提供行而不需要排序,则不会有太多行。row_number查询将有额外的几个运算符,这些运算符无论如何都相当便宜。

    当SQL Server具有TOP时,为什么在其中使用排名函数

    排名功能通常比 顶部

    对于两者都有效的情况,请考虑 顶部 是一种相当古老的专有语法,而不是标准SQL。在添加窗口功能之前,它在产品中已经存在了很长一段时间。如果您不应该使用可移植SQL 顶部

    尽管您可能也不使用排名函数。另一种(标准SQL)替代方案是

    SELECT d.ID, d.fName, d.lName, d.birthDate
    FROM fData d
    ORDER BY d.birthDate
    OFFSET 0 ROWS
    FETCH NEXT 1 ROW ONLY
    

    它给出了与相同的计划 顶部1