Sql server 获取记录子集以及记录总数

Sql server 获取记录子集以及记录总数,sql-server,sql-server-2008,Sql Server,Sql Server 2008,我正在从SQLServer2008返回一个记录集以进行分页。我一次只返回15条记录,但我需要有匹配的总数以及记录的子集。我使用了两个不同的查询,结果是混合的,这取决于我需要在较大的组中提取子集的位置。以下是一个示例: SET NOCOUNT ON; WITH tempTable AS ( SELECT FirstName , LastName , ROW_NUMBER() OVER(ORDER BY FirstName ASC) AS RowNumber

我正在从SQLServer2008返回一个记录集以进行分页。我一次只返回15条记录,但我需要有匹配的总数以及记录的子集。我使用了两个不同的查询,结果是混合的,这取决于我需要在较大的组中提取子集的位置。以下是一个示例:

SET NOCOUNT ON;
WITH tempTable AS (
  SELECT
     FirstName
     , LastName
     , ROW_NUMBER() OVER(ORDER BY FirstName ASC) AS RowNumber 
   FROM People
   WHERE 
      Active = 1
)

SELECT 
   tempTable.*     
   , (SELECT Max(RowNumber) FROM tempTable) AS Records    
FROM tempTable     
WHERE
   RowNumber >= 1
   AND RowNumber <= 15
ORDER BY
   FirstName
当我返回匹配的低端项目时,这个查询运行得非常快,比如记录1到15。然而,当我开始返回记录1000-1015时,处理时间将从不到一秒增加到15秒以上

因此,我将查询改为以下内容:

SET NOCOUNT ON;
WITH tempTable AS (
  SELECT * FROM (
     SELECT
        FirstName
        , LastName
        , ROW_NUMBER() OVER(ORDER BY FirstName ASC) AS RowNumber 
        , COUNT(*) OVER(PARTITION BY NULL) AS Records
      FROM People
      WHERE 
         Active = 1
   ) derived
   WHERE RowNumber >= 1 AND RowNumber <= 15
)

SELECT 
   tempTable.*     
FROM tempTable     
ORDER BY
   FirstName
该查询在2-3秒内运行高位返回,但也在2-3秒内运行低位查询。因为它对70000+行中的每一行进行计数,所以它使每个请求花费的时间更长,而不仅仅是大的行数

因此,我需要弄清楚如何获得一个好的行计数,以及在结果集中的任何一点上只返回项目的子集,而不会遭受如此巨大的惩罚。我可以为高行数处理2-3秒的惩罚,但15太多了,我不愿意在一个人浏览的前几页上承受缓慢的加载


注意:我知道在第二个例子中我不需要CTE,但这只是一个简单的例子。在生产中,我在将诱惑过滤到我需要的15行之后,在诱惑上做进一步的连接。

我过去处理过一种类似的情况,不费心确定确切的行数,但使用查询计划给我一个估计的行数,有点像此链接中的第一项所描述的:

其目的是在900-915范围内传递所请求的任何行,然后返回估计的行数,如

rows 900-915 of approx. 990
这避免了计算所有行。一旦用户移动到该点之外,我就显示了

rows 1000-1015 of approx. 1015

i、 e.只需将最后一行作为我的新估算。

以下是我所做的工作,无论我返回哪些记录,速度都一样快:

--Parameters include:
@pageNum int = 1,
@pageSize int = 0,



DECLARE 
    @pageStart int,
    @pageEnd int

SELECT
    @pageStart = @pageSize * @pageNum - (@pageSize - 1),
    @pageEnd = @pageSize * @pageNum;


SET NOCOUNT ON;
WITH tempTable AS (
    SELECT
        ROW_NUMBER() OVER (ORDER BY FirstName ASC) AS RowNumber,
        FirstName
        , LastName
    FROM People
    WHERE Active = 1
)

SELECT
    (SELECT COUNT(*) FROM tempTable) AS TotalRows,
    *
FROM tempTable
WHERE @pageEnd = 0
OR RowNumber BETWEEN @pageStart AND @pageEnd
ORDER BY RowNumber

很确定这就是问题所在。RowNumber是一个派生列,因此没有索引,而COUNT*可以使用索引+1.你搞定了。。。处理时间从15-20秒缩短到不到1秒。谢谢:-很遗憾,这不会考虑搜索条件。另请参阅。