使用row_number从查询中获取@@ rowcount的有效方法

Phi*_*ett 30 sql sql-server sql-server-2005

我使用SQL Server 2005中的row_number over()功能进行了一次昂贵的查询.在查询被分页时,我只返回这些记录的子列表.但是,我还想返回记录总数,而不仅仅是分页子集.有效地运行查询两次以获得计数是不可能的.

选择计数(*)也是不可能的,因为当我尝试这个时表现非常糟糕.

我真正喜欢的是@@ ROW_NUMBERROWCOUNT :-)

RBa*_*ung 36

与OVER(PARTITON BY ..)一起使用时,检查COUNT(*)聚合,如下所示:

    SELECT
     ROW_NUMBER() OVER(ORDER BY object_id, column_id) as RowNum
    , COUNT(*) OVER(PARTITION BY 1) as TotalRows
    , * 
    FROM master.sys.columns
Run Code Online (Sandbox Code Playgroud)

这是恕我直言,这是最好的方式,而无需做两个查询.


EBa*_*arr 36

多年来,一堆开发人员的汗水已经有效地分页结果集.然而,没有一个答案 - 这取决于你的用例.部分用例是有效地获取页面,部分是确定完整结果集中有多少行.很抱歉,如果我稍微偏离分页,但这两者在我的脑海里紧紧相连.

有很多策略,如果你有任何类型的数据量并且不适合用例,那么大多数策略都是不好的.虽然这不是一个完整的清单,但以下是一些选项......

单独运行 Count(*)

  • 运行一个单独的查询,执行一个简单的"从MyTable选择计数(*)"
  • 简单易用的小桌子
  • 对于未经过滤的大型表,您可以使用它,它可以是窄的,也可以是非聚集索引
  • 当你有一个复杂的WHERE/JOIN标准时会崩溃,因为运行WHERE/JOIN两次是很昂贵的.
  • 由于读取次数增加,因此会对广泛的索引进行分解.

结合ROW_Number() OVER()COUNT(1) OVER(PARTITION By 1)

  • 这是由@RBarryYoung提出的.它具有易于实现和非常灵活的优点.
  • 不利的一面是,有很多原因导致这种情况变得非常昂贵.
  • 例如,在我正在工作的DB中,有一个大约6000行的Media表.它不是特别宽,具有整数聚类PK,以及紧凑的唯一索引.然而,简单的COUNT(*) OVER(PARTITION BY 1) as TotalRows结果是大约12,000次读取.比较简单SELECT COUNT(*) FROM Media- 12读.Wowzers.

更新 - 我提到的读取问题有点红鲱鱼.事实证明,对于窗口函数,用于测量读取的单位是混合的.最终结果似乎是大量的读取.您可以在此处查看有关此问题的更多信息:为什么窗口聚合函数的逻辑读取如此之高?

临时表/表变量

  • 有许多策略采用结果集并将相关的键或结果段插入临时表/表变量.
  • 对于中小型结果集,这可以提供很好的结果.
  • 这种类型的策略几乎适用于任何SQL平台/版本.
  • 对结果集进行多次操作(通常是一项要求)也很容易.
  • 缺点是处理大型结果集时...将几百万行插入临时表会产生成本.
  • 使问题更加复杂的是,TempDB上的大量系统压力可能是一个很重要的因素,临时表在TempDB中有效运行.

高斯和/双行数

  • 这个想法依赖于数学家高斯想出的东西的子集(如何将一系列数字相加).子集是如何从表中的任何点获取行计数.
  • 从一系列数字(Row_Number())开始,1到N的行数是 (N + 1) - 1.链接中有更多解释.
  • 公式看起来好像只能用N,但如果你坚持使用公式,就会发生一些有趣的事情,你可以从表格中间的页面中找出行数.
  • 最终结果是ROW_Number() OVER(Order by ID),ROW_Number() OVER(Order by ID DESC) 然后将两个数相加并减去1.
  • 以我的Media表为例,我的读数从12,000降至约75.
  • 在较大的页面中,您最终会多次重复数据,但读取中的偏移量可能是值得的.
  • 我没有在太多情况下对此进行测试,因此在其他情况下它可能会崩溃.

顶部(@n)/ SET ROWCOUNT

  • 这些不是特定的策略本身,而是基于我们对查询优化器的了解进行优化.
  • 创造性地使用Top(@n)[top可以是SQL 2008中的变量]或SET ROWCOUNT可以减少您的工作集...即使您拉动结果集的中间页面,您仍然可以缩小结果范围
  • 由于查询优化器行为,这些想法起作用...服务包/修补程序可以改变行为(尽管可能不会).
  • 在certian实例中,SET ROWCOUNT可能有点准确
  • 此策略不考虑获取完整行数,只是使分页更有效

那么开发人员应该做些什么呢?

读我的好人,读.以下是我倾斜的一些文章......

希望有所帮助.