在SQL Server上进行分页查询时,通常是使用offset-fetch实现

select * from table_name order by keys offset begin_index rows fetch next counts rows only

当然也可以使用Top或者RowNum实现分页查询,但这里讨论的主要的是使用offset-fetch进行分页的情况。
一般来说,order by keys中的keys通常为主键,为了方便讨论,假设主键由一个字段组成(这也是大部分实际应用中的情况),暂不讨论由多个字段组成的主键,其实两种是没有本质差别的。
SQL Server中的主键默认使用聚簇索引 ,也设置使用非聚簇索引,具体资料可以阅读:Primary Key vs. Clustered Index 这篇文章
根据上面的讨论,本文的讨论具体内容为:使用offset-fetch语句进行分页查询并且order by的key是使用聚簇索引的主键的情况。
对于数据量较少的表来说,使用哪种分页查询的方式速度影响都不大,但是当表的数据量足够多时,且offset的位置较大时,直接使用文章开头给出的SQL语句进行查询会导致查询缓慢,并且offset的位置越靠后,查询速度越慢。初步推断为:SQL Server在执行该SQL语句时,从主键的起始位置开始,顺序遍历,直到遇到offset指定的位置。有知道SQLServer对该语句的实际执行过程的朋友能够说一声就更好了。
将SQL语句改为

select * from (select primary_key from table_name offset begin_index rows fetch next counts rows only) as t inner join table_name

可以有效提高查询速度。以下简单分析下为何会修改后的SQL语句查询速度更快的原因,仅提供参考,不代表绝对正确,希望有朋友指正。

SQL1:

(select primary_key from table_name offset begin_index rows fetch next counts rows only)

以上语句SQL1:除了查询的字段与文章开头SQL语句不一致外,其他部分是一致的。通过指定查询的字段为主键,且主键是有索引的,又是根据主键进行排序来分页的,因此,可以合理的认为该查询能够通过索引快速定位到要查询的主键的位置,得到符合条件的主键。
然后将查询出来的主键与表进行连接查询,相当于指定了要查询数据的主键,可以通过索引快速定位到数据并读取出来。也就是将原来的顺序读取改为通过两次索引直接读取的方式,来加快查询速度。
在后续查找资料时发现,文章Pagination with OFFSET / FETCH : A better way也提出了类似的方法,并且提供了测试的结果和更详细的分析,感兴趣的朋友可以看看。
不过,总体思路都是利用索引进行优化。