SqlSever分页查询,仅扫描一次表

数据库的分页查询通常由两个查询组成:数据库

select count(*) from Goods

函数

select *
from (
    select row_number() over(order by goodsId) as rowid, *
    from Goods
) as a
where rowid >= @pageSize * (@pageIndex - 1) + 1
and rowid <= @pageSize * @pageIndex

第一个查询,获取符合条件的记录总数,用于计算总页数。第二个查询获取指定页上的记录。测试

两个查询须要执行两次,也就是作两次表扫描,这对效率是极大的损失。能不能只作一次表扫描?
row_number()函数在作排名时,确定须要作一次表扫描,而排名完成后,确定是知道有多少条记录的,若是这个内部值能输出到外部给调用者使用,那么两个查询就能够合并为一个查询,且仅须要一次表扫描了。
通过研究,row_number()函数并无这个功能,可是同时发现 over()这个窗口函数既能够配合排名函数使用,也能够配合聚合函数使用。例如:优化

select count(*) over() as recordCount from Goods

那么,若是利用窗口函数over(),而后同时搭配row_number()排名函数和count()聚合函数,Sql Server的执行计划可否在内部自动优化为仅作一次表扫描?因而查询改成以下:spa

select *
from (
    select count(*) over() as recordTotalCount,
           row_number() over(order by goodsId) as rowid, 
           *
    from Goods
) as a
where rowid >= @pageSize * (@pageIndex - 1) + 1
and rowid <= @pageSize * @pageIndex    

通过测试,因为在同一个查询中,都使用了over()窗口函数,Sql Server在生成执行计划时,自动优化为仅进行一次表扫描了code

相关文章
相关标签/搜索